cgx86.pas 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the common parts of the code generator for the i386 and the x86-64.
  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 common parts of the code generator for the i386 and the x86-64.
  19. }
  20. unit cgx86;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. cgbase,cgobj,
  25. aasmbase,aasmtai,aasmcpu,
  26. cpubase,cpuinfo,rgobj,rgx86,rgcpu,
  27. symconst,symtype;
  28. type
  29. tcgx86 = class(tcg)
  30. rgfpu : Trgx86fpu;
  31. procedure init_register_allocators;override;
  32. procedure done_register_allocators;override;
  33. function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  34. function getmmxregister(list:Taasmoutput):Tregister;
  35. procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
  36. procedure ungetregister(list:Taasmoutput;r:Tregister);override;
  37. procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
  38. procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
  39. function uses_registers(rt:Tregistertype):boolean;override;
  40. procedure add_reg_instruction(instr:Tai;r:tregister);override;
  41. procedure dec_fpu_stack;
  42. procedure inc_fpu_stack;
  43. { passing parameters, per default the parameter is pushed }
  44. { nr gives the number of the parameter (enumerated from }
  45. { left to right), this allows to move the parameter to }
  46. { register, if the cpu supports register calling }
  47. { conventions }
  48. procedure a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const locpara : tparalocation);override;
  49. procedure a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);override;
  50. procedure a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);override;
  51. procedure a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);override;
  52. procedure a_call_name(list : taasmoutput;const s : string);override;
  53. procedure a_call_reg(list : taasmoutput;reg : tregister);override;
  54. procedure a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister); override;
  55. procedure a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; const ref: TReference); override;
  56. procedure a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister); override;
  57. procedure a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister); override;
  58. procedure a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference); override;
  59. procedure a_op_const_reg_reg(list: taasmoutput; op: TOpCg;
  60. size: tcgsize; a: aword; src, dst: tregister); override;
  61. procedure a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;
  62. size: tcgsize; src1, src2, dst: tregister); override;
  63. { move instructions }
  64. procedure a_load_const_reg(list : taasmoutput; tosize: tcgsize; a : aword;reg : tregister);override;
  65. procedure a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aword;const ref : treference);override;
  66. procedure a_load_reg_ref(list : taasmoutput;fromsize,tosize: tcgsize; reg : tregister;const ref : treference);override;
  67. procedure a_load_ref_reg(list : taasmoutput;fromsize,tosize: tcgsize;const ref : treference;reg : tregister);override;
  68. procedure a_load_reg_reg(list : taasmoutput;fromsize,tosize: tcgsize;reg1,reg2 : tregister);override;
  69. procedure a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);override;
  70. { fpu move instructions }
  71. procedure a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister); override;
  72. procedure a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister); override;
  73. procedure a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference); override;
  74. { vector register move instructions }
  75. procedure a_loadmm_reg_reg(list: taasmoutput; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle); override;
  76. procedure a_loadmm_ref_reg(list: taasmoutput; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
  77. procedure a_loadmm_reg_ref(list: taasmoutput; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle); override;
  78. procedure a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle); override;
  79. procedure a_opmm_reg_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle);override;
  80. { comparison operations }
  81. procedure a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  82. l : tasmlabel);override;
  83. procedure a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const ref : treference;
  84. l : tasmlabel);override;
  85. procedure a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;reg1,reg2 : tregister;l : tasmlabel); override;
  86. procedure a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister; l : tasmlabel); override;
  87. procedure a_jmp_always(list : taasmoutput;l: tasmlabel); override;
  88. procedure a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel); override;
  89. procedure g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister); override;
  90. procedure g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref: TReference); override;
  91. procedure g_concatcopy(list : taasmoutput;const source,dest : treference;len : aword; delsource,loadref : boolean);override;
  92. procedure g_exception_reason_save(list : taasmoutput; const href : treference);override;
  93. procedure g_exception_reason_save_const(list : taasmoutput; const href : treference; a: aword);override;
  94. procedure g_exception_reason_load(list : taasmoutput; const href : treference);override;
  95. { entry/exit code helpers }
  96. procedure g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);override;
  97. procedure g_interrupt_stackframe_entry(list : taasmoutput);override;
  98. procedure g_interrupt_stackframe_exit(list : taasmoutput;accused,acchiused:boolean);override;
  99. procedure g_profilecode(list : taasmoutput);override;
  100. procedure g_stackpointer_alloc(list : taasmoutput;localsize : longint);override;
  101. procedure g_stackframe_entry(list : taasmoutput;localsize : longint);override;
  102. procedure g_restore_frame_pointer(list : taasmoutput);override;
  103. procedure g_return_from_proc(list : taasmoutput;parasize : aword);override;
  104. procedure g_save_standard_registers(list:Taasmoutput);override;
  105. procedure g_restore_standard_registers(list:Taasmoutput);override;
  106. procedure g_save_all_registers(list : taasmoutput);override;
  107. procedure g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);override;
  108. procedure g_overflowcheck(list: taasmoutput; const l:tlocation;def:tdef);override;
  109. protected
  110. procedure a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  111. procedure check_register_size(size:tcgsize;reg:tregister);
  112. procedure opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;loc : tlocation;dst: tregister; shuffle : pmmshuffle);
  113. private
  114. procedure sizes2load(s1,s2 : tcgsize;var op: tasmop; var s3: topsize);
  115. procedure floatload(list: taasmoutput; t : tcgsize;const ref : treference);
  116. procedure floatstore(list: taasmoutput; t : tcgsize;const ref : treference);
  117. procedure floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
  118. procedure floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
  119. end;
  120. function use_sse(def : tdef) : boolean;
  121. const
  122. {$ifdef x86_64}
  123. TCGSize2OpSize: Array[tcgsize] of topsize =
  124. (S_NO,S_B,S_W,S_L,S_D,S_B,S_W,S_L,S_D,
  125. S_FS,S_FL,S_FX,S_IQ,S_FXX,
  126. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  127. {$else x86_64}
  128. TCGSize2OpSize: Array[tcgsize] of topsize =
  129. (S_NO,S_B,S_W,S_L,S_L,S_B,S_W,S_L,S_L,
  130. S_FS,S_FL,S_FX,S_IQ,S_FXX,
  131. S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  132. {$endif x86_64}
  133. implementation
  134. uses
  135. globtype,globals,verbose,systems,cutils,
  136. symdef,defutil,paramgr,tgobj,procinfo;
  137. {$ifndef NOTARGETWIN32}
  138. const
  139. winstackpagesize = 4096;
  140. {$endif NOTARGETWIN32}
  141. TOpCG2AsmOp: Array[topcg] of TAsmOp = (A_NONE,A_ADD,A_AND,A_DIV,
  142. A_IDIV,A_MUL, A_IMUL, A_NEG,A_NOT,A_OR,
  143. A_SAR,A_SHL,A_SHR,A_SUB,A_XOR);
  144. TOpCmp2AsmCond: Array[topcmp] of TAsmCond = (C_NONE,
  145. C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
  146. function use_sse(def : tdef) : boolean;
  147. begin
  148. use_sse:=(is_single(def) and (aktfputype in sse_singlescalar)) or
  149. (is_double(def) and (aktfputype in sse_doublescalar));
  150. end;
  151. procedure Tcgx86.init_register_allocators;
  152. begin
  153. inherited init_register_allocators;
  154. if cs_create_pic in aktmoduleswitches then
  155. 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])
  156. else
  157. 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]);
  158. rg[R_MMXREGISTER]:=trgcpu.create(R_MMXREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
  159. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,[RS_MM0,RS_MM1,RS_MM2,RS_MM3,RS_MM4,RS_MM5,RS_MM6,RS_MM7],first_sse_imreg,[]);
  160. rgfpu:=Trgx86fpu.create;
  161. end;
  162. procedure Tcgx86.done_register_allocators;
  163. begin
  164. rg[R_INTREGISTER].free;
  165. rg[R_MMREGISTER].free;
  166. rg[R_MMXREGISTER].free;
  167. rgfpu.free;
  168. inherited done_register_allocators;
  169. end;
  170. function Tcgx86.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
  171. begin
  172. result:=rgfpu.getregisterfpu(list);
  173. end;
  174. function Tcgx86.getmmxregister(list:Taasmoutput):Tregister;
  175. begin
  176. if not assigned(rg[R_MMXREGISTER]) then
  177. internalerror(200312124);
  178. result:=rg[R_MMXREGISTER].getregister(list,R_SUBNONE);
  179. end;
  180. procedure Tcgx86.getexplicitregister(list:Taasmoutput;r:Tregister);
  181. begin
  182. if getregtype(r)=R_FPUREGISTER then
  183. internalerror(2003121210)
  184. else
  185. inherited getexplicitregister(list,r);
  186. end;
  187. procedure tcgx86.ungetregister(list:Taasmoutput;r:Tregister);
  188. begin
  189. if getregtype(r)=R_FPUREGISTER then
  190. rgfpu.ungetregisterfpu(list,r)
  191. else
  192. inherited ungetregister(list,r);
  193. end;
  194. procedure Tcgx86.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
  195. begin
  196. if rt<>R_FPUREGISTER then
  197. inherited allocexplicitregisters(list,rt,r);
  198. end;
  199. procedure Tcgx86.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
  200. begin
  201. if rt<>R_FPUREGISTER then
  202. inherited deallocexplicitregisters(list,rt,r);
  203. end;
  204. function Tcgx86.uses_registers(rt:Tregistertype):boolean;
  205. begin
  206. if rt=R_FPUREGISTER then
  207. result:=false
  208. else
  209. result:=inherited uses_registers(rt);
  210. end;
  211. procedure tcgx86.add_reg_instruction(instr:Tai;r:tregister);
  212. begin
  213. if getregtype(r)<>R_FPUREGISTER then
  214. inherited add_reg_instruction(instr,r);
  215. end;
  216. procedure tcgx86.dec_fpu_stack;
  217. begin
  218. dec(rgfpu.fpuvaroffset);
  219. end;
  220. procedure tcgx86.inc_fpu_stack;
  221. begin
  222. inc(rgfpu.fpuvaroffset);
  223. end;
  224. {****************************************************************************
  225. This is private property, keep out! :)
  226. ****************************************************************************}
  227. procedure tcgx86.sizes2load(s1,s2 : tcgsize; var op: tasmop; var s3: topsize);
  228. begin
  229. case s2 of
  230. OS_8,OS_S8 :
  231. if S1 in [OS_8,OS_S8] then
  232. s3 := S_B
  233. else internalerror(200109221);
  234. OS_16,OS_S16:
  235. case s1 of
  236. OS_8,OS_S8:
  237. s3 := S_BW;
  238. OS_16,OS_S16:
  239. s3 := S_W;
  240. else
  241. internalerror(200109222);
  242. end;
  243. OS_32,OS_S32:
  244. case s1 of
  245. OS_8,OS_S8:
  246. s3 := S_BL;
  247. OS_16,OS_S16:
  248. s3 := S_WL;
  249. OS_32,OS_S32:
  250. s3 := S_L;
  251. else
  252. internalerror(200109223);
  253. end;
  254. {$ifdef x86_64}
  255. OS_64,OS_S64:
  256. case s1 of
  257. OS_8,OS_S8:
  258. s3 := S_BQ;
  259. OS_16,OS_S16:
  260. s3 := S_WQ;
  261. OS_32,OS_S32:
  262. s3 := S_LQ;
  263. OS_64,OS_S64:
  264. s3 := S_Q;
  265. else
  266. internalerror(200304302);
  267. end;
  268. {$endif x86_64}
  269. else
  270. internalerror(200109227);
  271. end;
  272. if s3 in [S_B,S_W,S_L,S_Q] then
  273. op := A_MOV
  274. else if s1 in [OS_8,OS_16,OS_32,OS_64] then
  275. op := A_MOVZX
  276. else
  277. op := A_MOVSX;
  278. end;
  279. procedure tcgx86.floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
  280. begin
  281. case t of
  282. OS_F32 :
  283. begin
  284. op:=A_FLD;
  285. s:=S_FS;
  286. end;
  287. OS_F64 :
  288. begin
  289. op:=A_FLD;
  290. { ???? }
  291. s:=S_FL;
  292. end;
  293. OS_F80 :
  294. begin
  295. op:=A_FLD;
  296. s:=S_FX;
  297. end;
  298. OS_C64 :
  299. begin
  300. op:=A_FILD;
  301. s:=S_IQ;
  302. end;
  303. else
  304. internalerror(200204041);
  305. end;
  306. end;
  307. procedure tcgx86.floatload(list: taasmoutput; t : tcgsize;const ref : treference);
  308. var
  309. op : tasmop;
  310. s : topsize;
  311. begin
  312. floatloadops(t,op,s);
  313. list.concat(Taicpu.Op_ref(op,s,ref));
  314. inc_fpu_stack;
  315. end;
  316. procedure tcgx86.floatstoreops(t : tcgsize;var op : tasmop;var s : topsize);
  317. begin
  318. case t of
  319. OS_F32 :
  320. begin
  321. op:=A_FSTP;
  322. s:=S_FS;
  323. end;
  324. OS_F64 :
  325. begin
  326. op:=A_FSTP;
  327. s:=S_FL;
  328. end;
  329. OS_F80 :
  330. begin
  331. op:=A_FSTP;
  332. s:=S_FX;
  333. end;
  334. OS_C64 :
  335. begin
  336. op:=A_FISTP;
  337. s:=S_IQ;
  338. end;
  339. else
  340. internalerror(200204042);
  341. end;
  342. end;
  343. procedure tcgx86.floatstore(list: taasmoutput; t : tcgsize;const ref : treference);
  344. var
  345. op : tasmop;
  346. s : topsize;
  347. begin
  348. floatstoreops(t,op,s);
  349. list.concat(Taicpu.Op_ref(op,s,ref));
  350. dec_fpu_stack;
  351. end;
  352. procedure tcgx86.check_register_size(size:tcgsize;reg:tregister);
  353. begin
  354. if TCGSize2OpSize[size]<>TCGSize2OpSize[reg_cgsize(reg)] then
  355. internalerror(200306031);
  356. end;
  357. {****************************************************************************
  358. Assembler code
  359. ****************************************************************************}
  360. { currently does nothing }
  361. procedure tcgx86.a_jmp_always(list : taasmoutput;l: tasmlabel);
  362. begin
  363. a_jmp_cond(list, OC_NONE, l);
  364. end;
  365. { we implement the following routines because otherwise we can't }
  366. { instantiate the class since it's abstract }
  367. procedure tcgx86.a_param_reg(list : taasmoutput;size : tcgsize;r : tregister;const locpara : tparalocation);
  368. begin
  369. check_register_size(size,r);
  370. if (locpara.loc=LOC_REFERENCE) and
  371. (locpara.reference.index=NR_STACK_POINTER_REG) then
  372. begin
  373. case size of
  374. OS_8,OS_S8,
  375. OS_16,OS_S16:
  376. begin
  377. if locpara.alignment = 2 then
  378. list.concat(taicpu.op_reg(A_PUSH,S_W,makeregsize(r,OS_16)))
  379. else
  380. list.concat(taicpu.op_reg(A_PUSH,S_L,makeregsize(r,OS_32)));
  381. end;
  382. OS_32,OS_S32:
  383. begin
  384. if getsubreg(r)<>R_SUBD then
  385. internalerror(7843);
  386. list.concat(taicpu.op_reg(A_PUSH,S_L,r));
  387. end
  388. else
  389. internalerror(2002032212);
  390. end;
  391. end
  392. else
  393. inherited a_param_reg(list,size,r,locpara);
  394. end;
  395. procedure tcgx86.a_param_const(list : taasmoutput;size : tcgsize;a : aword;const locpara : tparalocation);
  396. begin
  397. if (locpara.loc=LOC_REFERENCE) and
  398. (locpara.reference.index=NR_STACK_POINTER_REG) then
  399. begin
  400. case size of
  401. OS_8,OS_S8,OS_16,OS_S16:
  402. begin
  403. if locpara.alignment = 2 then
  404. list.concat(taicpu.op_const(A_PUSH,S_W,a))
  405. else
  406. list.concat(taicpu.op_const(A_PUSH,S_L,a));
  407. end;
  408. OS_32,OS_S32:
  409. list.concat(taicpu.op_const(A_PUSH,S_L,a));
  410. else
  411. internalerror(2002032213);
  412. end;
  413. end
  414. else
  415. inherited a_param_const(list,size,a,locpara);
  416. end;
  417. procedure tcgx86.a_param_ref(list : taasmoutput;size : tcgsize;const r : treference;const locpara : tparalocation);
  418. var
  419. pushsize : tcgsize;
  420. tmpreg : tregister;
  421. begin
  422. if (locpara.loc=LOC_REFERENCE) and
  423. (locpara.reference.index=NR_STACK_POINTER_REG) then
  424. begin
  425. case size of
  426. OS_8,OS_S8,
  427. OS_16,OS_S16:
  428. begin
  429. if locpara.alignment = 2 then
  430. pushsize:=OS_16
  431. else
  432. pushsize:=OS_32;
  433. tmpreg:=getintregister(list,pushsize);
  434. a_load_ref_reg(list,size,pushsize,r,tmpreg);
  435. list.concat(taicpu.op_reg(A_PUSH,TCgsize2opsize[pushsize],tmpreg));
  436. ungetregister(list,tmpreg);
  437. end;
  438. OS_32,OS_S32:
  439. list.concat(taicpu.op_ref(A_PUSH,S_L,r));
  440. {$ifdef cpu64bit}
  441. OS_64,OS_S64:
  442. list.concat(taicpu.op_ref(A_PUSH,S_Q,r));
  443. {$endif cpu64bit}
  444. else
  445. internalerror(2002032214);
  446. end;
  447. end
  448. else
  449. inherited a_param_ref(list,size,r,locpara);
  450. end;
  451. procedure tcgx86.a_paramaddr_ref(list : taasmoutput;const r : treference;const locpara : tparalocation);
  452. var
  453. tmpreg : tregister;
  454. begin
  455. if (r.segment<>NR_NO) then
  456. CGMessage(cg_e_cant_use_far_pointer_there);
  457. if (locpara.loc=LOC_REFERENCE) and
  458. (locpara.reference.index=NR_STACK_POINTER_REG) then
  459. begin
  460. if (r.base=NR_NO) and (r.index=NR_NO) then
  461. begin
  462. if assigned(r.symbol) then
  463. list.concat(Taicpu.Op_sym_ofs(A_PUSH,S_L,r.symbol,r.offset))
  464. else
  465. list.concat(Taicpu.Op_const(A_PUSH,S_L,r.offset));
  466. end
  467. else if (r.base=NR_NO) and (r.index<>NR_NO) and
  468. (r.offset=0) and (r.scalefactor=0) and (r.symbol=nil) then
  469. list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.index))
  470. else if (r.base<>NR_NO) and (r.index=NR_NO) and
  471. (r.offset=0) and (r.symbol=nil) then
  472. list.concat(Taicpu.Op_reg(A_PUSH,S_L,r.base))
  473. else
  474. begin
  475. tmpreg:=getaddressregister(list);
  476. a_loadaddr_ref_reg(list,r,tmpreg);
  477. ungetregister(list,tmpreg);
  478. list.concat(taicpu.op_reg(A_PUSH,S_L,tmpreg));
  479. end;
  480. end
  481. else
  482. inherited a_paramaddr_ref(list,r,locpara);
  483. end;
  484. procedure tcgx86.a_call_name(list : taasmoutput;const s : string);
  485. begin
  486. list.concat(taicpu.op_sym(A_CALL,S_NO,objectlibrary.newasmsymbol(s)));
  487. end;
  488. procedure tcgx86.a_call_reg(list : taasmoutput;reg : tregister);
  489. begin
  490. list.concat(taicpu.op_reg(A_CALL,S_NO,reg));
  491. end;
  492. {********************** load instructions ********************}
  493. procedure tcgx86.a_load_const_reg(list : taasmoutput; tosize: TCGSize; a : aword; reg : TRegister);
  494. begin
  495. check_register_size(tosize,reg);
  496. { the optimizer will change it to "xor reg,reg" when loading zero, }
  497. { no need to do it here too (JM) }
  498. list.concat(taicpu.op_const_reg(A_MOV,TCGSize2OpSize[tosize],a,reg))
  499. end;
  500. procedure tcgx86.a_load_const_ref(list : taasmoutput; tosize: tcgsize; a : aword;const ref : treference);
  501. begin
  502. list.concat(taicpu.op_const_ref(A_MOV,TCGSize2OpSize[tosize],a,ref));
  503. end;
  504. procedure tcgx86.a_load_reg_ref(list : taasmoutput; fromsize,tosize: TCGSize; reg : tregister;const ref : treference);
  505. var
  506. op: tasmop;
  507. s: topsize;
  508. tmpreg : tregister;
  509. begin
  510. check_register_size(fromsize,reg);
  511. sizes2load(fromsize,tosize,op,s);
  512. case s of
  513. S_BW,S_BL,S_WL
  514. {$ifdef x86_64}
  515. ,S_BQ,S_WQ,S_LQ
  516. {$endif x86_64}
  517. :
  518. begin
  519. tmpreg:=getintregister(list,tosize);
  520. list.concat(taicpu.op_reg_reg(op,s,reg,tmpreg));
  521. a_load_reg_ref(list,tosize,tosize,tmpreg,ref);
  522. ungetregister(list,tmpreg);
  523. end;
  524. else
  525. list.concat(taicpu.op_reg_ref(op,s,reg,ref));
  526. end;
  527. end;
  528. procedure tcgx86.a_load_ref_reg(list : taasmoutput;fromsize,tosize : tcgsize;const ref: treference;reg : tregister);
  529. var
  530. op: tasmop;
  531. s: topsize;
  532. begin
  533. check_register_size(tosize,reg);
  534. sizes2load(fromsize,tosize,op,s);
  535. list.concat(taicpu.op_ref_reg(op,s,ref,reg));
  536. end;
  537. procedure tcgx86.a_load_reg_reg(list : taasmoutput;fromsize,tosize : tcgsize;reg1,reg2 : tregister);
  538. var
  539. op: tasmop;
  540. s: topsize;
  541. eq:boolean;
  542. instr:Taicpu;
  543. begin
  544. check_register_size(fromsize,reg1);
  545. check_register_size(tosize,reg2);
  546. sizes2load(fromsize,tosize,op,s);
  547. eq:=getsupreg(reg1)=getsupreg(reg2);
  548. if eq then
  549. begin
  550. { "mov reg1, reg1" doesn't make sense }
  551. if op = A_MOV then
  552. exit;
  553. end;
  554. instr:=taicpu.op_reg_reg(op,s,reg1,reg2);
  555. {Notify the register allocator that we have written a move instruction so
  556. it can try to eliminate it.}
  557. add_move_instruction(instr);
  558. list.concat(instr);
  559. end;
  560. procedure tcgx86.a_loadaddr_ref_reg(list : taasmoutput;const ref : treference;r : tregister);
  561. begin
  562. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  563. begin
  564. if assigned(ref.symbol) then
  565. list.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,ref.symbol,ref.offset,r))
  566. else
  567. a_load_const_reg(list,OS_INT,ref.offset,r);
  568. end
  569. else if (ref.base=NR_NO) and (ref.index<>NR_NO) and
  570. (ref.offset=0) and (ref.scalefactor=0) and (ref.symbol=nil) then
  571. a_load_reg_reg(list,OS_INT,OS_INT,ref.index,r)
  572. else if (ref.base<>NR_NO) and (ref.index=NR_NO) and
  573. (ref.offset=0) and (ref.symbol=nil) then
  574. a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r)
  575. else
  576. list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,r));
  577. end;
  578. { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
  579. { R_ST means "the current value at the top of the fpu stack" (JM) }
  580. procedure tcgx86.a_loadfpu_reg_reg(list: taasmoutput; size: tcgsize; reg1, reg2: tregister);
  581. begin
  582. if (reg1<>NR_ST) then
  583. begin
  584. list.concat(taicpu.op_reg(A_FLD,S_NO,rgfpu.correct_fpuregister(reg1,rgfpu.fpuvaroffset)));
  585. inc_fpu_stack;
  586. end;
  587. if (reg2<>NR_ST) then
  588. begin
  589. list.concat(taicpu.op_reg(A_FSTP,S_NO,rgfpu.correct_fpuregister(reg2,rgfpu.fpuvaroffset)));
  590. dec_fpu_stack;
  591. end;
  592. end;
  593. procedure tcgx86.a_loadfpu_ref_reg(list: taasmoutput; size: tcgsize; const ref: treference; reg: tregister);
  594. begin
  595. floatload(list,size,ref);
  596. if (reg<>NR_ST) then
  597. a_loadfpu_reg_reg(list,size,NR_ST,reg);
  598. end;
  599. procedure tcgx86.a_loadfpu_reg_ref(list: taasmoutput; size: tcgsize; reg: tregister; const ref: treference);
  600. begin
  601. if reg<>NR_ST then
  602. a_loadfpu_reg_reg(list,size,reg,NR_ST);
  603. floatstore(list,size,ref);
  604. end;
  605. function get_scalar_mm_op(fromsize,tosize : tcgsize) : tasmop;
  606. begin
  607. case fromsize of
  608. OS_F32:
  609. case tosize of
  610. OS_F64:
  611. result:=A_CVTSS2SD;
  612. OS_F32:
  613. result:=A_MOVSS;
  614. else
  615. internalerror(200312205);
  616. end;
  617. OS_F64:
  618. case tosize of
  619. OS_F64:
  620. result:=A_MOVSD;
  621. OS_F32:
  622. result:=A_CVTSD2SS;
  623. else
  624. internalerror(200312204);
  625. end;
  626. else
  627. internalerror(200312203);
  628. end;
  629. end;
  630. procedure tcgx86.a_loadmm_reg_reg(list: taasmoutput; fromsize, tosize : tcgsize;reg1, reg2: tregister;shuffle : pmmshuffle);
  631. begin
  632. if shuffle=nil then
  633. begin
  634. if fromsize=tosize then
  635. list.concat(taicpu.op_reg_reg(A_MOVAPS,S_NO,reg1,reg2))
  636. else
  637. internalerror(200312202);
  638. end
  639. else if shufflescalar(shuffle) then
  640. list.concat(taicpu.op_reg_reg(get_scalar_mm_op(fromsize,tosize),S_NO,reg1,reg2))
  641. else
  642. internalerror(200312201);
  643. end;
  644. procedure tcgx86.a_loadmm_ref_reg(list: taasmoutput; fromsize, tosize : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
  645. begin
  646. if shuffle=nil then
  647. begin
  648. list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,ref,reg));
  649. end
  650. else if shufflescalar(shuffle) then
  651. list.concat(taicpu.op_ref_reg(get_scalar_mm_op(fromsize,tosize),S_NO,ref,reg))
  652. else
  653. internalerror(200312252);
  654. end;
  655. procedure tcgx86.a_loadmm_reg_ref(list: taasmoutput; fromsize, tosize : tcgsize;reg: tregister; const ref: treference;shuffle : pmmshuffle);
  656. begin
  657. if shuffle=nil then
  658. begin
  659. list.concat(taicpu.op_ref_reg(A_MOVQ,S_NO,ref,reg));
  660. end
  661. else if shufflescalar(shuffle) then
  662. list.concat(taicpu.op_reg_ref(get_scalar_mm_op(fromsize,tosize),S_NO,reg,ref))
  663. else
  664. internalerror(200312252);
  665. end;
  666. procedure tcgx86.a_opmm_ref_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;const ref: treference; reg: tregister;shuffle : pmmshuffle);
  667. var
  668. l : tlocation;
  669. begin
  670. l.loc:=LOC_REFERENCE;
  671. l.reference:=ref;
  672. l.size:=size;
  673. opmm_loc_reg(list,op,size,l,reg,shuffle);
  674. end;
  675. procedure tcgx86.a_opmm_reg_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;src,dst: tregister;shuffle : pmmshuffle);
  676. var
  677. l : tlocation;
  678. begin
  679. l.loc:=LOC_MMREGISTER;
  680. l.register:=src;
  681. l.size:=size;
  682. opmm_loc_reg(list,op,size,l,dst,shuffle);
  683. end;
  684. procedure tcgx86.opmm_loc_reg(list: taasmoutput; Op: TOpCG; size : tcgsize;loc : tlocation;dst: tregister; shuffle : pmmshuffle);
  685. const
  686. opmm2asmop : array[0..1,OS_F32..OS_F64,topcg] of tasmop = (
  687. ( { scalar }
  688. ( { OS_F32 }
  689. A_NOP,A_ADDSS,A_NOP,A_DIVSS,A_NOP,A_NOP,A_MULSS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSS,A_NOP
  690. ),
  691. ( { OS_F64 }
  692. A_NOP,A_ADDSD,A_NOP,A_DIVSD,A_NOP,A_NOP,A_MULSD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_SUBSD,A_NOP
  693. )
  694. ),
  695. ( { vectorized/packed }
  696. { because the logical packed single instructions have shorter op codes, we use always
  697. these
  698. }
  699. ( { OS_F32 }
  700. A_NOP,A_ADDPS,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
  701. ),
  702. ( { OS_F64 }
  703. A_NOP,A_ADDPD,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_NOP,A_XORPS
  704. )
  705. )
  706. );
  707. var
  708. resultreg : tregister;
  709. asmop : tasmop;
  710. begin
  711. { this is an internally used procedure so the parameters have
  712. some constrains
  713. }
  714. if loc.size<>size then
  715. internalerror(200312213);
  716. resultreg:=dst;
  717. { deshuffle }
  718. //!!!
  719. if (shuffle<>nil) and not(shufflescalar(shuffle)) then
  720. begin
  721. end
  722. else if (shuffle=nil) then
  723. asmop:=opmm2asmop[1,size,op]
  724. else if shufflescalar(shuffle) then
  725. begin
  726. asmop:=opmm2asmop[0,size,op];
  727. { no scalar operation available? }
  728. if asmop=A_NOP then
  729. begin
  730. { do vectorized and shuffle finally }
  731. //!!!
  732. end;
  733. end
  734. else
  735. internalerror(200312211);
  736. if asmop=A_NOP then
  737. internalerror(200312215);
  738. case loc.loc of
  739. LOC_CREFERENCE,LOC_REFERENCE:
  740. list.concat(taicpu.op_ref_reg(asmop,S_NO,loc.reference,resultreg));
  741. LOC_CMMREGISTER,LOC_MMREGISTER:
  742. list.concat(taicpu.op_reg_reg(asmop,S_NO,loc.register,resultreg));
  743. else
  744. internalerror(200312214);
  745. end;
  746. { shuffle }
  747. if resultreg<>dst then
  748. begin
  749. internalerror(200312212);
  750. end;
  751. end;
  752. procedure tcgx86.a_op_const_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; reg: TRegister);
  753. var
  754. opcode: tasmop;
  755. power: longint;
  756. begin
  757. check_register_size(size,reg);
  758. case op of
  759. OP_DIV, OP_IDIV:
  760. begin
  761. if ispowerof2(a,power) then
  762. begin
  763. case op of
  764. OP_DIV:
  765. opcode := A_SHR;
  766. OP_IDIV:
  767. opcode := A_SAR;
  768. end;
  769. list.concat(taicpu.op_const_reg(opcode,TCgSize2OpSize[size],power,reg));
  770. exit;
  771. end;
  772. { the rest should be handled specifically in the code }
  773. { generator because of the silly register usage restraints }
  774. internalerror(200109224);
  775. end;
  776. OP_MUL,OP_IMUL:
  777. begin
  778. if not(cs_check_overflow in aktlocalswitches) and
  779. ispowerof2(a,power) then
  780. begin
  781. list.concat(taicpu.op_const_reg(A_SHL,TCgSize2OpSize[size],power,reg));
  782. exit;
  783. end;
  784. if op = OP_IMUL then
  785. list.concat(taicpu.op_const_reg(A_IMUL,TCgSize2OpSize[size],a,reg))
  786. else
  787. { OP_MUL should be handled specifically in the code }
  788. { generator because of the silly register usage restraints }
  789. internalerror(200109225);
  790. end;
  791. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  792. if not(cs_check_overflow in aktlocalswitches) and
  793. (a = 1) and
  794. (op in [OP_ADD,OP_SUB]) then
  795. if op = OP_ADD then
  796. list.concat(taicpu.op_reg(A_INC,TCgSize2OpSize[size],reg))
  797. else
  798. list.concat(taicpu.op_reg(A_DEC,TCgSize2OpSize[size],reg))
  799. else if (a = 0) then
  800. if (op <> OP_AND) then
  801. exit
  802. else
  803. list.concat(taicpu.op_const_reg(A_MOV,TCgSize2OpSize[size],0,reg))
  804. else if (a = high(aword)) and
  805. (op in [OP_AND,OP_OR,OP_XOR]) then
  806. begin
  807. case op of
  808. OP_AND:
  809. exit;
  810. OP_OR:
  811. list.concat(taicpu.op_const_reg(A_MOV,TCgSize2OpSize[size],high(aword),reg));
  812. OP_XOR:
  813. list.concat(taicpu.op_reg(A_NOT,TCgSize2OpSize[size],reg));
  814. end
  815. end
  816. else
  817. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],a,reg));
  818. OP_SHL,OP_SHR,OP_SAR:
  819. begin
  820. if (a and 31) <> 0 Then
  821. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,reg));
  822. if (a shr 5) <> 0 Then
  823. internalerror(68991);
  824. end
  825. else internalerror(68992);
  826. end;
  827. end;
  828. procedure tcgx86.a_op_const_ref(list : taasmoutput; Op: TOpCG; size: TCGSize; a: AWord; const ref: TReference);
  829. var
  830. opcode: tasmop;
  831. power: longint;
  832. begin
  833. Case Op of
  834. OP_DIV, OP_IDIV:
  835. Begin
  836. if ispowerof2(a,power) then
  837. begin
  838. case op of
  839. OP_DIV:
  840. opcode := A_SHR;
  841. OP_IDIV:
  842. opcode := A_SAR;
  843. end;
  844. list.concat(taicpu.op_const_ref(opcode,
  845. TCgSize2OpSize[size],power,ref));
  846. exit;
  847. end;
  848. { the rest should be handled specifically in the code }
  849. { generator because of the silly register usage restraints }
  850. internalerror(200109231);
  851. End;
  852. OP_MUL,OP_IMUL:
  853. begin
  854. if not(cs_check_overflow in aktlocalswitches) and
  855. ispowerof2(a,power) then
  856. begin
  857. list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
  858. power,ref));
  859. exit;
  860. end;
  861. { can't multiply a memory location directly with a constant }
  862. if op = OP_IMUL then
  863. inherited a_op_const_ref(list,op,size,a,ref)
  864. else
  865. { OP_MUL should be handled specifically in the code }
  866. { generator because of the silly register usage restraints }
  867. internalerror(200109232);
  868. end;
  869. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  870. if not(cs_check_overflow in aktlocalswitches) and
  871. (a = 1) and
  872. (op in [OP_ADD,OP_SUB]) then
  873. if op = OP_ADD then
  874. list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
  875. else
  876. list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
  877. else if (a = 0) then
  878. if (op <> OP_AND) then
  879. exit
  880. else
  881. a_load_const_ref(list,size,0,ref)
  882. else if (a = high(aword)) and
  883. (op in [OP_AND,OP_OR,OP_XOR]) then
  884. begin
  885. case op of
  886. OP_AND:
  887. exit;
  888. OP_OR:
  889. list.concat(taicpu.op_const_ref(A_MOV,TCgSize2OpSize[size],high(aword),ref));
  890. OP_XOR:
  891. list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref));
  892. end
  893. end
  894. else
  895. list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
  896. TCgSize2OpSize[size],a,ref));
  897. OP_SHL,OP_SHR,OP_SAR:
  898. begin
  899. if (a and 31) <> 0 then
  900. list.concat(taicpu.op_const_ref(
  901. TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
  902. if (a shr 5) <> 0 Then
  903. internalerror(68991);
  904. end
  905. else internalerror(68992);
  906. end;
  907. end;
  908. procedure tcgx86.a_op_reg_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; src, dst: TRegister);
  909. var
  910. dstsize: topsize;
  911. instr:Taicpu;
  912. begin
  913. check_register_size(size,src);
  914. check_register_size(size,dst);
  915. dstsize := tcgsize2opsize[size];
  916. case op of
  917. OP_NEG,OP_NOT:
  918. begin
  919. if src<>dst then
  920. a_load_reg_reg(list,size,size,src,dst);
  921. list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
  922. end;
  923. OP_MUL,OP_DIV,OP_IDIV:
  924. { special stuff, needs separate handling inside code }
  925. { generator }
  926. internalerror(200109233);
  927. OP_SHR,OP_SHL,OP_SAR:
  928. begin
  929. getexplicitregister(list,NR_CL);
  930. a_load_reg_reg(list,size,OS_8,dst,NR_CL);
  931. list.concat(taicpu.op_reg_reg(Topcg2asmop[op],S_B,src,NR_CL));
  932. ungetregister(list,NR_CL);
  933. end;
  934. else
  935. begin
  936. if reg2opsize(src) <> dstsize then
  937. internalerror(200109226);
  938. instr:=taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,src,dst);
  939. list.concat(instr);
  940. end;
  941. end;
  942. end;
  943. procedure tcgx86.a_op_ref_reg(list : taasmoutput; Op: TOpCG; size: TCGSize; const ref: TReference; reg: TRegister);
  944. begin
  945. check_register_size(size,reg);
  946. case op of
  947. OP_NEG,OP_NOT,OP_IMUL:
  948. begin
  949. inherited a_op_ref_reg(list,op,size,ref,reg);
  950. end;
  951. OP_MUL,OP_DIV,OP_IDIV:
  952. { special stuff, needs separate handling inside code }
  953. { generator }
  954. internalerror(200109239);
  955. else
  956. begin
  957. reg := makeregsize(reg,size);
  958. list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],tcgsize2opsize[size],ref,reg));
  959. end;
  960. end;
  961. end;
  962. procedure tcgx86.a_op_reg_ref(list : taasmoutput; Op: TOpCG; size: TCGSize;reg: TRegister; const ref: TReference);
  963. begin
  964. check_register_size(size,reg);
  965. case op of
  966. OP_NEG,OP_NOT:
  967. begin
  968. if reg<>NR_NO then
  969. internalerror(200109237);
  970. list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
  971. end;
  972. OP_IMUL:
  973. begin
  974. { this one needs a load/imul/store, which is the default }
  975. inherited a_op_ref_reg(list,op,size,ref,reg);
  976. end;
  977. OP_MUL,OP_DIV,OP_IDIV:
  978. { special stuff, needs separate handling inside code }
  979. { generator }
  980. internalerror(200109238);
  981. else
  982. begin
  983. list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],reg,ref));
  984. end;
  985. end;
  986. end;
  987. procedure tcgx86.a_op_const_reg_reg(list: taasmoutput; op: TOpCg; size: tcgsize; a: aword; src, dst: tregister);
  988. var
  989. tmpref: treference;
  990. power: longint;
  991. begin
  992. check_register_size(size,src);
  993. check_register_size(size,dst);
  994. if not (size in [OS_32,OS_S32]) then
  995. begin
  996. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  997. exit;
  998. end;
  999. { if we get here, we have to do a 32 bit calculation, guaranteed }
  1000. case op of
  1001. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  1002. OP_SAR:
  1003. { can't do anything special for these }
  1004. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  1005. OP_IMUL:
  1006. begin
  1007. if not(cs_check_overflow in aktlocalswitches) and
  1008. ispowerof2(a,power) then
  1009. { can be done with a shift }
  1010. begin
  1011. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  1012. exit;
  1013. end;
  1014. list.concat(taicpu.op_const_reg_reg(A_IMUL,S_L,a,src,dst));
  1015. end;
  1016. OP_ADD, OP_SUB:
  1017. if (a = 0) then
  1018. a_load_reg_reg(list,size,size,src,dst)
  1019. else
  1020. begin
  1021. reference_reset(tmpref);
  1022. tmpref.base := src;
  1023. tmpref.offset := longint(a);
  1024. if op = OP_SUB then
  1025. tmpref.offset := -tmpref.offset;
  1026. list.concat(taicpu.op_ref_reg(A_LEA,S_L,tmpref,dst));
  1027. end
  1028. else internalerror(200112302);
  1029. end;
  1030. end;
  1031. procedure tcgx86.a_op_reg_reg_reg(list: taasmoutput; op: TOpCg;size: tcgsize; src1, src2, dst: tregister);
  1032. var
  1033. tmpref: treference;
  1034. begin
  1035. check_register_size(size,src1);
  1036. check_register_size(size,src2);
  1037. check_register_size(size,dst);
  1038. if not(size in [OS_32,OS_S32]) then
  1039. begin
  1040. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  1041. exit;
  1042. end;
  1043. { if we get here, we have to do a 32 bit calculation, guaranteed }
  1044. Case Op of
  1045. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  1046. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  1047. { can't do anything special for these }
  1048. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  1049. OP_IMUL:
  1050. list.concat(taicpu.op_reg_reg_reg(A_IMUL,S_L,src1,src2,dst));
  1051. OP_ADD:
  1052. begin
  1053. reference_reset(tmpref);
  1054. tmpref.base := src1;
  1055. tmpref.index := src2;
  1056. tmpref.scalefactor := 1;
  1057. list.concat(taicpu.op_ref_reg(A_LEA,S_L,tmpref,dst));
  1058. end
  1059. else internalerror(200112303);
  1060. end;
  1061. end;
  1062. {*************** compare instructructions ****************}
  1063. procedure tcgx86.a_cmp_const_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;reg : tregister;
  1064. l : tasmlabel);
  1065. begin
  1066. if (a = 0) then
  1067. list.concat(taicpu.op_reg_reg(A_TEST,tcgsize2opsize[size],reg,reg))
  1068. else
  1069. list.concat(taicpu.op_const_reg(A_CMP,tcgsize2opsize[size],a,reg));
  1070. a_jmp_cond(list,cmp_op,l);
  1071. end;
  1072. procedure tcgx86.a_cmp_const_ref_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;a : aword;const ref : treference;
  1073. l : tasmlabel);
  1074. begin
  1075. list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,ref));
  1076. a_jmp_cond(list,cmp_op,l);
  1077. end;
  1078. procedure tcgx86.a_cmp_reg_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;
  1079. reg1,reg2 : tregister;l : tasmlabel);
  1080. begin
  1081. check_register_size(size,reg1);
  1082. check_register_size(size,reg2);
  1083. list.concat(taicpu.op_reg_reg(A_CMP,TCgSize2OpSize[size],reg1,reg2));
  1084. a_jmp_cond(list,cmp_op,l);
  1085. end;
  1086. procedure tcgx86.a_cmp_ref_reg_label(list : taasmoutput;size : tcgsize;cmp_op : topcmp;const ref: treference; reg : tregister;l : tasmlabel);
  1087. begin
  1088. check_register_size(size,reg);
  1089. list.concat(taicpu.op_ref_reg(A_CMP,TCgSize2OpSize[size],ref,reg));
  1090. a_jmp_cond(list,cmp_op,l);
  1091. end;
  1092. procedure tcgx86.a_jmp_cond(list : taasmoutput;cond : TOpCmp;l: tasmlabel);
  1093. var
  1094. ai : taicpu;
  1095. begin
  1096. if cond=OC_None then
  1097. ai := Taicpu.Op_sym(A_JMP,S_NO,l)
  1098. else
  1099. begin
  1100. ai:=Taicpu.Op_sym(A_Jcc,S_NO,l);
  1101. ai.SetCondition(TOpCmp2AsmCond[cond]);
  1102. end;
  1103. ai.is_jmp:=true;
  1104. list.concat(ai);
  1105. end;
  1106. procedure tcgx86.a_jmp_flags(list : taasmoutput;const f : TResFlags;l: tasmlabel);
  1107. var
  1108. ai : taicpu;
  1109. begin
  1110. ai := Taicpu.op_sym(A_Jcc,S_NO,l);
  1111. ai.SetCondition(flags_to_cond(f));
  1112. ai.is_jmp := true;
  1113. list.concat(ai);
  1114. end;
  1115. procedure tcgx86.g_flags2reg(list: taasmoutput; size: TCgSize; const f: tresflags; reg: TRegister);
  1116. var
  1117. ai : taicpu;
  1118. hreg : tregister;
  1119. begin
  1120. hreg:=makeregsize(reg,OS_8);
  1121. ai:=Taicpu.op_reg(A_SETcc,S_B,hreg);
  1122. ai.setcondition(flags_to_cond(f));
  1123. list.concat(ai);
  1124. if (reg<>hreg) then
  1125. a_load_reg_reg(list,OS_8,size,hreg,reg);
  1126. end;
  1127. procedure tcgx86.g_flags2ref(list: taasmoutput; size: TCgSize; const f: tresflags; const ref: TReference);
  1128. var
  1129. ai : taicpu;
  1130. begin
  1131. if not(size in [OS_8,OS_S8]) then
  1132. a_load_const_ref(list,size,0,ref);
  1133. ai:=Taicpu.op_ref(A_SETcc,S_B,ref);
  1134. ai.setcondition(flags_to_cond(f));
  1135. list.concat(ai);
  1136. end;
  1137. { ************* concatcopy ************ }
  1138. procedure Tcgx86.g_concatcopy(list:Taasmoutput;const source,dest:Treference;
  1139. len:aword;delsource,loadref:boolean);
  1140. type copymode=(copy_move,copy_mmx,copy_string);
  1141. var srcref,dstref:Treference;
  1142. r,r0,r1,r2,r3:Tregister;
  1143. helpsize:aword;
  1144. copysize:byte;
  1145. cgsize:Tcgsize;
  1146. cm:copymode;
  1147. begin
  1148. cm:=copy_move;
  1149. helpsize:=12;
  1150. if cs_littlesize in aktglobalswitches then
  1151. helpsize:=8;
  1152. if (cs_mmx in aktlocalswitches) and
  1153. not(pi_uses_fpu in current_procinfo.flags) and
  1154. ((len=8) or (len=16) or (len=24) or (len=32)) then
  1155. cm:=copy_mmx;
  1156. if (cs_littlesize in aktglobalswitches) and
  1157. (len>helpsize) and
  1158. not((len<=16) and (cm=copy_mmx)) then
  1159. cm:=copy_string;
  1160. if loadref then
  1161. cm:=copy_string;
  1162. case cm of
  1163. copy_move:
  1164. begin
  1165. dstref:=dest;
  1166. srcref:=source;
  1167. copysize:=4;
  1168. cgsize:=OS_32;
  1169. while len<>0 do
  1170. begin
  1171. if len<2 then
  1172. begin
  1173. copysize:=1;
  1174. cgsize:=OS_8;
  1175. end
  1176. else if len<4 then
  1177. begin
  1178. copysize:=2;
  1179. cgsize:=OS_16;
  1180. end;
  1181. dec(len,copysize);
  1182. if (len=0) and delsource then
  1183. reference_release(list,source);
  1184. r:=getintregister(list,cgsize);
  1185. a_load_ref_reg(list,cgsize,cgsize,srcref,r);
  1186. ungetregister(list,r);
  1187. a_load_reg_ref(list,cgsize,cgsize,r,dstref);
  1188. inc(srcref.offset,copysize);
  1189. inc(dstref.offset,copysize);
  1190. end;
  1191. end;
  1192. copy_mmx:
  1193. begin
  1194. dstref:=dest;
  1195. srcref:=source;
  1196. r0:=getmmxregister(list);
  1197. a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r0,nil);
  1198. if len>=16 then
  1199. begin
  1200. inc(srcref.offset,8);
  1201. r1:=getmmxregister(list);
  1202. a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r1,nil);
  1203. end;
  1204. if len>=24 then
  1205. begin
  1206. inc(srcref.offset,8);
  1207. r2:=getmmxregister(list);
  1208. a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r2,nil);
  1209. end;
  1210. if len>=32 then
  1211. begin
  1212. inc(srcref.offset,8);
  1213. r3:=getmmxregister(list);
  1214. a_loadmm_ref_reg(list,OS_M64,OS_M64,srcref,r3,nil);
  1215. end;
  1216. a_loadmm_reg_ref(list,OS_M64,OS_M64,r0,dstref,nil);
  1217. ungetregister(list,r0);
  1218. if len>=16 then
  1219. begin
  1220. inc(dstref.offset,8);
  1221. a_loadmm_reg_ref(list,OS_M64,OS_M64,r1,dstref,nil);
  1222. ungetregister(list,r1);
  1223. end;
  1224. if len>=24 then
  1225. begin
  1226. inc(dstref.offset,8);
  1227. a_loadmm_reg_ref(list,OS_M64,OS_M64,r2,dstref,nil);
  1228. ungetregister(list,r2);
  1229. end;
  1230. if len>=32 then
  1231. begin
  1232. inc(dstref.offset,8);
  1233. a_loadmm_reg_ref(list,OS_M64,OS_M64,r3,dstref,nil);
  1234. ungetregister(list,r3);
  1235. end;
  1236. end
  1237. else {copy_string, should be a good fallback in case of unhandled}
  1238. begin
  1239. getexplicitregister(list,NR_EDI);
  1240. a_loadaddr_ref_reg(list,dest,NR_EDI);
  1241. getexplicitregister(list,NR_ESI);
  1242. if loadref then
  1243. a_load_ref_reg(list,OS_ADDR,OS_ADDR,source,NR_ESI)
  1244. else
  1245. begin
  1246. a_loadaddr_ref_reg(list,source,NR_ESI);
  1247. if delsource then
  1248. begin
  1249. srcref:=source;
  1250. { Don't release ESI register yet, it's needed
  1251. by the movsl }
  1252. if (srcref.base=NR_ESI) then
  1253. srcref.base:=NR_NO
  1254. else if (srcref.index=NR_ESI) then
  1255. srcref.index:=NR_NO;
  1256. reference_release(list,srcref);
  1257. end;
  1258. end;
  1259. getexplicitregister(list,NR_ECX);
  1260. list.concat(Taicpu.op_none(A_CLD,S_NO));
  1261. if cs_littlesize in aktglobalswitches then
  1262. begin
  1263. a_load_const_reg(list,OS_INT,len,NR_ECX);
  1264. list.concat(Taicpu.op_none(A_REP,S_NO));
  1265. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  1266. end
  1267. else
  1268. begin
  1269. helpsize:=len shr 2;
  1270. len:=len and 3;
  1271. if helpsize>1 then
  1272. begin
  1273. a_load_const_reg(list,OS_INT,helpsize,NR_ECX);
  1274. list.concat(Taicpu.op_none(A_REP,S_NO));
  1275. end;
  1276. if helpsize>0 then
  1277. list.concat(Taicpu.op_none(A_MOVSL,S_NO));
  1278. if len>1 then
  1279. begin
  1280. dec(len,2);
  1281. list.concat(Taicpu.op_none(A_MOVSW,S_NO));
  1282. end;
  1283. if len=1 then
  1284. list.concat(Taicpu.op_none(A_MOVSB,S_NO));
  1285. end;
  1286. ungetregister(list,NR_ECX);
  1287. ungetregister(list,NR_ESI);
  1288. ungetregister(list,NR_EDI);
  1289. end;
  1290. end;
  1291. if delsource then
  1292. tg.ungetiftemp(list,source);
  1293. end;
  1294. procedure tcgx86.g_exception_reason_save(list : taasmoutput; const href : treference);
  1295. begin
  1296. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
  1297. end;
  1298. procedure tcgx86.g_exception_reason_save_const(list : taasmoutput;const href : treference; a: aword);
  1299. begin
  1300. list.concat(Taicpu.op_const(A_PUSH,S_L,a));
  1301. end;
  1302. procedure tcgx86.g_exception_reason_load(list : taasmoutput; const href : treference);
  1303. begin
  1304. list.concat(Taicpu.op_reg(A_POP,S_L,NR_EAX));
  1305. end;
  1306. {****************************************************************************
  1307. Entry/Exit Code Helpers
  1308. ****************************************************************************}
  1309. procedure tcgx86.g_copyvaluepara_openarray(list : taasmoutput;const ref, lenref:treference;elesize:aword);
  1310. var
  1311. power,len : longint;
  1312. opsize : topsize;
  1313. {$ifndef __NOWINPECOFF__}
  1314. again,ok : tasmlabel;
  1315. {$endif}
  1316. begin
  1317. { get stack space }
  1318. getexplicitregister(list,NR_EDI);
  1319. list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,NR_EDI));
  1320. list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
  1321. if (elesize<>1) then
  1322. begin
  1323. if ispowerof2(elesize, power) then
  1324. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
  1325. else
  1326. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
  1327. end;
  1328. {$ifndef __NOWINPECOFF__}
  1329. { windows guards only a few pages for stack growing, }
  1330. { so we have to access every page first }
  1331. if target_info.system=system_i386_win32 then
  1332. begin
  1333. objectlibrary.getlabel(again);
  1334. objectlibrary.getlabel(ok);
  1335. a_label(list,again);
  1336. list.concat(Taicpu.op_const_reg(A_CMP,S_L,winstackpagesize,NR_EDI));
  1337. a_jmp_cond(list,OC_B,ok);
  1338. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
  1339. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EDI));
  1340. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize,NR_EDI));
  1341. a_jmp_always(list,again);
  1342. a_label(list,ok);
  1343. list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
  1344. ungetregister(list,NR_EDI);
  1345. { now reload EDI }
  1346. getexplicitregister(list,NR_EDI);
  1347. list.concat(Taicpu.op_ref_reg(A_MOV,S_L,lenref,NR_EDI));
  1348. list.concat(Taicpu.op_reg(A_INC,S_L,NR_EDI));
  1349. if (elesize<>1) then
  1350. begin
  1351. if ispowerof2(elesize, power) then
  1352. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_EDI))
  1353. else
  1354. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,elesize,NR_EDI));
  1355. end;
  1356. end
  1357. else
  1358. {$endif __NOWINPECOFF__}
  1359. list.concat(Taicpu.op_reg_reg(A_SUB,S_L,NR_EDI,NR_ESP));
  1360. { align stack on 4 bytes }
  1361. list.concat(Taicpu.op_const_reg(A_AND,S_L,$fffffff4,NR_ESP));
  1362. { load destination }
  1363. a_load_reg_reg(list,OS_INT,OS_INT,NR_ESP,NR_EDI);
  1364. { Allocate other registers }
  1365. getexplicitregister(list,NR_ECX);
  1366. getexplicitregister(list,NR_ESI);
  1367. { load count }
  1368. a_load_ref_reg(list,OS_INT,OS_INT,lenref,NR_ECX);
  1369. { load source }
  1370. a_load_ref_reg(list,OS_INT,OS_INT,ref,NR_ESI);
  1371. { scheduled .... }
  1372. list.concat(Taicpu.op_reg(A_INC,S_L,NR_ECX));
  1373. { calculate size }
  1374. len:=elesize;
  1375. opsize:=S_B;
  1376. if (len and 3)=0 then
  1377. begin
  1378. opsize:=S_L;
  1379. len:=len shr 2;
  1380. end
  1381. else
  1382. if (len and 1)=0 then
  1383. begin
  1384. opsize:=S_W;
  1385. len:=len shr 1;
  1386. end;
  1387. if ispowerof2(len, power) then
  1388. list.concat(Taicpu.op_const_reg(A_SHL,S_L,power,NR_ECX))
  1389. else
  1390. list.concat(Taicpu.op_const_reg(A_IMUL,S_L,len,NR_ECX));
  1391. list.concat(Taicpu.op_none(A_REP,S_NO));
  1392. case opsize of
  1393. S_B : list.concat(Taicpu.Op_none(A_MOVSB,S_NO));
  1394. S_W : list.concat(Taicpu.Op_none(A_MOVSW,S_NO));
  1395. S_L : list.concat(Taicpu.Op_none(A_MOVSL,S_NO));
  1396. end;
  1397. ungetregister(list,NR_EDI);
  1398. ungetregister(list,NR_ECX);
  1399. ungetregister(list,NR_ESI);
  1400. { patch the new address }
  1401. a_load_reg_ref(list,OS_INT,OS_INT,NR_ESP,ref);
  1402. end;
  1403. procedure tcgx86.g_interrupt_stackframe_entry(list : taasmoutput);
  1404. begin
  1405. { .... also the segment registers }
  1406. list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_GS));
  1407. list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_FS));
  1408. list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_ES));
  1409. list.concat(Taicpu.Op_reg(A_PUSH,S_W,NR_DS));
  1410. { save the registers of an interrupt procedure }
  1411. list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDI));
  1412. list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ESI));
  1413. list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EDX));
  1414. list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_ECX));
  1415. list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EBX));
  1416. list.concat(Taicpu.Op_reg(A_PUSH,S_L,NR_EAX));
  1417. end;
  1418. procedure tcgx86.g_interrupt_stackframe_exit(list : taasmoutput;accused,acchiused:boolean);
  1419. begin
  1420. if accused then
  1421. list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
  1422. else
  1423. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EAX));
  1424. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EBX));
  1425. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ECX));
  1426. if acchiused then
  1427. list.concat(Taicpu.Op_const_reg(A_ADD,S_L,4,NR_ESP))
  1428. else
  1429. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDX));
  1430. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_ESI));
  1431. list.concat(Taicpu.Op_reg(A_POP,S_L,NR_EDI));
  1432. { .... also the segment registers }
  1433. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_DS));
  1434. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_ES));
  1435. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_FS));
  1436. list.concat(Taicpu.Op_reg(A_POP,S_W,NR_GS));
  1437. { this restores the flags }
  1438. list.concat(Taicpu.Op_none(A_IRET,S_NO));
  1439. end;
  1440. procedure tcgx86.g_profilecode(list : taasmoutput);
  1441. var
  1442. pl : tasmlabel;
  1443. mcountprefix : String[4];
  1444. begin
  1445. case target_info.system of
  1446. {$ifndef NOTARGETWIN32}
  1447. system_i386_win32,
  1448. {$endif}
  1449. system_i386_freebsd,
  1450. system_i386_netbsd,
  1451. // system_i386_openbsd,
  1452. system_i386_wdosx,
  1453. system_i386_linux:
  1454. begin
  1455. Case target_info.system Of
  1456. system_i386_freebsd : mcountprefix:='.';
  1457. system_i386_netbsd : mcountprefix:='__';
  1458. // system_i386_openbsd : mcountprefix:='.';
  1459. else
  1460. mcountPrefix:='';
  1461. end;
  1462. objectlibrary.getaddrlabel(pl);
  1463. list.concat(Tai_section.Create(sec_data));
  1464. list.concat(Tai_align.Create(4));
  1465. list.concat(Tai_label.Create(pl));
  1466. list.concat(Tai_const.Create_32bit(0));
  1467. list.concat(Tai_section.Create(sec_code));
  1468. list.concat(Taicpu.Op_sym_ofs_reg(A_MOV,S_L,pl,0,NR_EDX));
  1469. a_call_name(list,target_info.Cprefix+mcountprefix+'mcount');
  1470. include(rg[R_INTREGISTER].used_in_proc,RS_EDX);
  1471. end;
  1472. system_i386_go32v2,system_i386_watcom:
  1473. begin
  1474. a_call_name(list,'MCOUNT');
  1475. end;
  1476. end;
  1477. end;
  1478. procedure tcgx86.g_stackpointer_alloc(list : taasmoutput;localsize : longint);
  1479. var
  1480. href : treference;
  1481. i : integer;
  1482. again : tasmlabel;
  1483. begin
  1484. if localsize>0 then
  1485. begin
  1486. {$ifndef NOTARGETWIN32}
  1487. { windows guards only a few pages for stack growing, }
  1488. { so we have to access every page first }
  1489. if (target_info.system=system_i386_win32) and
  1490. (localsize>=winstackpagesize) then
  1491. begin
  1492. if localsize div winstackpagesize<=5 then
  1493. begin
  1494. list.concat(Taicpu.Op_const_reg(A_SUB,S_L,localsize-4,NR_ESP));
  1495. for i:=1 to localsize div winstackpagesize do
  1496. begin
  1497. reference_reset_base(href,NR_ESP,localsize-i*winstackpagesize);
  1498. list.concat(Taicpu.op_const_ref(A_MOV,S_L,0,href));
  1499. end;
  1500. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
  1501. end
  1502. else
  1503. begin
  1504. objectlibrary.getlabel(again);
  1505. getexplicitregister(list,NR_EDI);
  1506. list.concat(Taicpu.op_const_reg(A_MOV,S_L,localsize div winstackpagesize,NR_EDI));
  1507. a_label(list,again);
  1508. list.concat(Taicpu.op_const_reg(A_SUB,S_L,winstackpagesize-4,NR_ESP));
  1509. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EAX));
  1510. list.concat(Taicpu.op_reg(A_DEC,S_L,NR_EDI));
  1511. a_jmp_cond(list,OC_NE,again);
  1512. ungetregister(list,NR_EDI);
  1513. list.concat(Taicpu.op_const_reg(A_SUB,S_L,localsize mod winstackpagesize,NR_ESP));
  1514. end
  1515. end
  1516. else
  1517. {$endif NOTARGETWIN32}
  1518. list.concat(Taicpu.Op_const_reg(A_SUB,S_L,localsize,NR_ESP));
  1519. end;
  1520. end;
  1521. procedure tcgx86.g_stackframe_entry(list : taasmoutput;localsize : longint);
  1522. begin
  1523. list.concat(tai_regalloc.alloc(NR_EBP));
  1524. include(rg[R_INTREGISTER].preserved_by_proc,RS_EBP);
  1525. list.concat(Taicpu.op_reg(A_PUSH,S_L,NR_EBP));
  1526. list.concat(Taicpu.op_reg_reg(A_MOV,S_L,NR_ESP,NR_EBP));
  1527. if localsize>0 then
  1528. g_stackpointer_alloc(list,localsize);
  1529. if cs_create_pic in aktmoduleswitches then
  1530. begin
  1531. a_call_name(list,'FPC_GETEIPINEBX');
  1532. list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,objectlibrary.newasmsymboldata('_GLOBAL_OFFSET_TABLE_'),0,NR_EBX));
  1533. list.concat(tai_regalloc.alloc(NR_EBX));
  1534. end;
  1535. end;
  1536. procedure tcgx86.g_restore_frame_pointer(list : taasmoutput);
  1537. begin
  1538. if cs_create_pic in aktmoduleswitches then
  1539. list.concat(tai_regalloc.dealloc(NR_EBX));
  1540. list.concat(tai_regalloc.dealloc(NR_EBP));
  1541. list.concat(Taicpu.op_none(A_LEAVE,S_NO));
  1542. if assigned(rg[R_MMXREGISTER]) and (rg[R_MMXREGISTER].uses_registers) then
  1543. list.concat(Taicpu.op_none(A_EMMS,S_NO));
  1544. end;
  1545. procedure tcgx86.g_return_from_proc(list : taasmoutput;parasize : aword);
  1546. begin
  1547. { Routines with the poclearstack flag set use only a ret }
  1548. { also routines with parasize=0 }
  1549. if current_procinfo.procdef.proccalloption in clearstack_pocalls then
  1550. begin
  1551. { complex return values are removed from stack in C code PM }
  1552. if paramanager.ret_in_param(current_procinfo.procdef.rettype.def,
  1553. current_procinfo.procdef.proccalloption) then
  1554. list.concat(Taicpu.Op_const(A_RET,S_NO,4))
  1555. else
  1556. list.concat(Taicpu.Op_none(A_RET,S_NO));
  1557. end
  1558. else if (parasize=0) then
  1559. list.concat(Taicpu.Op_none(A_RET,S_NO))
  1560. else
  1561. begin
  1562. { parameters are limited to 65535 bytes because }
  1563. { ret allows only imm16 }
  1564. if (parasize>65535) then
  1565. CGMessage(cg_e_parasize_too_big);
  1566. list.concat(Taicpu.Op_const(A_RET,S_NO,parasize));
  1567. end;
  1568. end;
  1569. procedure tcgx86.g_save_standard_registers(list:Taasmoutput);
  1570. var
  1571. href : treference;
  1572. size : longint;
  1573. begin
  1574. { Get temp }
  1575. size:=0;
  1576. if RS_EBX in rg[R_INTREGISTER].used_in_proc then
  1577. inc(size,POINTER_SIZE);
  1578. if RS_ESI in rg[R_INTREGISTER].used_in_proc then
  1579. inc(size,POINTER_SIZE);
  1580. if RS_EDI in rg[R_INTREGISTER].used_in_proc then
  1581. inc(size,POINTER_SIZE);
  1582. if size>0 then
  1583. begin
  1584. tg.GetTemp(list,size,tt_noreuse,current_procinfo.save_regs_ref);
  1585. { Copy registers to temp }
  1586. href:=current_procinfo.save_regs_ref;
  1587. if RS_EBX in rg[R_INTREGISTER].used_in_proc then
  1588. begin
  1589. a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EBX,href);
  1590. inc(href.offset,POINTER_SIZE);
  1591. end;
  1592. if RS_ESI in rg[R_INTREGISTER].used_in_proc then
  1593. begin
  1594. a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_ESI,href);
  1595. inc(href.offset,POINTER_SIZE);
  1596. end;
  1597. if RS_EDI in rg[R_INTREGISTER].used_in_proc then
  1598. begin
  1599. a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_EDI,href);
  1600. inc(href.offset,POINTER_SIZE);
  1601. end;
  1602. end;
  1603. include(rg[R_INTREGISTER].preserved_by_proc,RS_EBX);
  1604. include(rg[R_INTREGISTER].preserved_by_proc,RS_ESI);
  1605. include(rg[R_INTREGISTER].preserved_by_proc,RS_EDI);
  1606. end;
  1607. procedure tcgx86.g_restore_standard_registers(list:Taasmoutput);
  1608. var
  1609. href : treference;
  1610. begin
  1611. { Copy registers from temp }
  1612. href:=current_procinfo.save_regs_ref;
  1613. if RS_EBX in rg[R_INTREGISTER].used_in_proc then
  1614. begin
  1615. a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EBX);
  1616. inc(href.offset,POINTER_SIZE);
  1617. end;
  1618. if RS_ESI in rg[R_INTREGISTER].used_in_proc then
  1619. begin
  1620. a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_ESI);
  1621. inc(href.offset,POINTER_SIZE);
  1622. end;
  1623. if RS_EDI in rg[R_INTREGISTER].used_in_proc then
  1624. begin
  1625. a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_EDI);
  1626. inc(href.offset,POINTER_SIZE);
  1627. end;
  1628. tg.UnGetTemp(list,current_procinfo.save_regs_ref);
  1629. end;
  1630. procedure tcgx86.g_save_all_registers(list : taasmoutput);
  1631. begin
  1632. list.concat(Taicpu.Op_none(A_PUSHA,S_L));
  1633. tg.GetTemp(list,POINTER_SIZE,tt_noreuse,current_procinfo.save_regs_ref);
  1634. a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_ESP,current_procinfo.save_regs_ref);
  1635. end;
  1636. procedure tcgx86.g_restore_all_registers(list : taasmoutput;accused,acchiused:boolean);
  1637. var
  1638. href : treference;
  1639. begin
  1640. a_load_ref_reg(list,OS_ADDR,OS_ADDR,current_procinfo.save_regs_ref,NR_ESP);
  1641. tg.UnGetTemp(list,current_procinfo.save_regs_ref);
  1642. if acchiused then
  1643. begin
  1644. reference_reset_base(href,NR_ESP,20);
  1645. list.concat(Taicpu.Op_reg_ref(A_MOV,S_L,NR_EDX,href));
  1646. end;
  1647. if accused then
  1648. begin
  1649. reference_reset_base(href,NR_ESP,28);
  1650. list.concat(Taicpu.Op_reg_ref(A_MOV,S_L,NR_EAX,href));
  1651. end;
  1652. list.concat(Taicpu.Op_none(A_POPA,S_L));
  1653. { We add a NOP because of the 386DX CPU bugs with POPAD }
  1654. list.concat(taicpu.op_none(A_NOP,S_L));
  1655. end;
  1656. { produces if necessary overflowcode }
  1657. procedure tcgx86.g_overflowcheck(list: taasmoutput; const l:tlocation;def:tdef);
  1658. var
  1659. hl : tasmlabel;
  1660. ai : taicpu;
  1661. cond : TAsmCond;
  1662. begin
  1663. if not(cs_check_overflow in aktlocalswitches) then
  1664. exit;
  1665. objectlibrary.getlabel(hl);
  1666. if not ((def.deftype=pointerdef) or
  1667. ((def.deftype=orddef) and
  1668. (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  1669. bool8bit,bool16bit,bool32bit]))) then
  1670. cond:=C_NO
  1671. else
  1672. cond:=C_NB;
  1673. ai:=Taicpu.Op_Sym(A_Jcc,S_NO,hl);
  1674. ai.SetCondition(cond);
  1675. ai.is_jmp:=true;
  1676. list.concat(ai);
  1677. a_call_name(list,'FPC_OVERFLOW');
  1678. a_label(list,hl);
  1679. end;
  1680. end.
  1681. {
  1682. $Log$
  1683. Revision 1.100 2003-12-26 14:02:30 peter
  1684. * sparc updates
  1685. * use registertype in spill_register
  1686. Revision 1.99 2003/12/26 13:19:16 florian
  1687. * rtl and compiler compile with -Cfsse2
  1688. Revision 1.98 2003/12/26 00:32:22 florian
  1689. + fpu<->mm register conversion
  1690. Revision 1.97 2003/12/25 12:01:35 florian
  1691. + possible sse2 unit usage for double calculations
  1692. * some sse2 assembler issues fixed
  1693. Revision 1.96 2003/12/25 01:07:09 florian
  1694. + $fputype directive support
  1695. + single data type operations with sse unit
  1696. * fixed more x86-64 stuff
  1697. Revision 1.95 2003/12/24 01:47:23 florian
  1698. * first fixes to compile the x86-64 system unit
  1699. Revision 1.94 2003/12/24 00:10:03 florian
  1700. - delete parameter in cg64 methods removed
  1701. Revision 1.93 2003/12/21 19:42:43 florian
  1702. * fixed ppc inlining stuff
  1703. * fixed wrong unit writing
  1704. + added some sse stuff
  1705. Revision 1.92 2003/12/19 22:08:44 daniel
  1706. * Some work to restore the MMX capabilities
  1707. Revision 1.91 2003/12/15 21:25:49 peter
  1708. * reg allocations for imaginary register are now inserted just
  1709. before reg allocation
  1710. * tregister changed to enum to allow compile time check
  1711. * fixed several tregister-tsuperregister errors
  1712. Revision 1.90 2003/12/12 17:16:18 peter
  1713. * rg[tregistertype] added in tcg
  1714. Revision 1.89 2003/12/06 01:15:23 florian
  1715. * reverted Peter's alloctemp patch; hopefully properly
  1716. Revision 1.88 2003/12/03 23:13:20 peter
  1717. * delayed paraloc allocation, a_param_*() gets extra parameter
  1718. if it needs to allocate temp or real paralocation
  1719. * optimized/simplified int-real loading
  1720. Revision 1.87 2003/11/05 23:06:03 florian
  1721. * elesize of g_copyvaluepara_openarray changed
  1722. Revision 1.86 2003/10/30 18:53:53 marco
  1723. * profiling fix
  1724. Revision 1.85 2003/10/30 16:22:40 peter
  1725. * call firstpass before allocation and codegeneration is started
  1726. * move leftover code from pass_2.generatecode() to psub
  1727. Revision 1.84 2003/10/29 21:24:14 jonas
  1728. + support for fpu temp parameters
  1729. + saving/restoring of fpu register before/after a procedure call
  1730. Revision 1.83 2003/10/20 19:30:08 peter
  1731. * remove memdebug code for rg
  1732. Revision 1.82 2003/10/18 15:41:26 peter
  1733. * made worklists dynamic in size
  1734. Revision 1.81 2003/10/17 15:25:18 florian
  1735. * fixed more ppc stuff
  1736. Revision 1.80 2003/10/17 14:38:32 peter
  1737. * 64k registers supported
  1738. * fixed some memory leaks
  1739. Revision 1.79 2003/10/14 00:30:48 florian
  1740. + some code for PIC support added
  1741. Revision 1.78 2003/10/13 01:23:13 florian
  1742. * some ideas for mm support implemented
  1743. Revision 1.77 2003/10/11 16:06:42 florian
  1744. * fixed some MMX<->SSE
  1745. * started to fix ppc, needs an overhaul
  1746. + stabs info improve for spilling, not sure if it works correctly/completly
  1747. - MMX_SUPPORT removed from Makefile.fpc
  1748. Revision 1.76 2003/10/10 17:48:14 peter
  1749. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  1750. * tregisteralloctor renamed to trgobj
  1751. * removed rgobj from a lot of units
  1752. * moved location_* and reference_* to cgobj
  1753. * first things for mmx register allocation
  1754. Revision 1.75 2003/10/09 21:31:37 daniel
  1755. * Register allocator splitted, ans abstract now
  1756. Revision 1.74 2003/10/07 16:09:03 florian
  1757. * x86 supports only mem/reg to reg for movsx and movzx
  1758. Revision 1.73 2003/10/07 15:17:07 peter
  1759. * inline supported again, LOC_REFERENCEs are used to pass the
  1760. parameters
  1761. * inlineparasymtable,inlinelocalsymtable removed
  1762. * exitlabel inserting fixed
  1763. Revision 1.72 2003/10/03 22:00:33 peter
  1764. * parameter alignment fixes
  1765. Revision 1.71 2003/10/03 14:45:37 peter
  1766. * save ESP after pusha and restore before popa for save all registers
  1767. Revision 1.70 2003/10/01 20:34:51 peter
  1768. * procinfo unit contains tprocinfo
  1769. * cginfo renamed to cgbase
  1770. * moved cgmessage to verbose
  1771. * fixed ppc and sparc compiles
  1772. Revision 1.69 2003/09/30 19:53:47 peter
  1773. * fix pushw reg
  1774. Revision 1.68 2003/09/29 20:58:56 peter
  1775. * optimized releasing of registers
  1776. Revision 1.67 2003/09/28 13:37:19 peter
  1777. * a_call_ref removed
  1778. Revision 1.66 2003/09/25 21:29:16 peter
  1779. * change push/pop in getreg/ungetreg
  1780. Revision 1.65 2003/09/25 13:13:32 florian
  1781. * more x86-64 fixes
  1782. Revision 1.64 2003/09/11 11:55:00 florian
  1783. * improved arm code generation
  1784. * move some protected and private field around
  1785. * the temp. register for register parameters/arguments are now released
  1786. before the move to the parameter register is done. This improves
  1787. the code in a lot of cases.
  1788. Revision 1.63 2003/09/09 21:03:17 peter
  1789. * basics for x86 register calling
  1790. Revision 1.62 2003/09/09 20:59:27 daniel
  1791. * Adding register allocation order
  1792. Revision 1.61 2003/09/07 22:09:35 peter
  1793. * preparations for different default calling conventions
  1794. * various RA fixes
  1795. Revision 1.60 2003/09/05 17:41:13 florian
  1796. * merged Wiktor's Watcom patches in 1.1
  1797. Revision 1.59 2003/09/03 15:55:02 peter
  1798. * NEWRA branch merged
  1799. Revision 1.58.2.5 2003/08/31 20:40:50 daniel
  1800. * Fixed add_edges_used
  1801. Revision 1.58.2.4 2003/08/31 15:46:26 peter
  1802. * more updates for tregister
  1803. Revision 1.58.2.3 2003/08/29 17:29:00 peter
  1804. * next batch of updates
  1805. Revision 1.58.2.2 2003/08/28 18:35:08 peter
  1806. * tregister changed to cardinal
  1807. Revision 1.58.2.1 2003/08/27 21:06:34 peter
  1808. * more updates
  1809. Revision 1.58 2003/08/20 19:28:21 daniel
  1810. * Small NOTARGETWIN32 conditional tweak
  1811. Revision 1.57 2003/07/03 18:59:25 peter
  1812. * loadfpu_reg_reg size specifier
  1813. Revision 1.56 2003/06/14 14:53:50 jonas
  1814. * fixed newra cycle for x86
  1815. * added constants for indicating source and destination operands of the
  1816. "move reg,reg" instruction to aasmcpu (and use those in rgobj)
  1817. Revision 1.55 2003/06/13 21:19:32 peter
  1818. * current_procdef removed, use current_procinfo.procdef instead
  1819. Revision 1.54 2003/06/12 18:31:18 peter
  1820. * fix newra cycle for i386
  1821. Revision 1.53 2003/06/07 10:24:10 peter
  1822. * fixed copyvaluepara for left-to-right pushing
  1823. Revision 1.52 2003/06/07 10:06:55 jonas
  1824. * fixed cycling problem
  1825. Revision 1.51 2003/06/03 21:11:09 peter
  1826. * cg.a_load_* get a from and to size specifier
  1827. * makeregsize only accepts newregister
  1828. * i386 uses generic tcgnotnode,tcgunaryminus
  1829. Revision 1.50 2003/06/03 13:01:59 daniel
  1830. * Register allocator finished
  1831. Revision 1.49 2003/06/01 21:38:07 peter
  1832. * getregisterfpu size parameter added
  1833. * op_const_reg size parameter added
  1834. * sparc updates
  1835. Revision 1.48 2003/05/30 23:57:08 peter
  1836. * more sparc cleanup
  1837. * accumulator removed, splitted in function_return_reg (called) and
  1838. function_result_reg (caller)
  1839. Revision 1.47 2003/05/22 21:33:31 peter
  1840. * removed some unit dependencies
  1841. Revision 1.46 2003/05/16 14:33:31 peter
  1842. * regvar fixes
  1843. Revision 1.45 2003/05/15 18:58:54 peter
  1844. * removed selfpointer_offset, vmtpointer_offset
  1845. * tvarsym.adjusted_address
  1846. * address in localsymtable is now in the real direction
  1847. * removed some obsolete globals
  1848. Revision 1.44 2003/04/30 20:53:32 florian
  1849. * error when address of an abstract method is taken
  1850. * fixed some x86-64 problems
  1851. * merged some more x86-64 and i386 code
  1852. Revision 1.43 2003/04/27 11:21:36 peter
  1853. * aktprocdef renamed to current_procinfo.procdef
  1854. * procinfo renamed to current_procinfo
  1855. * procinfo will now be stored in current_module so it can be
  1856. cleaned up properly
  1857. * gen_main_procsym changed to create_main_proc and release_main_proc
  1858. to also generate a tprocinfo structure
  1859. * fixed unit implicit initfinal
  1860. Revision 1.42 2003/04/23 14:42:08 daniel
  1861. * Further register allocator work. Compiler now smaller with new
  1862. allocator than without.
  1863. * Somebody forgot to adjust ppu version number
  1864. Revision 1.41 2003/04/23 09:51:16 daniel
  1865. * Removed usage of edi in a lot of places when new register allocator used
  1866. + Added newra versions of g_concatcopy and secondadd_float
  1867. Revision 1.40 2003/04/22 13:47:08 peter
  1868. * fixed C style array of const
  1869. * fixed C array passing
  1870. * fixed left to right with high parameters
  1871. Revision 1.39 2003/04/22 10:09:35 daniel
  1872. + Implemented the actual register allocator
  1873. + Scratch registers unavailable when new register allocator used
  1874. + maybe_save/maybe_restore unavailable when new register allocator used
  1875. Revision 1.38 2003/04/17 16:48:21 daniel
  1876. * Added some code to keep track of move instructions in register
  1877. allocator
  1878. Revision 1.37 2003/03/28 19:16:57 peter
  1879. * generic constructor working for i386
  1880. * remove fixed self register
  1881. * esi added as address register for i386
  1882. Revision 1.36 2003/03/18 18:17:46 peter
  1883. * reg2opsize()
  1884. Revision 1.35 2003/03/13 19:52:23 jonas
  1885. * and more new register allocator fixes (in the i386 code generator this
  1886. time). At least now the ppc cross compiler can compile the linux
  1887. system unit again, but I haven't tested it.
  1888. Revision 1.34 2003/02/27 16:40:32 daniel
  1889. * Fixed ie 200301234 problem on Win32 target
  1890. Revision 1.33 2003/02/26 21:15:43 daniel
  1891. * Fixed the optimizer
  1892. Revision 1.32 2003/02/19 22:00:17 daniel
  1893. * Code generator converted to new register notation
  1894. - Horribily outdated todo.txt removed
  1895. Revision 1.31 2003/01/21 10:41:13 daniel
  1896. * Fixed another 200301081
  1897. Revision 1.30 2003/01/13 23:00:18 daniel
  1898. * Fixed internalerror
  1899. Revision 1.29 2003/01/13 14:54:34 daniel
  1900. * Further work to convert codegenerator register convention;
  1901. internalerror bug fixed.
  1902. Revision 1.28 2003/01/09 20:41:00 daniel
  1903. * Converted some code in cgx86.pas to new register numbering
  1904. Revision 1.27 2003/01/08 18:43:58 daniel
  1905. * Tregister changed into a record
  1906. Revision 1.26 2003/01/05 13:36:53 florian
  1907. * x86-64 compiles
  1908. + very basic support for float128 type (x86-64 only)
  1909. Revision 1.25 2003/01/02 16:17:50 peter
  1910. * align stack on 4 bytes in copyvalueopenarray
  1911. Revision 1.24 2002/12/24 15:56:50 peter
  1912. * stackpointer_alloc added for adjusting ESP. Win32 needs
  1913. this for the pageprotection
  1914. Revision 1.23 2002/11/25 18:43:34 carl
  1915. - removed the invalid if <> checking (Delphi is strange on this)
  1916. + implemented abstract warning on instance creation of class with
  1917. abstract methods.
  1918. * some error message cleanups
  1919. Revision 1.22 2002/11/25 17:43:29 peter
  1920. * splitted defbase in defutil,symutil,defcmp
  1921. * merged isconvertable and is_equal into compare_defs(_ext)
  1922. * made operator search faster by walking the list only once
  1923. Revision 1.21 2002/11/18 17:32:01 peter
  1924. * pass proccalloption to ret_in_xxx and push_xxx functions
  1925. Revision 1.20 2002/11/09 21:18:31 carl
  1926. * flags2reg() was not extending the byte register to the correct result size
  1927. Revision 1.19 2002/10/16 19:01:43 peter
  1928. + $IMPLICITEXCEPTIONS switch to turn on/off generation of the
  1929. implicit exception frames for procedures with initialized variables
  1930. and for constructors. The default is on for compatibility
  1931. Revision 1.18 2002/10/05 12:43:30 carl
  1932. * fixes for Delphi 6 compilation
  1933. (warning : Some features do not work under Delphi)
  1934. Revision 1.17 2002/09/17 18:54:06 jonas
  1935. * a_load_reg_reg() now has two size parameters: source and dest. This
  1936. allows some optimizations on architectures that don't encode the
  1937. register size in the register name.
  1938. Revision 1.16 2002/09/16 19:08:47 peter
  1939. * support references without registers and symbol in paramref_addr. It
  1940. pushes only the offset
  1941. Revision 1.15 2002/09/16 18:06:29 peter
  1942. * move CGSize2Opsize to interface
  1943. Revision 1.14 2002/09/01 14:42:41 peter
  1944. * removevaluepara added to fix the stackpointer so restoring of
  1945. saved registers works
  1946. Revision 1.13 2002/09/01 12:09:27 peter
  1947. + a_call_reg, a_call_loc added
  1948. * removed exprasmlist references
  1949. Revision 1.12 2002/08/17 09:23:50 florian
  1950. * first part of procinfo rewrite
  1951. Revision 1.11 2002/08/16 14:25:00 carl
  1952. * issameref() to test if two references are the same (then emit no opcodes)
  1953. + ret_in_reg to replace ret_in_acc
  1954. (fix some register allocation bugs at the same time)
  1955. + save_std_register now has an extra parameter which is the
  1956. usedinproc registers
  1957. Revision 1.10 2002/08/15 08:13:54 carl
  1958. - a_load_sym_ofs_reg removed
  1959. * loadvmt now calls loadaddr_ref_reg instead
  1960. Revision 1.9 2002/08/11 14:32:33 peter
  1961. * renamed current_library to objectlibrary
  1962. Revision 1.8 2002/08/11 13:24:20 peter
  1963. * saving of asmsymbols in ppu supported
  1964. * asmsymbollist global is removed and moved into a new class
  1965. tasmlibrarydata that will hold the info of a .a file which
  1966. corresponds with a single module. Added librarydata to tmodule
  1967. to keep the library info stored for the module. In the future the
  1968. objectfiles will also be stored to the tasmlibrarydata class
  1969. * all getlabel/newasmsymbol and friends are moved to the new class
  1970. Revision 1.7 2002/08/10 10:06:04 jonas
  1971. * fixed stupid bug of mine in g_flags2reg() when optimizations are on
  1972. Revision 1.6 2002/08/09 19:18:27 carl
  1973. * fix generic exception handling
  1974. Revision 1.5 2002/08/04 19:52:04 carl
  1975. + updated exception routines
  1976. Revision 1.4 2002/07/27 19:53:51 jonas
  1977. + generic implementation of tcg.g_flags2ref()
  1978. * tcg.flags2xxx() now also needs a size parameter
  1979. Revision 1.3 2002/07/26 21:15:46 florian
  1980. * rewrote the system handling
  1981. Revision 1.2 2002/07/21 16:55:34 jonas
  1982. * fixed bug in op_const_reg_reg() for imul
  1983. Revision 1.1 2002/07/20 19:28:47 florian
  1984. * splitting of i386\cgcpu.pas into x86\cgx86.pas and i386\cgcpu.pas
  1985. cgx86.pas will contain the common code for i386 and x86_64
  1986. }