cgx86.pas 80 KB

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