cgcpu.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the code generator for the i386
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. cgbase,cgobj,cg64f32,cgx86,
  24. aasmbase,aasmtai,aasmcpu,
  25. cpubase,parabase,cgutils,
  26. symconst
  27. ;
  28. type
  29. tcg386 = class(tcgx86)
  30. procedure init_register_allocators;override;
  31. { passing parameter using push instead of mov }
  32. procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : tcgpara);override;
  33. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : tcgpara);override;
  34. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : tcgpara);override;
  35. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : tcgpara);override;
  36. procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);override;
  37. procedure g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);override;
  38. procedure g_exception_reason_save(list : taasmoutput; const href : treference);override;
  39. procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aint);override;
  40. procedure g_exception_reason_load(list : taasmoutput; const href : treference);override;
  41. end;
  42. tcg64f386 = class(tcg64f32)
  43. procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);override;
  44. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
  45. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);override;
  46. procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);override;
  47. private
  48. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  49. end;
  50. implementation
  51. uses
  52. globals,verbose,systems,cutils,
  53. paramgr,procinfo,
  54. rgcpu,rgx86;
  55. function use_push(const cgpara:tcgpara):boolean;
  56. begin
  57. result:=assigned(cgpara.location) and
  58. (cgpara.location^.loc=LOC_REFERENCE) and
  59. (cgpara.location^.reference.index=NR_STACK_POINTER_REG);
  60. end;
  61. procedure Tcg386.init_register_allocators;
  62. begin
  63. inherited init_register_allocators;
  64. if cs_create_pic in aktmoduleswitches then
  65. rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP,RS_EBX])
  66. else
  67. rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
  68. rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
  69. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_XMM0,RS_XMM1,RS_XMM2,RS_XMM3,RS_XMM4,RS_XMM5,RS_XMM6,RS_XMM7],first_mm_imreg,[]);
  70. rgfpu:=Trgx86fpu.create;
  71. end;
  72. procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const cgpara : tcgpara);
  73. var
  74. pushsize : tcgsize;
  75. begin
  76. check_register_size(size,r);
  77. if use_push(cgpara) then
  78. begin
  79. cgpara.check_simple_location;
  80. pushsize:=int_cgsize(cgpara.alignment);
  81. list.concat(taicpu.op_reg(A_PUSH,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
  82. end
  83. else
  84. inherited a_param_reg(list,size,r,cgpara);
  85. end;
  86. procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const cgpara : tcgpara);
  87. var
  88. pushsize : tcgsize;
  89. begin
  90. if use_push(cgpara) then
  91. begin
  92. cgpara.check_simple_location;
  93. pushsize:=int_cgsize(cgpara.alignment);
  94. list.concat(taicpu.op_const(A_PUSH,tcgsize2opsize[pushsize],a));
  95. end
  96. else
  97. inherited a_param_const(list,size,a,cgpara);
  98. end;
  99. procedure tcg386.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const cgpara : tcgpara);
  100. procedure pushdata(paraloc:pcgparalocation;ofs:aint);
  101. var
  102. pushsize : tcgsize;
  103. tmpreg : tregister;
  104. href : treference;
  105. begin
  106. if not assigned(paraloc) then
  107. exit;
  108. if (paraloc^.loc<>LOC_REFERENCE) or
  109. (paraloc^.reference.index<>NR_STACK_POINTER_REG) or
  110. (tcgsize2size[paraloc^.size]>sizeof(aint)) then
  111. internalerror(200501162);
  112. { Pushes are needed in reverse order, add the size of the
  113. current location to the offset where to load from. This
  114. prevents wrong calculations for the last location when
  115. the size is not a power of 2 }
  116. if assigned(paraloc^.next) then
  117. pushdata(paraloc^.next,ofs+tcgsize2size[paraloc^.size]);
  118. { Push the data starting at ofs }
  119. href:=r;
  120. inc(href.offset,ofs);
  121. if tcgsize2size[paraloc^.size]>cgpara.alignment then
  122. pushsize:=paraloc^.size
  123. else
  124. pushsize:=int_cgsize(cgpara.alignment);
  125. if tcgsize2size[paraloc^.size]<cgpara.alignment then
  126. begin
  127. tmpreg:=getintregister(list,pushsize);
  128. a_load_ref_reg(list,paraloc^.size,pushsize,href,tmpreg);
  129. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
  130. end
  131. else
  132. list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[pushsize],href));
  133. end;
  134. var
  135. len : aint;
  136. href : treference;
  137. begin
  138. { cgpara.size=OS_NO requires a copy on the stack }
  139. if use_push(cgpara) then
  140. begin
  141. if tcgsize2size[cgpara.size]<>tcgsize2size[size] then
  142. internalerror(200501161);
  143. { Record copy? }
  144. if (cgpara.size=OS_NO) then
  145. begin
  146. cgpara.check_simple_location;
  147. len:=align(cgpara.intsize,cgpara.alignment);
  148. g_stackpointer_alloc(list,len);
  149. reference_reset_base(href,NR_STACK_POINTER_REG,0);
  150. g_concatcopy(list,r,href,len);
  151. end
  152. else
  153. begin
  154. { We need to push the data in reverse order,
  155. therefor we use a recursive algorithm }
  156. pushdata(cgpara.location,0);
  157. end
  158. end
  159. else
  160. inherited a_param_ref(list,size,r,cgpara);
  161. end;
  162. procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;const cgpara : tcgpara);
  163. var
  164. tmpreg : tregister;
  165. opsize : topsize;
  166. begin
  167. with r do
  168. begin
  169. if (segment<>NR_NO) then
  170. cgmessage(cg_e_cant_use_far_pointer_there);
  171. if use_push(cgpara) then
  172. begin
  173. cgpara.check_simple_location;
  174. opsize:=tcgsize2opsize[OS_ADDR];
  175. if (base=NR_NO) and (index=NR_NO) then
  176. begin
  177. if assigned(symbol) then
  178. list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
  179. else
  180. list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
  181. end
  182. else if (base=NR_NO) and (index<>NR_NO) and
  183. (offset=0) and (scalefactor=0) and (symbol=nil) then
  184. list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
  185. else if (base<>NR_NO) and (index=NR_NO) and
  186. (offset=0) and (symbol=nil) then
  187. list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
  188. else
  189. begin
  190. tmpreg:=getaddressregister(list);
  191. a_loadaddr_ref_reg(list,r,tmpreg);
  192. list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
  193. end;
  194. end
  195. else
  196. inherited a_paramaddr_ref(list,r,cgpara);
  197. end;
  198. end;
  199. procedure tcg386.g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);
  200. var
  201. stacksize : longint;
  202. begin
  203. { Release PIC register }
  204. if cs_create_pic in aktmoduleswitches then
  205. list.concat(tai_regalloc.dealloc(NR_PIC_OFFSET_REG,nil));
  206. { MMX needs to call EMMS }
  207. if assigned(rg[R_MMXREGISTER]) and
  208. (rg[R_MMXREGISTER].uses_registers) then
  209. list.concat(Taicpu.op_none(A_EMMS,S_NO));
  210. { remove stackframe }
  211. if not nostackframe then
  212. begin
  213. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  214. begin
  215. stacksize:=current_procinfo.calc_stackframe_size;
  216. if (stacksize<>0) then
  217. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
  218. end
  219. else
  220. list.concat(Taicpu.op_none(A_LEAVE,S_NO));
  221. list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG,nil));
  222. end;
  223. { return from proc }
  224. if (po_interrupt in current_procinfo.procdef.procoptions) then
  225. begin
  226. if (current_procinfo.procdef.funcretloc[calleeside].loc<>LOC_VOID) and
  227. (current_procinfo.procdef.funcretloc[calleeside].loc=LOC_REGISTER) then
  228. list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
  229. else
  230. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EAX));
  231. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EBX));
  232. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ECX));
  233. if (current_procinfo.procdef.funcretloc[calleeside].loc=LOC_REGISTER) and
  234. (current_procinfo.procdef.funcretloc[calleeside].size in [OS_64,OS_S64]) then
  235. list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
  236. else
  237. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
  238. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ESI));
  239. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDI));
  240. { .... also the segment registers }
  241. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  242. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
  243. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
  244. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
  245. { this restores the flags }
  246. list.concat(Taicpu.Op_none(A_IRET,S_NO));
  247. end
  248. { Routines with the poclearstack flag set use only a ret }
  249. else if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  250. begin
  251. { complex return values are removed from stack in C code PM }
  252. if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,
  253. current_procinfo.procdef.proccalloption) then
  254. list.concat(Taicpu.Op_const(A_RET,S_NO,sizeof(aint)))
  255. else
  256. list.concat(Taicpu.Op_none(A_RET,S_NO));
  257. end
  258. { ... also routines with parasize=0 }
  259. else if (parasize=0) then
  260. list.concat(Taicpu.Op_none(A_RET,S_NO))
  261. else
  262. begin
  263. { parameters are limited to 65535 bytes because ret allows only imm16 }
  264. if (parasize>65535) then
  265. CGMessage(cg_e_parasize_too_big);
  266. list.concat(Taicpu.Op_const(A_RET,S_NO,parasize));
  267. end;
  268. end;
  269. procedure tcg386.g_copyvaluepara_openarray(list : taasmoutput;const ref:treference;const lenloc:tlocation;elesize:aint;destreg:tregister);
  270. var
  271. power,len : longint;
  272. opsize : topsize;
  273. {$ifndef __NOWINPECOFF__}
  274. again,ok : tasmlabel;
  275. {$endif}
  276. begin
  277. { get stack space }
  278. getcpuregister(list,NR_EDI);
  279. a_load_loc_reg(list,OS_INT,lenloc,NR_EDI);
  280. list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
  281. if (elesize<>1) then
  282. begin
  283. if ispowerof2(elesize, power) then
  284. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
  285. else
  286. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
  287. end;
  288. {$ifndef __NOWINPECOFF__}
  289. { windows guards only a few pages for stack growing, }
  290. { so we have to access every page first }
  291. if target_info.system=system_i386_win32 then
  292. begin
  293. objectlibrary.getlabel(again);
  294. objectlibrary.getlabel(ok);
  295. a_label(list,again);
  296. list.concat(Taicpu.op_const_reg(A_CMP,S_L,winstackpagesize,NR_EDI));
  297. a_jmp_cond(list,OC_B,ok);
  298. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
  299. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EDI));
  300. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize,NR_EDI));
  301. a_jmp_always(list,again);
  302. a_label(list,ok);
  303. list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
  304. ungetcpuregister(list,NR_EDI);
  305. { now reload EDI }
  306. getcpuregister(list,NR_EDI);
  307. a_load_loc_reg(list,OS_INT,lenloc,NR_EDI);
  308. list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
  309. if (elesize<>1) then
  310. begin
  311. if ispowerof2(elesize, power) then
  312. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
  313. else
  314. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
  315. end;
  316. end
  317. else
  318. {$endif __NOWINPECOFF__}
  319. list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
  320. { align stack on 4 bytes }
  321. list.concat(Taicpu.op_const_reg(A_AND,S_L,aint($fffffff4),NR_ESP));
  322. { load destination, don't use a_load_reg_reg, that will add a move instruction
  323. that can confuse the reg allocator }
  324. list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,NR_ESP,NR_EDI));
  325. { Allocate other registers }
  326. getcpuregister(list,NR_ECX);
  327. getcpuregister(list,NR_ESI);
  328. { load count }
  329. a_load_loc_reg(list,OS_INT,lenloc,NR_ECX);
  330. { load source }
  331. a_loadaddr_ref_reg(list,ref,NR_ESI);
  332. { scheduled .... }
  333. list.concat(Taicpu.op_reg(A_INC,S_L,NR_ECX));
  334. { calculate size }
  335. len:=elesize;
  336. opsize:=S_B;
  337. if (len and 3)=0 then
  338. begin
  339. opsize:=S_L;
  340. len:=len shr 2;
  341. end
  342. else
  343. if (len and 1)=0 then
  344. begin
  345. opsize:=S_W;
  346. len:=len shr 1;
  347. end;
  348. if len<>0 then
  349. begin
  350. if ispowerof2(len, power) then
  351. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_ECX))
  352. else
  353. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,len,NR_ECX));
  354. end;
  355. list.concat(Taicpu.op_none(A_REP,S_NO));
  356. case opsize of
  357. S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  358. S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  359. S_L : list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
  360. end;
  361. ungetcpuregister(list,NR_EDI);
  362. ungetcpuregister(list,NR_ECX);
  363. ungetcpuregister(list,NR_ESI);
  364. { patch the new address, but don't use a_load_reg_reg, that will add a move instruction
  365. that can confuse the reg allocator }
  366. list.concat(Taicpu.Op_reg_reg(A_MOV,S_L,NR_ESP,destreg));
  367. end;
  368. procedure tcg386.g_exception_reason_save(list : taasmoutput; const href : treference);
  369. begin
  370. list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG));
  371. end;
  372. procedure tcg386.g_exception_reason_save_const(list : taasmoutput;const href : treference; a: aint);
  373. begin
  374. list.concat(Taicpu.op_const(A_PUSH,tcgsize2opsize[OS_INT],a));
  375. end;
  376. procedure tcg386.g_exception_reason_load(list : taasmoutput; const href : treference);
  377. begin
  378. list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG));
  379. end;
  380. { ************* 64bit operations ************ }
  381. procedure tcg64f386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  382. begin
  383. case op of
  384. OP_ADD :
  385. begin
  386. op1:=A_ADD;
  387. op2:=A_ADC;
  388. end;
  389. OP_SUB :
  390. begin
  391. op1:=A_SUB;
  392. op2:=A_SBB;
  393. end;
  394. OP_XOR :
  395. begin
  396. op1:=A_XOR;
  397. op2:=A_XOR;
  398. end;
  399. OP_OR :
  400. begin
  401. op1:=A_OR;
  402. op2:=A_OR;
  403. end;
  404. OP_AND :
  405. begin
  406. op1:=A_AND;
  407. op2:=A_AND;
  408. end;
  409. else
  410. internalerror(200203241);
  411. end;
  412. end;
  413. procedure tcg64f386.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);
  414. var
  415. op1,op2 : TAsmOp;
  416. tempref : treference;
  417. begin
  418. get_64bit_ops(op,op1,op2);
  419. list.concat(taicpu.op_ref_reg(op1,S_L,ref,reg.reglo));
  420. tempref:=ref;
  421. inc(tempref.offset,4);
  422. list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
  423. end;
  424. procedure tcg64f386.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  425. var
  426. op1,op2 : TAsmOp;
  427. begin
  428. case op of
  429. OP_NEG :
  430. begin
  431. if (regsrc.reglo<>regdst.reglo) then
  432. a_load64_reg_reg(list,regsrc,regdst);
  433. list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
  434. list.concat(taicpu.op_reg(A_NEG,S_L,regdst.reglo));
  435. list.concat(taicpu.op_const_reg(A_SBB,S_L,-1,regdst.reghi));
  436. exit;
  437. end;
  438. OP_NOT :
  439. begin
  440. if (regsrc.reglo<>regdst.reglo) then
  441. a_load64_reg_reg(list,regsrc,regdst);
  442. list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
  443. list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reglo));
  444. exit;
  445. end;
  446. end;
  447. get_64bit_ops(op,op1,op2);
  448. list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
  449. list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
  450. end;
  451. procedure tcg64f386.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);
  452. var
  453. op1,op2 : TAsmOp;
  454. begin
  455. case op of
  456. OP_AND,OP_OR,OP_XOR:
  457. begin
  458. cg.a_op_const_reg(list,op,OS_32,aint(lo(value)),reg.reglo);
  459. cg.a_op_const_reg(list,op,OS_32,aint(hi(value)),reg.reghi);
  460. end;
  461. OP_ADD, OP_SUB:
  462. begin
  463. // can't use a_op_const_ref because this may use dec/inc
  464. get_64bit_ops(op,op1,op2);
  465. list.concat(taicpu.op_const_reg(op1,S_L,aint(lo(value)),reg.reglo));
  466. list.concat(taicpu.op_const_reg(op2,S_L,aint(hi(value)),reg.reghi));
  467. end;
  468. else
  469. internalerror(200204021);
  470. end;
  471. end;
  472. procedure tcg64f386.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);
  473. var
  474. op1,op2 : TAsmOp;
  475. tempref : treference;
  476. begin
  477. case op of
  478. OP_AND,OP_OR,OP_XOR:
  479. begin
  480. cg.a_op_const_ref(list,op,OS_32,lo(value),ref);
  481. tempref:=ref;
  482. inc(tempref.offset,4);
  483. cg.a_op_const_ref(list,op,OS_32,hi(value),tempref);
  484. end;
  485. OP_ADD, OP_SUB:
  486. begin
  487. get_64bit_ops(op,op1,op2);
  488. // can't use a_op_const_ref because this may use dec/inc
  489. list.concat(taicpu.op_const_ref(op1,S_L,lo(value),ref));
  490. tempref:=ref;
  491. inc(tempref.offset,4);
  492. list.concat(taicpu.op_const_ref(op2,S_L,hi(value),tempref));
  493. end;
  494. else
  495. internalerror(200204022);
  496. end;
  497. end;
  498. begin
  499. cg := tcg386.create;
  500. cg64 := tcg64f386.create;
  501. end.
  502. {
  503. $Log$
  504. Revision 1.63 2005-01-18 22:19:20 peter
  505. * multiple location support for i386 a_param_ref
  506. * remove a_param_copy_ref for i386
  507. Revision 1.62 2004/11/21 17:54:59 peter
  508. * ttempcreatenode.create_reg merged into .create with parameter
  509. whether a register is allowed
  510. * funcret_paraloc renamed to funcretloc
  511. Revision 1.61 2004/11/21 17:17:04 florian
  512. * changed funcret location back to tlocation
  513. Revision 1.60 2004/10/31 21:45:03 peter
  514. * generic tlocation
  515. * move tlocation to cgutils
  516. Revision 1.59 2004/10/24 20:01:08 peter
  517. * remove saveregister calling convention
  518. Revision 1.58 2004/10/24 11:44:28 peter
  519. * small regvar fixes
  520. * loadref parameter removed from concatcopy,incrrefcount,etc
  521. Revision 1.57 2004/10/15 09:16:21 mazen
  522. - remove $IFDEF DELPHI and related code
  523. - remove $IFDEF FPCPROCVAR and related code
  524. Revision 1.56 2004/10/13 21:12:51 peter
  525. * -Or fixes for open array
  526. Revision 1.55 2004/10/11 15:46:45 peter
  527. * length parameter for copyvaluearray changed to tlocation
  528. Revision 1.54 2004/10/05 20:41:01 peter
  529. * more spilling rewrites
  530. Revision 1.53 2004/09/25 14:23:54 peter
  531. * ungetregister is now only used for cpuregisters, renamed to
  532. ungetcpuregister
  533. * renamed (get|unget)explicitregister(s) to ..cpuregister
  534. * removed location-release/reference_release
  535. Revision 1.52 2004/09/21 17:25:12 peter
  536. * paraloc branch merged
  537. Revision 1.51.4.1 2004/08/31 20:43:06 peter
  538. * paraloc patch
  539. Revision 1.51 2004/07/09 23:30:13 jonas
  540. * changed first_sse_imreg to first_mm_imreg
  541. Revision 1.50 2004/06/20 08:55:31 florian
  542. * logs truncated
  543. Revision 1.49 2004/06/16 20:07:10 florian
  544. * dwarf branch merged
  545. Revision 1.48 2004/04/09 14:36:05 peter
  546. * A_MOVSL renamed to A_MOVSD
  547. Revision 1.47.2.9 2004/05/30 10:45:50 peter
  548. * merged fixes from main branch
  549. Revision 1.47.2.8 2004/05/02 21:34:01 florian
  550. * i386 compilation fixed
  551. Revision 1.47.2.7 2004/05/02 12:45:32 peter
  552. * enabled cpuhasfixedstack for x86-64 again
  553. * fixed size of temp allocation for parameters
  554. }