cgx86.pas 65 KB

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