cgx86.pas 80 KB

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