cgcpu.pas 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  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. { This unit implements the code generator for the i386.
  19. }
  20. unit cgcpu;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,
  25. cgbase,cgobj,cg64f32,cgx86,
  26. aasmbase,aasmtai,aasmcpu,
  27. cpubase,cpuinfo,
  28. node,symconst
  29. {$ifdef delphi}
  30. ,dmisc
  31. {$endif}
  32. ;
  33. type
  34. tcg386 = class(tcgx86)
  35. procedure init_register_allocators;override;
  36. { passing parameter using push instead of mov }
  37. procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const locpara : tparalocation);override;
  38. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aint;const locpara : tparalocation);override;
  39. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);override;
  40. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);override;
  41. procedure g_save_all_registers(list : taasmoutput);override;
  42. procedure g_restore_all_registers(list : taasmoutput;const funcretparaloc:tparalocation);override;
  43. procedure g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);override;
  44. procedure g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aint);override;
  45. procedure g_exception_reason_save(list : taasmoutput; const href : treference);override;
  46. procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aint);override;
  47. procedure g_exception_reason_load(list : taasmoutput; const href : treference);override;
  48. end;
  49. tcg64f386 = class(tcg64f32)
  50. procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);override;
  51. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);override;
  52. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);override;
  53. procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);override;
  54. private
  55. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  56. end;
  57. implementation
  58. uses
  59. globals,verbose,systems,cutils,
  60. symdef,symsym,defutil,paramgr,procinfo,
  61. rgcpu,rgx86,tgobj,
  62. cgutils;
  63. procedure Tcg386.init_register_allocators;
  64. begin
  65. inherited init_register_allocators;
  66. if cs_create_pic in aktmoduleswitches then
  67. 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])
  68. else
  69. 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]);
  70. 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_sse_imreg,[]);
  71. 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_sse_imreg,[]);
  72. rgfpu:=Trgx86fpu.create;
  73. end;
  74. procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const locpara : tparalocation);
  75. var
  76. pushsize : tcgsize;
  77. begin
  78. check_register_size(size,r);
  79. with locpara do
  80. if (loc=LOC_REFERENCE) and
  81. (reference.index=NR_STACK_POINTER_REG) then
  82. begin
  83. pushsize:=int_cgsize(alignment);
  84. list.concat(taicpu.op_reg(A_PUSH,tcgsize2opsize[pushsize],makeregsize(list,r,pushsize)));
  85. end
  86. else
  87. inherited a_param_reg(list,size,r,locpara);
  88. end;
  89. procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aint;const locpara : tparalocation);
  90. var
  91. pushsize : tcgsize;
  92. begin
  93. with locpara do
  94. if (loc=LOC_REFERENCE) and
  95. (reference.index=NR_STACK_POINTER_REG) then
  96. begin
  97. pushsize:=int_cgsize(alignment);
  98. list.concat(taicpu.op_const(A_PUSH,tcgsize2opsize[pushsize],a));
  99. end
  100. else
  101. inherited a_param_const(list,size,a,locpara);
  102. end;
  103. procedure tcg386.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
  104. var
  105. pushsize : tcgsize;
  106. tmpreg : tregister;
  107. begin
  108. with locpara do
  109. if (loc=LOC_REFERENCE) and
  110. (reference.index=NR_STACK_POINTER_REG) then
  111. begin
  112. pushsize:=int_cgsize(alignment);
  113. if tcgsize2size[size]<alignment then
  114. begin
  115. tmpreg:=getintregister(list,pushsize);
  116. a_load_ref_reg(list,size,pushsize,r,tmpreg);
  117. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
  118. ungetregister(list,tmpreg);
  119. end
  120. else
  121. list.concat(taicpu.op_ref(A_PUSH,TCgsize2opsize[pushsize],r));
  122. end
  123. else
  124. inherited a_param_ref(list,size,r,locpara);
  125. end;
  126. procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  127. var
  128. tmpreg : tregister;
  129. opsize : topsize;
  130. begin
  131. with r do
  132. begin
  133. if (segment<>NR_NO) then
  134. cgmessage(cg_e_cant_use_far_pointer_there);
  135. with locpara do
  136. if (locpara.loc=LOC_REFERENCE) and
  137. (locpara.reference.index=NR_STACK_POINTER_REG) then
  138. begin
  139. opsize:=tcgsize2opsize[OS_ADDR];
  140. if (base=NR_NO) and (index=NR_NO) then
  141. begin
  142. if assigned(symbol) then
  143. list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
  144. else
  145. list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
  146. end
  147. else if (base=NR_NO) and (index<>NR_NO) and
  148. (offset=0) and (scalefactor=0) and (symbol=nil) then
  149. list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
  150. else if (base<>NR_NO) and (index=NR_NO) and
  151. (offset=0) and (symbol=nil) then
  152. list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
  153. else
  154. begin
  155. tmpreg:=getaddressregister(list);
  156. a_loadaddr_ref_reg(list,r,tmpreg);
  157. ungetregister(list,tmpreg);
  158. list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
  159. end;
  160. end
  161. else
  162. inherited a_paramaddr_ref(list,r,locpara);
  163. end;
  164. end;
  165. procedure tcg386.g_save_all_registers(list : taasmoutput);
  166. begin
  167. list.concat(Taicpu.Op_none(A_PUSHA,S_L));
  168. tg.GetTemp(list,sizeof(aint),tt_noreuse,current_procinfo.save_regs_ref);
  169. a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_STACK_POINTER_REG,current_procinfo.save_regs_ref);
  170. end;
  171. procedure tcg386.g_restore_all_registers(list : taasmoutput;const funcretparaloc:tparalocation);
  172. var
  173. href : treference;
  174. begin
  175. a_load_ref_reg(list,OS_ADDR,OS_ADDR,current_procinfo.save_regs_ref,NR_STACK_POINTER_REG);
  176. tg.UnGetTemp(list,current_procinfo.save_regs_ref);
  177. if funcretparaloc.loc=LOC_REGISTER then
  178. begin
  179. if funcretparaloc.size in [OS_64,OS_S64] then
  180. begin
  181. reference_reset_base(href,NR_STACK_POINTER_REG,20);
  182. a_load_reg_ref(list,OS_32,OS_32,NR_FUNCTION_RETURN64_HIGH_REG,href);
  183. reference_reset_base(href,NR_STACK_POINTER_REG,28);
  184. a_load_reg_ref(list,OS_32,OS_32,NR_FUNCTION_RETURN64_LOW_REG,href);
  185. end
  186. else
  187. begin
  188. reference_reset_base(href,NR_STACK_POINTER_REG,28);
  189. a_load_reg_ref(list,OS_32,OS_32,NR_FUNCTION_RETURN_REG,href);
  190. end;
  191. end;
  192. list.concat(Taicpu.Op_none(A_POPA,S_L));
  193. { We add a NOP because of the 386DX CPU bugs with POPAD }
  194. list.concat(taicpu.op_none(A_NOP,S_L));
  195. end;
  196. procedure tcg386.g_proc_exit(list : taasmoutput;parasize:longint;nostackframe:boolean);
  197. var
  198. stacksize : longint;
  199. begin
  200. { Release PIC register }
  201. if cs_create_pic in aktmoduleswitches then
  202. list.concat(tai_regalloc.dealloc(NR_PIC_OFFSET_REG));
  203. { MMX needs to call EMMS }
  204. if assigned(rg[R_MMXREGISTER]) and
  205. (rg[R_MMXREGISTER].uses_registers) then
  206. list.concat(Taicpu.op_none(A_EMMS,S_NO));
  207. { remove stackframe }
  208. if not nostackframe then
  209. begin
  210. if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
  211. begin
  212. stacksize:=current_procinfo.calc_stackframe_size;
  213. if (stacksize<>0) then
  214. cg.a_op_const_reg(list,OP_ADD,OS_ADDR,stacksize,current_procinfo.framepointer);
  215. end
  216. else
  217. list.concat(Taicpu.op_none(A_LEAVE,S_NO));
  218. list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG));
  219. end;
  220. { return from proc }
  221. if (po_interrupt in current_procinfo.procdef.procoptions) then
  222. begin
  223. if current_procinfo.procdef.funcret_paraloc[calleeside].loc=LOC_REGISTER then
  224. list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
  225. else
  226. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EAX));
  227. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EBX));
  228. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ECX));
  229. if current_procinfo.procdef.funcret_paraloc[calleeside].lochigh=LOC_REGISTER then
  230. list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
  231. else
  232. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
  233. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ESI));
  234. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDI));
  235. { .... also the segment registers }
  236. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  237. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
  238. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
  239. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
  240. { this restores the flags }
  241. list.concat(Taicpu.Op_none(A_IRET,S_NO));
  242. end
  243. { Routines with the poclearstack flag set use only a ret }
  244. else if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  245. begin
  246. { complex return values are removed from stack in C code PM }
  247. if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,
  248. current_procinfo.procdef.proccalloption) then
  249. list.concat(Taicpu.Op_const(A_RET,S_NO,sizeof(aint)))
  250. else
  251. list.concat(Taicpu.Op_none(A_RET,S_NO));
  252. end
  253. { ... also routines with parasize=0 }
  254. else if (parasize=0) then
  255. list.concat(Taicpu.Op_none(A_RET,S_NO))
  256. else
  257. begin
  258. { parameters are limited to 65535 bytes because ret allows only imm16 }
  259. if (parasize>65535) then
  260. CGMessage(cg_e_parasize_too_big);
  261. list.concat(Taicpu.Op_const(A_RET,S_NO,parasize));
  262. end;
  263. end;
  264. procedure tcg386.g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aint);
  265. var
  266. power,len : longint;
  267. opsize : topsize;
  268. {$ifndef __NOWINPECOFF__}
  269. again,ok : tasmlabel;
  270. {$endif}
  271. begin
  272. { get stack space }
  273. getexplicitregister(list,NR_EDI);
  274. list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,NR_EDI));
  275. list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
  276. if (elesize<>1) then
  277. begin
  278. if ispowerof2(elesize, power) then
  279. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
  280. else
  281. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
  282. end;
  283. {$ifndef __NOWINPECOFF__}
  284. { windows guards only a few pages for stack growing, }
  285. { so we have to access every page first }
  286. if target_info.system=system_i386_win32 then
  287. begin
  288. objectlibrary.getlabel(again);
  289. objectlibrary.getlabel(ok);
  290. a_label(list,again);
  291. list.concat(Taicpu.op_const_reg(A_CMP,S_L,winstackpagesize,NR_EDI));
  292. a_jmp_cond(list,OC_B,ok);
  293. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
  294. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EDI));
  295. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize,NR_EDI));
  296. a_jmp_always(list,again);
  297. a_label(list,ok);
  298. list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
  299. ungetregister(list,NR_EDI);
  300. { now reload EDI }
  301. getexplicitregister(list,NR_EDI);
  302. list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,NR_EDI));
  303. list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
  304. if (elesize<>1) then
  305. begin
  306. if ispowerof2(elesize, power) then
  307. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
  308. else
  309. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
  310. end;
  311. end
  312. else
  313. {$endif __NOWINPECOFF__}
  314. list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
  315. { align stack on 4 bytes }
  316. list.concat(Taicpu.op_const_reg(A_AND,S_L,aint($fffffff4),NR_ESP));
  317. { load destination }
  318. a_load_reg_reg(list,OS_INT,OS_INT,NR_ESP,NR_EDI);
  319. { Allocate other registers }
  320. getexplicitregister(list,NR_ECX);
  321. getexplicitregister(list,NR_ESI);
  322. { load count }
  323. a_load_ref_reg(list,OS_INT,OS_INT,lenref,NR_ECX);
  324. { load source }
  325. a_load_ref_reg(list,OS_INT,OS_INT,ref,NR_ESI);
  326. { scheduled .... }
  327. list.concat(Taicpu.op_reg(A_INC,S_L,NR_ECX));
  328. { calculate size }
  329. len:=elesize;
  330. opsize:=S_B;
  331. if (len and 3)=0 then
  332. begin
  333. opsize:=S_L;
  334. len:=len shr 2;
  335. end
  336. else
  337. if (len and 1)=0 then
  338. begin
  339. opsize:=S_W;
  340. len:=len shr 1;
  341. end;
  342. if ispowerof2(len, power) then
  343. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_ECX))
  344. else
  345. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,len,NR_ECX));
  346. list.concat(Taicpu.op_none(A_REP,S_NO));
  347. case opsize of
  348. S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  349. S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  350. S_L : list.concat(Taicpu.Op_none(A_MOVSD,S_NO));
  351. end;
  352. ungetregister(list,NR_EDI);
  353. ungetregister(list,NR_ECX);
  354. ungetregister(list,NR_ESI);
  355. { patch the new address }
  356. a_load_reg_ref(list,OS_INT,OS_INT,NR_ESP,ref);
  357. end;
  358. procedure tcg386.g_exception_reason_save(list : taasmoutput; const href : treference);
  359. begin
  360. list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG));
  361. end;
  362. procedure tcg386.g_exception_reason_save_const(list : taasmoutput;const href : treference; a: aint);
  363. begin
  364. list.concat(Taicpu.op_const(A_PUSH,tcgsize2opsize[OS_INT],a));
  365. end;
  366. procedure tcg386.g_exception_reason_load(list : taasmoutput; const href : treference);
  367. begin
  368. list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG));
  369. end;
  370. { ************* 64bit operations ************ }
  371. procedure tcg64f386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  372. begin
  373. case op of
  374. OP_ADD :
  375. begin
  376. op1:=A_ADD;
  377. op2:=A_ADC;
  378. end;
  379. OP_SUB :
  380. begin
  381. op1:=A_SUB;
  382. op2:=A_SBB;
  383. end;
  384. OP_XOR :
  385. begin
  386. op1:=A_XOR;
  387. op2:=A_XOR;
  388. end;
  389. OP_OR :
  390. begin
  391. op1:=A_OR;
  392. op2:=A_OR;
  393. end;
  394. OP_AND :
  395. begin
  396. op1:=A_AND;
  397. op2:=A_AND;
  398. end;
  399. else
  400. internalerror(200203241);
  401. end;
  402. end;
  403. procedure tcg64f386.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reg : tregister64);
  404. var
  405. op1,op2 : TAsmOp;
  406. tempref : treference;
  407. begin
  408. get_64bit_ops(op,op1,op2);
  409. list.concat(taicpu.op_ref_reg(op1,S_L,ref,reg.reglo));
  410. tempref:=ref;
  411. inc(tempref.offset,4);
  412. list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
  413. end;
  414. procedure tcg64f386.a_op64_reg_reg(list : taasmoutput;op:TOpCG;regsrc,regdst : tregister64);
  415. var
  416. op1,op2 : TAsmOp;
  417. begin
  418. case op of
  419. OP_NEG :
  420. begin
  421. if (regsrc.reglo<>regdst.reglo) then
  422. a_load64_reg_reg(list,regsrc,regdst);
  423. list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
  424. list.concat(taicpu.op_reg(A_NEG,S_L,regdst.reglo));
  425. list.concat(taicpu.op_const_reg(A_SBB,S_L,-1,regdst.reghi));
  426. exit;
  427. end;
  428. OP_NOT :
  429. begin
  430. if (regsrc.reglo<>regdst.reglo) then
  431. a_load64_reg_reg(list,regsrc,regdst);
  432. list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reghi));
  433. list.concat(taicpu.op_reg(A_NOT,S_L,regdst.reglo));
  434. exit;
  435. end;
  436. end;
  437. get_64bit_ops(op,op1,op2);
  438. list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
  439. list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
  440. end;
  441. procedure tcg64f386.a_op64_const_reg(list : taasmoutput;op:TOpCG;value : int64;reg : tregister64);
  442. var
  443. op1,op2 : TAsmOp;
  444. begin
  445. case op of
  446. OP_AND,OP_OR,OP_XOR:
  447. begin
  448. cg.a_op_const_reg(list,op,OS_32,aint(lo(value)),reg.reglo);
  449. cg.a_op_const_reg(list,op,OS_32,aint(hi(value)),reg.reghi);
  450. end;
  451. OP_ADD, OP_SUB:
  452. begin
  453. // can't use a_op_const_ref because this may use dec/inc
  454. get_64bit_ops(op,op1,op2);
  455. list.concat(taicpu.op_const_reg(op1,S_L,aint(lo(value)),reg.reglo));
  456. list.concat(taicpu.op_const_reg(op2,S_L,aint(hi(value)),reg.reghi));
  457. end;
  458. else
  459. internalerror(200204021);
  460. end;
  461. end;
  462. procedure tcg64f386.a_op64_const_ref(list : taasmoutput;op:TOpCG;value : int64;const ref : treference);
  463. var
  464. op1,op2 : TAsmOp;
  465. tempref : treference;
  466. begin
  467. case op of
  468. OP_AND,OP_OR,OP_XOR:
  469. begin
  470. cg.a_op_const_ref(list,op,OS_32,lo(value),ref);
  471. tempref:=ref;
  472. inc(tempref.offset,4);
  473. cg.a_op_const_ref(list,op,OS_32,hi(value),tempref);
  474. end;
  475. OP_ADD, OP_SUB:
  476. begin
  477. get_64bit_ops(op,op1,op2);
  478. // can't use a_op_const_ref because this may use dec/inc
  479. list.concat(taicpu.op_const_ref(op1,S_L,lo(value),ref));
  480. tempref:=ref;
  481. inc(tempref.offset,4);
  482. list.concat(taicpu.op_const_ref(op2,S_L,hi(value),tempref));
  483. end;
  484. else
  485. internalerror(200204022);
  486. end;
  487. end;
  488. begin
  489. cg := tcg386.create;
  490. cg64 := tcg64f386.create;
  491. end.
  492. {
  493. $Log$
  494. Revision 1.50 2004-06-20 08:55:31 florian
  495. * logs truncated
  496. Revision 1.49 2004/06/16 20:07:10 florian
  497. * dwarf branch merged
  498. Revision 1.48 2004/04/09 14:36:05 peter
  499. * A_MOVSL renamed to A_MOVSD
  500. Revision 1.47.2.9 2004/05/30 10:45:50 peter
  501. * merged fixes from main branch
  502. Revision 1.47.2.8 2004/05/02 21:34:01 florian
  503. * i386 compilation fixed
  504. Revision 1.47.2.7 2004/05/02 12:45:32 peter
  505. * enabled cpuhasfixedstack for x86-64 again
  506. * fixed size of temp allocation for parameters
  507. }