cgcpu.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  20. interface
  21. uses
  22. cginfo,cgbase,cgobj,cg64f32,aasm,cpuasm,cpubase,cpuinfo,symconst;
  23. type
  24. tcg386 = class(tcg64f32)
  25. { passing parameters, per default the parameter is pushed }
  26. { nr gives the number of the parameter (enumerated from }
  27. { left to right), this allows to move the parameter to }
  28. { register, if the cpu supports register calling }
  29. { conventions }
  30. procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);override;
  31. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);override;
  32. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;nr : longint);override;
  33. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);override;
  34. procedure a_call_name(list : taasmoutput;const s : string;
  35. offset : longint);override;
  36. procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; a: AWord; reg: TRegister); override;
  37. procedure a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; const ref: TReference); override;
  38. procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  39. procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
  40. procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
  41. procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  42. size: tcgsize; a: aword; src, dst: tregister); override;
  43. procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  44. size: tcgsize; src1, src2, dst: tregister); override;
  45. { move instructions }
  46. procedure a_load_const_reg(list : taasmoutput; size: tcgsize; a : aword;reg : tregister);override;
  47. procedure a_load_const_ref(list : taasmoutput; size: tcgsize; a : aword;const ref : treference);override;
  48. procedure a_load_reg_ref(list : taasmoutput; size: tcgsize; reg : tregister;const ref : treference);override;
  49. procedure a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref : treference;reg : tregister);override;
  50. procedure a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);override;
  51. procedure a_load_sym_ofs_reg(list: taasmoutput; const sym: tasmsymbol; ofs: longint; reg: tregister); override;
  52. { fpu move instructions }
  53. procedure a_loadfpu_reg_reg(list: taasmoutput; reg1, reg2: tregister); override;
  54. procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
  55. procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
  56. { vector register move instructions }
  57. procedure a_loadmm_reg_reg(list: taasmoutput; reg1, reg2: tregister); override;
  58. procedure a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister); override;
  59. procedure a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference); override;
  60. procedure a_parammm_reg(list: taasmoutput; reg: tregister); override;
  61. { comparison operations }
  62. procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  63. l : tasmlabel);override;
  64. procedure a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const ref : treference;
  65. l : tasmlabel);override;
  66. procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  67. procedure a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister; l : tasmlabel); override;
  68. procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
  69. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  70. procedure g_flags2reg(list: taasmoutput; const f: tresflags; reg: TRegister); override;
  71. procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
  72. procedure g_restore_frame_pointer(list : taasmoutput);override;
  73. procedure g_push_exception_value_reg(list : taasmoutput;reg : tregister);override;
  74. procedure g_push_exception_value_const(list : taasmoutput;reg : tregister);override;
  75. procedure g_pop_exception_value_reg(list : taasmoutput;reg : tregister);override;
  76. procedure g_return_from_proc(list : taasmoutput;parasize : aword); override;
  77. procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
  78. procedure a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reglo,reghi : tregister);override;
  79. procedure a_op64_reg_reg(list : taasmoutput;op:TOpCG;reglosrc,reghisrc,reglodst,reghidst : tregister);override;
  80. procedure a_op64_const_reg(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);override;
  81. procedure a_op64_const_ref(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;const ref : treference);override;
  82. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
  83. procedure g_maybe_loadself(list : taasmoutput); override;
  84. class function reg_cgsize(const reg: tregister): tcgsize; override;
  85. private
  86. procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  87. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  88. procedure sizes2load(s1 : tcgsize;s2 : topsize; var op: tasmop; var s3: topsize);
  89. procedure floatload(list: taasmoutput; t : tcgsize;const ref : treference);
  90. procedure floatstore(list: taasmoutput; t : tcgsize;const ref : treference);
  91. procedure floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
  92. procedure floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
  93. end;
  94. const
  95. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
  96. A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
  97. A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
  98. TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
  99. C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
  100. TCGSize2OpSize: Array[tcgsize] of topsize =
  101. (S_NO,S_B,S_W,S_L,S_L,S_B,S_W,S_L,S_L,
  102. S_FS,S_FL,S_FX,S_IQ,
  103. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  104. {
  105. TReg2CGSize: Array[tregister] of tcgsize = (OS_NO,
  106. S_L,S_L,S_L,S_L,S_L,S_L,S_L,S_L,
  107. S_W,S_W,S_W,S_W,S_W,S_W,S_W,S_W,
  108. S_B,S_B,S_B,S_B,S_B,S_B,S_B,S_B,
  109. S_W,S_W,S_W,S_W,S_W,S_W,
  110. S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,S_FL,
  111. S_L,S_L,S_L,S_L,S_L,S_L,
  112. S_L,S_L,S_L,S_L,
  113. S_L,S_L,S_L,S_L,S_L,
  114. OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,
  115. OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO,OS_NO
  116. );
  117. }
  118. implementation
  119. uses
  120. globtype,globals,verbose,systems,cutils,cga,rgobj,rgcpu;
  121. { currently does nothing }
  122. procedure tcg386.a_jmp_always(list : taasmoutput;l: tasmlabel);
  123. begin
  124. a_jmp_cond(list, OC_NONE, l);
  125. end;
  126. { we implement the following routines because otherwise we can't }
  127. { instantiate the class since it's abstract }
  128. procedure tcg386.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;nr : longint);
  129. begin
  130. case size of
  131. OS_8,OS_S8,
  132. OS_16,OS_S16:
  133. begin
  134. if target_info.alignment.paraalign = 2 then
  135. list.concat(taicpu.op_reg(A_PUSH,S_W,rg.makeregsize(r,OS_16)))
  136. else
  137. list.concat(taicpu.op_reg(A_PUSH,S_L,rg.makeregsize(r,OS_32)));
  138. end;
  139. OS_32,OS_S32:
  140. list.concat(taicpu.op_reg(A_PUSH,S_L,r));
  141. else
  142. internalerror(2002032212);
  143. end;
  144. end;
  145. procedure tcg386.a_param_const(list : taasmoutput;size : tcgsize;a : aword;nr : longint);
  146. begin
  147. case size of
  148. OS_8,OS_S8,OS_16,OS_S16:
  149. begin
  150. if target_info.alignment.paraalign = 2 then
  151. list.concat(taicpu.op_const(A_PUSH,S_W,a))
  152. else
  153. list.concat(taicpu.op_const(A_PUSH,S_L,a));
  154. end;
  155. OS_32,OS_S32:
  156. list.concat(taicpu.op_const(A_PUSH,S_L,a));
  157. else
  158. internalerror(2002032213);
  159. end;
  160. end;
  161. procedure tcg386.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;nr : longint);
  162. var
  163. tmpreg: tregister;
  164. begin
  165. case size of
  166. OS_8,OS_S8,
  167. OS_16,OS_S16:
  168. begin
  169. tmpreg := get_scratch_reg(list);
  170. a_load_ref_reg(list,size,r,tmpreg);
  171. if target_info.alignment.paraalign = 2 then
  172. list.concat(taicpu.op_reg(A_PUSH,S_W,rg.makeregsize(tmpreg,OS_16)))
  173. else
  174. list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
  175. free_scratch_reg(list,tmpreg);
  176. end;
  177. OS_32,OS_S32:
  178. list.concat(taicpu.op_ref(A_PUSH,S_L,r));
  179. else
  180. internalerror(2002032214);
  181. end;
  182. end;
  183. procedure tcg386.a_paramaddr_ref(list : taasmoutput;const r : treference;nr : longint);
  184. var
  185. tmpreg: tregister;
  186. begin
  187. if r.segment<>R_NO then
  188. CGMessage(cg_e_cant_use_far_pointer_there);
  189. if (r.base=R_NO) and (r.index=R_NO) then
  190. list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_L,r.symbol,r.offset))
  191. else if (r.base=R_NO) and (r.index<>R_NO) and
  192. (r.offset=0) and (r.scalefactor=0) and (r.symbol=nil) then
  193. list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.index))
  194. else if (r.base<>R_NO) and (r.index=R_NO) and
  195. (r.offset=0) and (r.symbol=nil) then
  196. list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
  197. else
  198. begin
  199. tmpreg := get_scratch_reg(list);
  200. a_loadaddr_ref_reg(list,r,tmpreg);
  201. list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
  202. free_scratch_reg(list,tmpreg);
  203. end;
  204. end;
  205. procedure tcg386.a_call_name(list : taasmoutput;const s : string; offset : longint);
  206. begin
  207. list.concat(taicpu.op_sym_ofs(A_CALL,S_NO,newasmsymbol(s),offset));
  208. end;
  209. {********************** load instructions ********************}
  210. procedure tcg386.a_load_const_reg(list : taasmoutput; size: TCGSize; a : aword; reg : TRegister);
  211. begin
  212. { the optimizer will change it to "xor reg,reg" when loading zero, }
  213. { no need to do it here too (JM) }
  214. list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[size],a,reg))
  215. end;
  216. procedure tcg386.a_load_const_ref(list : taasmoutput; size: tcgsize; a : aword;const ref : treference);
  217. begin
  218. {$ifdef OPTLOAD0}
  219. { zero is often used several times in succession -> load it in a }
  220. { register and then store it to memory, so the optimizer can then }
  221. { remove the unnecessary loads of registers and you get smaller }
  222. { (and faster) code }
  223. if (a = 0) and
  224. (size in [OS_32,OS_S32]) then
  225. inherited a_load_const_ref(list,size,a,ref)
  226. else
  227. {$endif OPTLOAD0}
  228. list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[size],a,ref));
  229. end;
  230. procedure tcg386.a_load_reg_ref(list : taasmoutput; size: TCGSize; reg : tregister;const ref : treference);
  231. begin
  232. list.concat(taicpu.op_reg_ref(A_MOV,TCGSize2OpSize[size],reg,
  233. ref));
  234. End;
  235. procedure tcg386.a_load_ref_reg(list : taasmoutput;size : tcgsize;const ref: treference;reg : tregister);
  236. var
  237. op: tasmop;
  238. s: topsize;
  239. begin
  240. sizes2load(size,reg2opsize[reg],op,s);
  241. list.concat(taicpu.op_ref_reg(op,s,ref,reg));
  242. end;
  243. procedure tcg386.a_load_reg_reg(list : taasmoutput;size : tcgsize;reg1,reg2 : tregister);
  244. var
  245. op: tasmop;
  246. s: topsize;
  247. begin
  248. sizes2load(size,reg2opsize[reg2],op,s);
  249. if (rg.makeregsize(reg1,OS_INT) = rg.makeregsize(reg2,OS_INT)) then
  250. begin
  251. { "mov reg1, reg1" doesn't make sense }
  252. if op = A_MOV then
  253. exit;
  254. { optimize movzx with "and ffff,<reg>" operation }
  255. if (op = A_MOVZX) then
  256. begin
  257. case size of
  258. OS_8:
  259. begin
  260. list.concat(taicpu.op_const_reg(A_AND,reg2opsize[reg2],255,reg2));
  261. exit;
  262. end;
  263. OS_16:
  264. begin
  265. list.concat(taicpu.op_const_reg(A_AND,reg2opsize[reg2],65535,reg2));
  266. exit;
  267. end;
  268. end;
  269. end;
  270. end;
  271. list.concat(taicpu.op_reg_reg(op,s,reg1,reg2));
  272. end;
  273. procedure tcg386.a_load_sym_ofs_reg(list: taasmoutput; const sym: tasmsymbol; ofs: longint; reg: tregister);
  274. begin
  275. list.concat(taicpu.op_sym_ofs_reg(A_MOV,S_L,sym,ofs,reg));
  276. end;
  277. { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
  278. { R_ST means "the current value at the top of the fpu stack" (JM) }
  279. procedure tcg386.a_loadfpu_reg_reg(list: taasmoutput; reg1, reg2: tregister);
  280. begin
  281. if (reg1 <> R_ST) then
  282. begin
  283. list.concat(taicpu.op_reg(A_FLD,S_NO,
  284. trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset)));
  285. inc(trgcpu(rg).fpuvaroffset);
  286. end;
  287. if (reg2 <> R_ST) then
  288. begin
  289. list.concat(taicpu.op_reg(A_FSTP,S_NO,
  290. trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset)));
  291. dec(trgcpu(rg).fpuvaroffset);
  292. end;
  293. end;
  294. procedure tcg386.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  295. begin
  296. floatload(list,size,ref);
  297. if (reg <> R_ST) then
  298. a_loadfpu_reg_reg(list,R_ST,reg);
  299. end;
  300. procedure tcg386.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  301. begin
  302. if reg <> R_ST then
  303. a_loadfpu_reg_reg(list,reg,R_ST);
  304. floatstore(list,size,ref);
  305. end;
  306. procedure tcg386.a_loadmm_reg_reg(list: taasmoutput; reg1, reg2: tregister);
  307. begin
  308. list.concat(taicpu.op_reg_reg(A_MOVQ,S_NO,reg1,reg2));
  309. end;
  310. procedure tcg386.a_loadmm_ref_reg(list: taasmoutput; const ref: treference; reg: tregister);
  311. begin
  312. list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,ref,reg));
  313. end;
  314. procedure tcg386.a_loadmm_reg_ref(list: taasmoutput; reg: tregister; const ref: treference);
  315. begin
  316. list.concat(taicpu.op_reg_ref(A_MOVQ,S_NO,reg,ref));
  317. end;
  318. procedure tcg386.a_parammm_reg(list: taasmoutput; reg: tregister);
  319. var
  320. href : treference;
  321. begin
  322. list.concat(taicpu.op_const_reg(A_SUB,S_L,8,R_ESP));
  323. reference_reset_base(href,R_ESP,0);
  324. list.concat(taicpu.op_reg_ref(A_MOVQ,S_NO,reg,href));
  325. end;
  326. procedure tcg386.a_op_const_reg(list : taasmoutput; Op: TOpCG; a: AWord; reg: TRegister);
  327. var
  328. opcode: tasmop;
  329. power: longint;
  330. begin
  331. Case Op of
  332. OP_DIV, OP_IDIV:
  333. Begin
  334. if ispowerof2(a,power) then
  335. begin
  336. case op of
  337. OP_DIV:
  338. opcode := A_SHR;
  339. OP_IDIV:
  340. opcode := A_SAR;
  341. end;
  342. list.concat(taicpu.op_const_reg(opcode,reg2opsize[reg],power,
  343. reg));
  344. exit;
  345. end;
  346. { the rest should be handled specifically in the code }
  347. { generator because of the silly register usage restraints }
  348. internalerror(200109224);
  349. End;
  350. OP_MUL,OP_IMUL:
  351. begin
  352. if not(cs_check_overflow in aktlocalswitches) and
  353. ispowerof2(a,power) then
  354. begin
  355. list.concat(taicpu.op_const_reg(A_SHL,reg2opsize[reg],power,
  356. reg));
  357. exit;
  358. end;
  359. if op = OP_IMUL then
  360. list.concat(taicpu.op_const_reg(A_IMUL,reg2opsize[reg],
  361. a,reg))
  362. else
  363. { OP_MUL should be handled specifically in the code }
  364. { generator because of the silly register usage restraints }
  365. internalerror(200109225);
  366. end;
  367. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  368. if not(cs_check_overflow in aktlocalswitches) and
  369. (a = 1) and
  370. (op in [OP_ADD,OP_SUB]) then
  371. if op = OP_ADD then
  372. list.concat(taicpu.op_reg(A_INC,reg2opsize[reg],reg))
  373. else
  374. list.concat(taicpu.op_reg(A_DEC,reg2opsize[reg],reg))
  375. else if (a = 0) then
  376. if (op <> OP_AND) then
  377. exit
  378. else
  379. list.concat(taicpu.op_const_reg(A_MOV,reg2opsize[reg],0,reg))
  380. else if (a = high(aword)) and
  381. (op in [OP_AND,OP_OR,OP_XOR]) then
  382. begin
  383. case op of
  384. OP_AND:
  385. exit;
  386. OP_OR:
  387. list.concat(taicpu.op_const_reg(A_MOV,reg2opsize[reg],high(aword),reg));
  388. OP_XOR:
  389. list.concat(taicpu.op_reg(A_NOT,reg2opsize[reg],reg));
  390. end
  391. end
  392. else
  393. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],reg2opsize[reg],
  394. a,reg));
  395. OP_SHL,OP_SHR,OP_SAR:
  396. begin
  397. if (a and 31) <> 0 Then
  398. list.concat(taicpu.op_const_reg(
  399. TOpCG2AsmOp[op],reg2opsize[reg],a and 31,reg));
  400. if (a shr 5) <> 0 Then
  401. internalerror(68991);
  402. end
  403. else internalerror(68992);
  404. end;
  405. end;
  406. procedure tcg386.a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; const ref: TReference);
  407. var
  408. opcode: tasmop;
  409. power: longint;
  410. begin
  411. Case Op of
  412. OP_DIV, OP_IDIV:
  413. Begin
  414. if ispowerof2(a,power) then
  415. begin
  416. case op of
  417. OP_DIV:
  418. opcode := A_SHR;
  419. OP_IDIV:
  420. opcode := A_SAR;
  421. end;
  422. list.concat(taicpu.op_const_ref(opcode,
  423. TCgSize2OpSize[size],power,ref));
  424. exit;
  425. end;
  426. { the rest should be handled specifically in the code }
  427. { generator because of the silly register usage restraints }
  428. internalerror(200109231);
  429. End;
  430. OP_MUL,OP_IMUL:
  431. begin
  432. if not(cs_check_overflow in aktlocalswitches) and
  433. ispowerof2(a,power) then
  434. begin
  435. list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
  436. power,ref));
  437. exit;
  438. end;
  439. { can't multiply a memory location directly with a constant }
  440. if op = OP_IMUL then
  441. inherited a_op_const_ref(list,op,size,a,ref)
  442. else
  443. { OP_MUL should be handled specifically in the code }
  444. { generator because of the silly register usage restraints }
  445. internalerror(200109232);
  446. end;
  447. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  448. if not(cs_check_overflow in aktlocalswitches) and
  449. (a = 1) and
  450. (op in [OP_ADD,OP_SUB]) then
  451. if op = OP_ADD then
  452. list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
  453. else
  454. list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
  455. else if (a = 0) then
  456. if (op <> OP_AND) then
  457. exit
  458. else
  459. a_load_const_ref(list,size,0,ref)
  460. else if (a = high(aword)) and
  461. (op in [OP_AND,OP_OR,OP_XOR]) then
  462. begin
  463. case op of
  464. OP_AND:
  465. exit;
  466. OP_OR:
  467. list.concat(taicpu.op_const_ref(A_MOV,TCgSize2OpSize[size],high(aword),ref));
  468. OP_XOR:
  469. list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref));
  470. end
  471. end
  472. else
  473. list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
  474. TCgSize2OpSize[size],a,ref));
  475. OP_SHL,OP_SHR,OP_SAR:
  476. begin
  477. if (a and 31) <> 0 Then
  478. list.concat(taicpu.op_const_ref(
  479. TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
  480. if (a shr 5) <> 0 Then
  481. internalerror(68991);
  482. end
  483. else internalerror(68992);
  484. end;
  485. end;
  486. procedure tcg386.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  487. var
  488. regloadsize: tcgsize;
  489. dstsize: topsize;
  490. tmpreg : tregister;
  491. popecx : boolean;
  492. begin
  493. dstsize := tcgsize2opsize[size];
  494. dst := rg.makeregsize(dst,size);
  495. case op of
  496. OP_NEG,OP_NOT:
  497. begin
  498. if src <> R_NO then
  499. internalerror(200112291);
  500. list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
  501. end;
  502. OP_MUL,OP_DIV,OP_IDIV:
  503. { special stuff, needs separate handling inside code }
  504. { generator }
  505. internalerror(200109233);
  506. OP_SHR,OP_SHL,OP_SAR:
  507. begin
  508. tmpreg := R_NO;
  509. { we need cl to hold the shift count, so if the destination }
  510. { is ecx, save it to a temp for now }
  511. if dst in [R_ECX,R_CX,R_CL] then
  512. begin
  513. case reg2opsize[dst] of
  514. S_B: regloadsize := OS_8;
  515. S_W: regloadsize := OS_16;
  516. else regloadsize := OS_32;
  517. end;
  518. tmpreg := get_scratch_reg(list);
  519. a_load_reg_reg(list,regloadsize,src,tmpreg);
  520. end;
  521. if not(src in [R_ECX,R_CX,R_CL]) then
  522. begin
  523. { is ecx still free (it's also free if it was allocated }
  524. { to dst, since we've moved dst somewhere else already) }
  525. if not((dst = R_ECX) or
  526. ((R_ECX in rg.unusedregsint) and
  527. { this will always be true, it's just here to }
  528. { allocate ecx }
  529. (rg.getexplicitregisterint(list,R_ECX) = R_ECX))) then
  530. begin
  531. list.concat(taicpu.op_reg(A_PUSH,S_L,R_ECX));
  532. popecx := true;
  533. end;
  534. a_load_reg_reg(list,OS_8,rg.makeregsize(src,OS_8),R_CL);
  535. end
  536. else
  537. src := R_CL;
  538. { do the shift }
  539. if tmpreg = R_NO then
  540. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  541. R_CL,dst))
  542. else
  543. begin
  544. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],S_L,
  545. R_CL,tmpreg));
  546. { move result back to the destination }
  547. a_load_reg_reg(list,OS_32,tmpreg,R_ECX);
  548. free_scratch_reg(list,tmpreg);
  549. end;
  550. if popecx then
  551. list.concat(taicpu.op_reg(A_POP,S_L,R_ECX))
  552. else if not (dst in [R_ECX,R_CX,R_CL]) then
  553. rg.ungetregisterint(list,R_ECX);
  554. end;
  555. else
  556. begin
  557. if reg2opsize[src] <> dstsize then
  558. internalerror(200109226);
  559. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  560. src,dst));
  561. end;
  562. end;
  563. end;
  564. procedure tcg386.a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
  565. var
  566. opsize: topsize;
  567. begin
  568. case op of
  569. OP_NEG,OP_NOT,OP_IMUL:
  570. begin
  571. inherited a_op_ref_reg(list,op,size,ref,reg);
  572. end;
  573. OP_MUL,OP_DIV,OP_IDIV:
  574. { special stuff, needs separate handling inside code }
  575. { generator }
  576. internalerror(200109239);
  577. else
  578. begin
  579. reg := rg.makeregsize(reg,size);
  580. list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],tcgsize2opsize[size],ref,reg));
  581. end;
  582. end;
  583. end;
  584. procedure tcg386.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
  585. var
  586. opsize: topsize;
  587. begin
  588. case op of
  589. OP_NEG,OP_NOT:
  590. begin
  591. if reg <> R_NO then
  592. internalerror(200109237);
  593. list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
  594. end;
  595. OP_IMUL:
  596. begin
  597. { this one needs a load/imul/store, which is the default }
  598. inherited a_op_ref_reg(list,op,size,ref,reg);
  599. end;
  600. OP_MUL,OP_DIV,OP_IDIV:
  601. { special stuff, needs separate handling inside code }
  602. { generator }
  603. internalerror(200109238);
  604. else
  605. begin
  606. opsize := tcgsize2opsize[size];
  607. list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref));
  608. end;
  609. end;
  610. end;
  611. procedure tcg386.a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  612. size: tcgsize; a: aword; src, dst: tregister);
  613. var
  614. tmpref: treference;
  615. power: longint;
  616. opsize: topsize;
  617. begin
  618. opsize := reg2opsize[src];
  619. if (opsize <> S_L) or
  620. not (size in [OS_32,OS_S32]) then
  621. begin
  622. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  623. exit;
  624. end;
  625. { if we get here, we have to do a 32 bit calculation, guaranteed }
  626. Case Op of
  627. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  628. OP_SAR:
  629. { can't do anything special for these }
  630. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  631. OP_IMUL:
  632. begin
  633. if not(cs_check_overflow in aktlocalswitches) and
  634. ispowerof2(a,power) then
  635. { can be done with a shift }
  636. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  637. list.concat(taicpu.op_const_reg_reg(A_IMUL,S_L,a,src,dst));
  638. end;
  639. OP_ADD, OP_SUB:
  640. if (a = 0) then
  641. a_load_reg_reg(list,size,src,dst)
  642. else
  643. begin
  644. reference_reset(tmpref);
  645. tmpref.base := src;
  646. tmpref.offset := longint(a);
  647. if op = OP_SUB then
  648. tmpref.offset := -tmpref.offset;
  649. list.concat(taicpu.op_ref_reg(A_LEA,S_L,tmpref,dst));
  650. end
  651. else internalerror(200112302);
  652. end;
  653. end;
  654. procedure tcg386.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  655. size: tcgsize; src1, src2, dst: tregister);
  656. var
  657. tmpref: treference;
  658. opsize: topsize;
  659. begin
  660. opsize := reg2opsize[src1];
  661. if (opsize <> S_L) or
  662. (reg2opsize[src2] <> S_L) or
  663. not (size in [OS_32,OS_S32]) then
  664. begin
  665. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  666. exit;
  667. end;
  668. { if we get here, we have to do a 32 bit calculation, guaranteed }
  669. Case Op of
  670. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  671. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  672. { can't do anything special for these }
  673. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  674. OP_IMUL:
  675. list.concat(taicpu.op_reg_reg_reg(A_IMUL,S_L,src1,src2,dst));
  676. OP_ADD:
  677. begin
  678. reference_reset(tmpref);
  679. tmpref.base := src1;
  680. tmpref.index := src2;
  681. tmpref.scalefactor := 1;
  682. list.concat(taicpu.op_ref_reg(A_LEA,S_L,tmpref,dst));
  683. end
  684. else internalerror(200112303);
  685. end;
  686. end;
  687. {*************** compare instructructions ****************}
  688. procedure tcg386.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  689. l : tasmlabel);
  690. begin
  691. if (a = 0) then
  692. list.concat(taicpu.op_reg_reg(A_TEST,reg2opsize[reg],reg,reg))
  693. else
  694. list.concat(taicpu.op_const_reg(A_CMP,reg2opsize[reg],a,reg));
  695. a_jmp_cond(list,cmp_op,l);
  696. end;
  697. procedure tcg386.a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const ref : treference;
  698. l : tasmlabel);
  699. begin
  700. list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,ref));
  701. a_jmp_cond(list,cmp_op,l);
  702. end;
  703. procedure tcg386.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;
  704. reg1,reg2 : tregister;l : tasmlabel);
  705. begin
  706. if reg2opsize[reg1] <> reg2opsize[reg2] then
  707. internalerror(200109226);
  708. list.concat(taicpu.op_reg_reg(A_CMP,reg2opsize[reg1],reg1,reg2));
  709. a_jmp_cond(list,cmp_op,l);
  710. end;
  711. procedure tcg386.a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister;l : tasmlabel);
  712. var
  713. opsize: topsize;
  714. begin
  715. reg := rg.makeregsize(reg,size);
  716. list.concat(taicpu.op_ref_reg(A_CMP,tcgsize2opsize[size],ref,reg));
  717. a_jmp_cond(list,cmp_op,l);
  718. end;
  719. procedure tcg386.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  720. var
  721. ai : taicpu;
  722. begin
  723. if cond=OC_None then
  724. ai := Taicpu.Op_sym(A_JMP,S_NO,l)
  725. else
  726. begin
  727. ai:=Taicpu.Op_sym(A_Jcc,S_NO,l);
  728. ai.SetCondition(TOpCmp2AsmCond[cond]);
  729. end;
  730. ai.is_jmp:=true;
  731. list.concat(ai);
  732. end;
  733. procedure tcg386.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  734. var
  735. ai : taicpu;
  736. begin
  737. ai := Taicpu.op_sym(A_Jcc,S_NO,l);
  738. ai.SetCondition(flags_to_cond(f));
  739. ai.is_jmp := true;
  740. list.concat(ai);
  741. end;
  742. procedure tcg386.g_flags2reg(list: taasmoutput; const f: tresflags; reg: TRegister);
  743. var
  744. ai : taicpu;
  745. hreg : tregister;
  746. begin
  747. hreg := rg.makeregsize(reg,OS_8);
  748. ai:=Taicpu.Op_reg(A_Setcc,S_B,hreg);
  749. ai.SetCondition(flags_to_cond(f));
  750. list.concat(ai);
  751. if hreg<>reg then
  752. a_load_reg_reg(exprasmlist,OS_8,hreg,reg);
  753. end;
  754. { *********** entry/exit code and address loading ************ }
  755. procedure tcg386.g_stackframe_entry(list : taasmoutput;localsize : longint);
  756. begin
  757. runerror(211);
  758. end;
  759. procedure tcg386.g_restore_frame_pointer(list : taasmoutput);
  760. begin
  761. runerror(211);
  762. end;
  763. procedure tcg386.g_push_exception_value_reg(list : taasmoutput;reg : tregister);
  764. begin
  765. runerror(211);
  766. end;
  767. procedure tcg386.g_push_exception_value_const(list : taasmoutput;reg : tregister);
  768. begin
  769. runerror(211);
  770. end;
  771. procedure tcg386.g_pop_exception_value_reg(list : taasmoutput;reg : tregister);
  772. begin
  773. runerror(211);
  774. end;
  775. procedure tcg386.g_return_from_proc(list : taasmoutput;parasize : aword);
  776. begin
  777. runerror(211);
  778. end;
  779. procedure tcg386.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  780. begin
  781. list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,r));
  782. end;
  783. { ************* 64bit operations ************ }
  784. procedure tcg386.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  785. begin
  786. case op of
  787. OP_ADD :
  788. begin
  789. op1:=A_ADD;
  790. op2:=A_ADC;
  791. end;
  792. OP_SUB :
  793. begin
  794. op1:=A_SUB;
  795. op2:=A_SBB;
  796. end;
  797. OP_XOR :
  798. begin
  799. op1:=A_XOR;
  800. op2:=A_XOR;
  801. end;
  802. OP_OR :
  803. begin
  804. op1:=A_OR;
  805. op2:=A_OR;
  806. end;
  807. OP_AND :
  808. begin
  809. op1:=A_AND;
  810. op2:=A_AND;
  811. end;
  812. else
  813. internalerror(200203241);
  814. end;
  815. end;
  816. procedure tcg386.a_op64_ref_reg(list : taasmoutput;op:TOpCG;const ref : treference;reglo,reghi : tregister);
  817. var
  818. op1,op2 : TAsmOp;
  819. tempref : treference;
  820. begin
  821. get_64bit_ops(op,op1,op2);
  822. list.concat(taicpu.op_ref_reg(op1,S_L,ref,reglo));
  823. tempref:=ref;
  824. inc(tempref.offset,4);
  825. list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reghi));
  826. end;
  827. procedure tcg386.a_op64_reg_reg(list : taasmoutput;op:TOpCG;reglosrc,reghisrc,reglodst,reghidst : tregister);
  828. var
  829. op1,op2 : TAsmOp;
  830. begin
  831. get_64bit_ops(op,op1,op2);
  832. list.concat(taicpu.op_reg_reg(op1,S_L,reglosrc,reglodst));
  833. list.concat(taicpu.op_reg_reg(op2,S_L,reghisrc,reghidst));
  834. end;
  835. procedure tcg386.a_op64_const_reg(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;reglodst,reghidst : tregister);
  836. var
  837. op1,op2 : TAsmOp;
  838. begin
  839. case op of
  840. OP_AND,OP_OR,OP_XOR:
  841. begin
  842. a_op_const_reg(list,op,valuelosrc,reglodst);
  843. a_op_const_reg(list,op,valuehisrc,reghidst);
  844. end;
  845. OP_ADD, OP_SUB:
  846. begin
  847. // can't use a_op_const_ref because this may use dec/inc
  848. get_64bit_ops(op,op1,op2);
  849. list.concat(taicpu.op_const_reg(op1,S_L,valuelosrc,reglodst));
  850. list.concat(taicpu.op_const_reg(op2,S_L,valuehisrc,reghidst));
  851. end;
  852. else
  853. internalerror(200204021);
  854. end;
  855. end;
  856. procedure tcg386.a_op64_const_ref(list : taasmoutput;op:TOpCG;valuelosrc,valuehisrc:AWord;const ref : treference);
  857. var
  858. op1,op2 : TAsmOp;
  859. tempref : treference;
  860. begin
  861. case op of
  862. OP_AND,OP_OR,OP_XOR:
  863. begin
  864. a_op_const_ref(list,op,OS_32,valuelosrc,ref);
  865. tempref:=ref;
  866. inc(tempref.offset,4);
  867. a_op_const_ref(list,op,OS_32,valuehisrc,tempref);
  868. end;
  869. OP_ADD, OP_SUB:
  870. begin
  871. get_64bit_ops(op,op1,op2);
  872. // can't use a_op_const_ref because this may use dec/inc
  873. list.concat(taicpu.op_const_ref(op1,S_L,valuelosrc,ref));
  874. tempref:=ref;
  875. inc(tempref.offset,4);
  876. list.concat(taicpu.op_const_ref(op2,S_L,valuehisrc,tempref));
  877. end;
  878. else
  879. internalerror(200204022);
  880. end;
  881. end;
  882. { ************* concatcopy ************ }
  883. procedure tcg386.g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);
  884. { temp implementation, until it's permanenty moved here from cga.pas }
  885. var
  886. oldlist: taasmoutput;
  887. begin
  888. if list <> exprasmlist then
  889. begin
  890. oldlist := exprasmlist;
  891. exprasmlist := list;
  892. end;
  893. cga.concatcopy(source,dest,len,delsource,loadref);
  894. if list <> exprasmlist then
  895. list := oldlist;
  896. end;
  897. procedure tcg386.g_maybe_loadself(list : taasmoutput);
  898. var
  899. oldlist: taasmoutput;
  900. begin
  901. if list <> exprasmlist then
  902. begin
  903. oldlist := exprasmlist;
  904. exprasmlist := list;
  905. end;
  906. cga.maybe_loadself;
  907. if list <> exprasmlist then
  908. list := oldlist;
  909. end;
  910. function tcg386.reg_cgsize(const reg: tregister): tcgsize;
  911. const
  912. regsize_2_cgsize: array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32);
  913. begin
  914. result := regsize_2_cgsize[reg2opsize[reg]];
  915. end;
  916. {***************** This is private property, keep out! :) *****************}
  917. procedure tcg386.sizes2load(s1 : tcgsize;s2: topsize; var op: tasmop; var s3: topsize);
  918. begin
  919. case s2 of
  920. S_B:
  921. if S1 in [OS_8,OS_S8] then
  922. s3 := S_B
  923. else internalerror(200109221);
  924. S_W:
  925. case s1 of
  926. OS_8,OS_S8:
  927. s3 := S_BW;
  928. OS_16,OS_S16:
  929. s3 := S_W;
  930. else internalerror(200109222);
  931. end;
  932. S_L:
  933. case s1 of
  934. OS_8,OS_S8:
  935. s3 := S_BL;
  936. OS_16,OS_S16:
  937. s3 := S_WL;
  938. OS_32,OS_S32:
  939. s3 := S_L;
  940. else internalerror(200109223);
  941. end;
  942. else internalerror(200109227);
  943. end;
  944. if s3 in [S_B,S_W,S_L] then
  945. op := A_MOV
  946. else if s1 in [OS_8,OS_16,OS_32] then
  947. op := A_MOVZX
  948. else
  949. op := A_MOVSX;
  950. end;
  951. procedure tcg386.floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
  952. begin
  953. case t of
  954. OS_F32 :
  955. begin
  956. op:=A_FLD;
  957. s:=S_FS;
  958. end;
  959. OS_F64 :
  960. begin
  961. op:=A_FLD;
  962. { ???? }
  963. s:=S_FL;
  964. end;
  965. OS_F80 :
  966. begin
  967. op:=A_FLD;
  968. s:=S_FX;
  969. end;
  970. OS_C64 :
  971. begin
  972. op:=A_FILD;
  973. s:=S_IQ;
  974. end;
  975. else
  976. internalerror(200204041);
  977. end;
  978. end;
  979. procedure tcg386.floatload(list: taasmoutput; t : tcgsize;const ref : treference);
  980. var
  981. op : tasmop;
  982. s : topsize;
  983. begin
  984. floatloadops(t,op,s);
  985. list.concat(Taicpu.Op_ref(op,s,ref));
  986. inc(trgcpu(rg).fpuvaroffset);
  987. end;
  988. procedure tcg386.floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
  989. begin
  990. case t of
  991. OS_F32 :
  992. begin
  993. op:=A_FSTP;
  994. s:=S_FS;
  995. end;
  996. OS_F64 :
  997. begin
  998. op:=A_FSTP;
  999. s:=S_FL;
  1000. end;
  1001. OS_F80 :
  1002. begin
  1003. op:=A_FSTP;
  1004. s:=S_FX;
  1005. end;
  1006. OS_C64 :
  1007. begin
  1008. op:=A_FISTP;
  1009. s:=S_IQ;
  1010. end;
  1011. else
  1012. internalerror(200204042);
  1013. end;
  1014. end;
  1015. procedure tcg386.floatstore(list: taasmoutput; t : tcgsize;const ref : treference);
  1016. var
  1017. op : tasmop;
  1018. s : topsize;
  1019. begin
  1020. floatstoreops(t,op,s);
  1021. list.concat(Taicpu.Op_ref(op,s,ref));
  1022. dec(trgcpu(rg).fpuvaroffset);
  1023. end;
  1024. begin
  1025. cg := tcg386.create;
  1026. end.
  1027. {
  1028. $Log$
  1029. Revision 1.14 2002-04-25 20:16:40 peter
  1030. * moved more routines from cga/n386util
  1031. Revision 1.13 2002/04/21 15:31:05 carl
  1032. * changeregsize -> rg.makeregsize
  1033. + a_jmp_always added
  1034. Revision 1.12 2002/04/15 19:44:20 peter
  1035. * fixed stackcheck that would be called recursively when a stack
  1036. error was found
  1037. * generic changeregsize(reg,size) for i386 register resizing
  1038. * removed some more routines from cga unit
  1039. * fixed returnvalue handling
  1040. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  1041. Revision 1.11 2002/04/04 19:06:10 peter
  1042. * removed unused units
  1043. * use tlocation.size in cg.a_*loc*() routines
  1044. Revision 1.10 2002/04/02 20:29:02 jonas
  1045. * optimized the code generated by the a_op_const_* and a_op64_const
  1046. methods
  1047. Revision 1.9 2002/04/02 17:11:33 peter
  1048. * tlocation,treference update
  1049. * LOC_CONSTANT added for better constant handling
  1050. * secondadd splitted in multiple routines
  1051. * location_force_reg added for loading a location to a register
  1052. of a specified size
  1053. * secondassignment parses now first the right and then the left node
  1054. (this is compatible with Kylix). This saves a lot of push/pop especially
  1055. with string operations
  1056. * adapted some routines to use the new cg methods
  1057. Revision 1.8 2002/03/31 20:26:37 jonas
  1058. + a_loadfpu_* and a_loadmm_* methods in tcg
  1059. * register allocation is now handled by a class and is mostly processor
  1060. independent (+rgobj.pas and i386/rgcpu.pas)
  1061. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1062. * some small improvements and fixes to the optimizer
  1063. * some register allocation fixes
  1064. * some fpuvaroffset fixes in the unary minus node
  1065. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1066. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1067. also better optimizable)
  1068. * fixed and optimized register saving/restoring for new/dispose nodes
  1069. * LOC_FPU locations now also require their "register" field to be set to
  1070. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1071. - list field removed of the tnode class because it's not used currently
  1072. and can cause hard-to-find bugs
  1073. Revision 1.7 2002/03/04 19:10:12 peter
  1074. * removed compiler warnings
  1075. Revision 1.6 2001/12/30 17:24:46 jonas
  1076. * range checking is now processor independent (part in cgobj,
  1077. part in cg64f32) and should work correctly again (it needed
  1078. some changes after the changes of the low and high of
  1079. tordef's to int64)
  1080. * maketojumpbool() is now processor independent (in ncgutil)
  1081. * getregister32 is now called getregisterint
  1082. Revision 1.5 2001/12/29 15:29:59 jonas
  1083. * powerpc/cgcpu.pas compiles :)
  1084. * several powerpc-related fixes
  1085. * cpuasm unit is now based on common tainst unit
  1086. + nppcmat unit for powerpc (almost complete)
  1087. Revision 1.4 2001/10/04 14:33:28 jonas
  1088. * fixed range check errors
  1089. Revision 1.3 2001/09/30 16:17:18 jonas
  1090. * made most constant and mem handling processor independent
  1091. Revision 1.2 2001/09/29 21:32:19 jonas
  1092. * fixed bug in a_load_reg_reg + implemented a_call
  1093. Revision 1.1 2001/09/28 20:39:33 jonas
  1094. * changed all flow control structures (except for exception handling
  1095. related things) to processor independent code (in new ncgflw unit)
  1096. + generic cgobj unit which contains lots of code generator helpers with
  1097. global "cg" class instance variable
  1098. + cgcpu unit for i386 (implements processor specific routines of the above
  1099. unit)
  1100. * updated cgbase and cpubase for the new code generator units
  1101. * include ncgflw unit in cpunode unit
  1102. }