cgx86.pas 66 KB

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