cgcpu.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the code generator for the SPARC
  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. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cgbase,cgobj,cg64f32,
  23. aasmbase,aasmtai,aasmcpu,
  24. cpubase,cpuinfo,
  25. node,symconst,SymType;
  26. type
  27. TCgSparc=class(tcg)
  28. protected
  29. function IsSimpleRef(const ref:treference):boolean;
  30. public
  31. procedure init_register_allocators;override;
  32. procedure done_register_allocators;override;
  33. { sparc special, needed by cg64 }
  34. procedure handle_load_store(list:taasmoutput;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
  35. procedure handle_reg_const_reg(list:taasmoutput;op:Tasmop;src:tregister;a:aword;dst:tregister);
  36. { parameter }
  37. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);override;
  38. procedure a_param_ref(list:TAasmOutput;sz:tcgsize;const r:TReference;const LocPara:TParaLocation);override;
  39. procedure a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation);override;
  40. procedure a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const locpara : tparalocation);override;
  41. procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const locpara : tparalocation);override;
  42. procedure a_load_param_ref(list : taasmoutput;const locpara : tparalocation;const ref:treference);override;
  43. procedure a_load_param_reg(list : taasmoutput;const locpara : tparalocation;const reg:tregister);override;
  44. procedure a_call_name(list:TAasmOutput;const s:string);override;
  45. procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override;
  46. { General purpose instructions }
  47. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;size:tcgsize;a:AWord;reg:TRegister);override;
  48. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  49. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  50. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  51. { move instructions }
  52. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  53. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;const ref:TReference);override;
  54. procedure a_load_reg_ref(list:TAasmOutput;FromSize,ToSize:TCgSize;reg:TRegister;const ref:TReference);override;
  55. procedure a_load_ref_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);override;
  56. procedure a_load_reg_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
  57. procedure a_loadaddr_ref_reg(list:TAasmOutput;const ref:TReference;r:tregister);override;
  58. { fpu move instructions }
  59. procedure a_loadfpu_reg_reg(list:TAasmOutput;size:tcgsize;reg1, reg2:tregister);override;
  60. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override;
  61. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override;
  62. { comparison operations }
  63. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  64. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  65. procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
  66. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  67. procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override;
  68. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override;
  69. procedure g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);override;
  70. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  71. procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override;
  72. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  73. procedure g_restore_standard_registers(list:taasmoutput;usedinproc:Tsuperregisterset);override;
  74. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  75. procedure g_save_all_registers(list : taasmoutput);override;
  76. procedure g_save_standard_registers(list : taasmoutput; usedinproc : Tsuperregisterset);override;
  77. procedure g_concatcopy(list:TAasmOutput;const source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  78. class function reg_cgsize(const reg:tregister):tcgsize;override;
  79. end;
  80. TCg64Sparc=class(tcg64f32)
  81. procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override;
  82. procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override;
  83. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  84. end;
  85. const
  86. TOpCG2AsmOp : array[topcg] of TAsmOp=(
  87. A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_UMUL,A_SMUL,A_NEG,A_NOT,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR
  88. );
  89. TOpCmp2AsmCond : array[topcmp] of TAsmCond=(
  90. C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A
  91. );
  92. implementation
  93. uses
  94. globtype,globals,verbose,systems,cutils,
  95. symdef,symsym,defutil,paramgr,
  96. rgobj,tgobj,rgcpu,cpupi;
  97. {****************************************************************************
  98. This is private property, keep out! :)
  99. ****************************************************************************}
  100. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  101. begin
  102. if (ref.base=NR_NO) and (ref.index<>NR_NO) then
  103. InternalError(2002100804);
  104. result :=not(assigned(ref.symbol))and
  105. (((ref.index = NR_NO) and
  106. (ref.offset >= simm13lo) and
  107. (ref.offset <= simm13hi)) or
  108. ((ref.index <> NR_NO) and
  109. (ref.offset = 0)));
  110. end;
  111. procedure tcgsparc.handle_load_store(list:taasmoutput;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
  112. var
  113. tmpreg : tregister;
  114. tmpref : treference;
  115. begin
  116. tmpreg:=NR_NO;
  117. { Be sure to have a base register }
  118. if (ref.base=NR_NO) then
  119. begin
  120. ref.base:=ref.index;
  121. ref.index:=NR_NO;
  122. end;
  123. { When need to use SETHI, do it first }
  124. if assigned(ref.symbol) or
  125. (ref.offset<simm13lo) or
  126. (ref.offset>simm13hi) then
  127. begin
  128. tmpreg:=rg.getregisterint(list,OS_INT);
  129. reference_reset(tmpref);
  130. tmpref.symbol:=ref.symbol;
  131. tmpref.offset:=ref.offset;
  132. tmpref.symaddr:=refs_hi;
  133. list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
  134. { Load the low part is left }
  135. {$warning TODO Maybe not needed to load symbol}
  136. tmpref.symaddr:=refs_lo;
  137. list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
  138. { The offset and symbol are loaded, reset in reference }
  139. ref.offset:=0;
  140. ref.symbol:=nil;
  141. { Only an index register or offset is allowed }
  142. if tmpreg<>NR_NO then
  143. begin
  144. if (ref.index<>NR_NO) then
  145. begin
  146. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
  147. ref.index:=tmpreg;
  148. end
  149. else
  150. begin
  151. if ref.base<>NR_NO then
  152. ref.index:=tmpreg
  153. else
  154. ref.base:=tmpreg;
  155. end;
  156. end;
  157. end;
  158. if (ref.base<>NR_NO) then
  159. begin
  160. if (ref.index<>NR_NO) and
  161. ((ref.offset<>0) or assigned(ref.symbol)) then
  162. begin
  163. if tmpreg=NR_NO then
  164. tmpreg:=rg.getregisterint(list,OS_INT);
  165. if (ref.index<>NR_NO) then
  166. begin
  167. list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
  168. ref.index:=NR_NO;
  169. end;
  170. end;
  171. end;
  172. if isstore then
  173. list.concat(taicpu.op_reg_ref(op,reg,ref))
  174. else
  175. list.concat(taicpu.op_ref_reg(op,ref,reg));
  176. if (tmpreg<>NR_NO) then
  177. rg.ungetregisterint(list,tmpreg);
  178. end;
  179. procedure tcgsparc.handle_reg_const_reg(list:taasmoutput;op:Tasmop;src:tregister;a:aword;dst:tregister);
  180. var
  181. tmpreg : tregister;
  182. begin
  183. if (longint(a)<simm13lo) or
  184. (longint(a)>simm13hi) then
  185. begin
  186. tmpreg:=rg.getregisterint(list,OS_INT);
  187. list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,tmpreg));
  188. list.concat(taicpu.op_reg_const_reg(A_OR,tmpreg,a and aword($3ff),tmpreg));
  189. list.concat(taicpu.op_reg_reg_reg(op,src,tmpreg,dst));
  190. rg.ungetregisterint(list,tmpreg);
  191. end
  192. else
  193. list.concat(taicpu.op_reg_const_reg(op,src,a,dst));
  194. end;
  195. {****************************************************************************
  196. Assembler code
  197. ****************************************************************************}
  198. procedure Tcgsparc.init_register_allocators;
  199. begin
  200. rg:=Trgcpu.create(15,chr(RS_O0)+chr(RS_O1)+chr(RS_O2)+chr(RS_O3)+
  201. chr(RS_O4)+chr(RS_O5)+chr(RS_O7)+
  202. chr(RS_L0)+chr(RS_L1)+chr(RS_L2)+chr(RS_L3)+
  203. chr(RS_L4)+chr(RS_L5)+chr(RS_L6)+chr(RS_L7));
  204. end;
  205. procedure Tcgsparc.done_register_allocators;
  206. begin
  207. rg.free;
  208. end;
  209. function TCgSparc.reg_cgsize(const reg:tregister):tcgsize;
  210. begin
  211. result:=OS_32;
  212. end;
  213. procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);
  214. var
  215. Ref:TReference;
  216. begin
  217. case locpara.loc of
  218. LOC_REGISTER,LOC_CREGISTER:
  219. a_load_const_reg(list,size,a,locpara.register);
  220. LOC_REFERENCE:
  221. begin
  222. { Code conventions need the parameters being allocated in %o6+92 }
  223. if locpara.reference.offset<92 then
  224. InternalError(2002081104);
  225. reference_reset_base(ref,locpara.reference.index,locpara.reference.offset);
  226. a_load_const_ref(list,size,a,ref);
  227. end;
  228. else
  229. InternalError(2002122200);
  230. end;
  231. end;
  232. procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation);
  233. var
  234. ref: treference;
  235. tmpreg:TRegister;
  236. begin
  237. with LocPara do
  238. case loc of
  239. LOC_REGISTER,LOC_CREGISTER :
  240. a_load_ref_reg(list,sz,sz,r,Register);
  241. LOC_REFERENCE:
  242. begin
  243. { Code conventions need the parameters being allocated in %o6+92 }
  244. if locpara.reference.offset<92 then
  245. InternalError(2002081104);
  246. reference_reset_base(ref,locpara.reference.index,locpara.reference.offset);
  247. tmpreg:=rg.getregisterint(list,OS_INT);
  248. a_load_ref_reg(list,sz,sz,r,tmpreg);
  249. a_load_reg_ref(list,sz,sz,tmpreg,ref);
  250. rg.ungetregisterint(list,tmpreg);
  251. end;
  252. else
  253. internalerror(2002081103);
  254. end;
  255. end;
  256. procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation);
  257. var
  258. Ref:TReference;
  259. TmpReg:TRegister;
  260. begin
  261. case locpara.loc of
  262. LOC_REGISTER,LOC_CREGISTER:
  263. a_loadaddr_ref_reg(list,r,locpara.register);
  264. LOC_REFERENCE:
  265. begin
  266. reference_reset(ref);
  267. ref.base := locpara.reference.index;
  268. ref.offset := locpara.reference.offset;
  269. tmpreg:=rg.getaddressregister(list);
  270. a_loadaddr_ref_reg(list,r,tmpreg);
  271. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  272. rg.ungetregisterint(list,tmpreg);
  273. end;
  274. else
  275. internalerror(2002080701);
  276. end;
  277. end;
  278. procedure tcgsparc.a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const locpara : tparalocation);
  279. var
  280. href : treference;
  281. begin
  282. tg.GetTemp(list,TCGSize2Size[size],tt_normal,href);
  283. a_loadfpu_reg_ref(list,size,r,href);
  284. a_paramfpu_ref(list,size,href,locpara);
  285. tg.Ungettemp(list,href);
  286. end;
  287. procedure tcgsparc.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const locpara : tparalocation);
  288. var
  289. templocpara : tparalocation;
  290. begin
  291. { floats are pushed in the int registers }
  292. templocpara:=locpara;
  293. case locpara.size of
  294. OS_F32 :
  295. begin
  296. templocpara.size:=OS_32;
  297. a_param_ref(list,OS_32,ref,templocpara);
  298. end;
  299. OS_F64 :
  300. begin
  301. templocpara.size:=OS_64;
  302. cg64.a_param64_ref(list,ref,templocpara);
  303. end;
  304. else
  305. internalerror(200307021);
  306. end;
  307. end;
  308. procedure tcgsparc.a_load_param_ref(list : taasmoutput;const locpara : tparalocation;const ref:treference);
  309. var
  310. href,
  311. tempref : treference;
  312. templocpara : tparalocation;
  313. begin
  314. { Load floats like ints }
  315. templocpara:=locpara;
  316. case locpara.size of
  317. OS_F32 :
  318. templocpara.size:=OS_32;
  319. OS_F64 :
  320. templocpara.size:=OS_64;
  321. end;
  322. { Word 0 is in register, word 1 is in reference }
  323. if (templocpara.loc=LOC_REFERENCE) and (templocpara.low_in_reg) then
  324. begin
  325. tempref:=ref;
  326. cg.a_load_reg_ref(list,OS_INT,OS_INT,templocpara.register,tempref);
  327. inc(tempref.offset,4);
  328. reference_reset_base(href,templocpara.reference.index,templocpara.reference.offset);
  329. cg.a_load_ref_ref(list,OS_INT,OS_INT,href,tempref);
  330. end
  331. else
  332. inherited a_load_param_ref(list,templocpara,ref);
  333. end;
  334. procedure tcgsparc.a_load_param_reg(list : taasmoutput;const locpara : tparalocation;const reg:tregister);
  335. var
  336. href : treference;
  337. begin
  338. { Word 0 is in register, word 1 is in reference, not
  339. possible to load it in 1 register }
  340. if (locpara.loc=LOC_REFERENCE) and (locpara.low_in_reg) then
  341. internalerror(200307011);
  342. { Float load use a temp reference }
  343. if locpara.size in [OS_F32,OS_F64] then
  344. begin
  345. tg.GetTemp(list,TCGSize2Size[locpara.size],tt_normal,href);
  346. a_load_param_ref(list,locpara,href);
  347. a_loadfpu_ref_reg(list,locpara.size,href,reg);
  348. tg.Ungettemp(list,href);
  349. end
  350. else
  351. inherited a_load_param_reg(list,locpara,reg);
  352. end;
  353. procedure TCgSparc.a_call_name(list:TAasmOutput;const s:string);
  354. begin
  355. list.concat(taicpu.op_sym(A_CALL,objectlibrary.newasmsymbol(s)));
  356. { Delay slot }
  357. list.concat(taicpu.op_none(A_NOP));
  358. end;
  359. procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister);
  360. begin
  361. list.concat(taicpu.op_reg(A_CALL,reg));
  362. { Delay slot }
  363. list.concat(taicpu.op_none(A_NOP));
  364. end;
  365. {********************** load instructions ********************}
  366. procedure TCgSparc.a_load_const_reg(list : TAasmOutput;size : TCGSize;a : aword;reg : TRegister);
  367. begin
  368. { we don't use the set instruction here because it could be evalutated to two
  369. instructions which would cause problems with the delay slot (FK) }
  370. { sethi allows to set the upper 22 bit, so we'll take full advantage of it }
  371. if (a and aword($1fff))=0 then
  372. list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,reg))
  373. else if (longint(a)>=simm13lo) and (longint(a)<=simm13hi) then
  374. list.concat(taicpu.op_reg_const_reg(A_OR,NR_G0,a,reg))
  375. else
  376. begin
  377. list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,reg));
  378. list.concat(taicpu.op_reg_const_reg(A_OR,reg,a and aword($3ff),reg));
  379. end;
  380. end;
  381. procedure TCgSparc.a_load_const_ref(list : TAasmOutput;size : tcgsize;a : aword;const ref : TReference);
  382. begin
  383. if a=0 then
  384. a_load_reg_ref(list,size,size,NR_G0,ref)
  385. else
  386. inherited a_load_const_ref(list,size,a,ref);
  387. end;
  388. procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;FromSize,ToSize:TCGSize;reg:tregister;const Ref:TReference);
  389. var
  390. op:tasmop;
  391. begin
  392. case ToSize of
  393. { signed integer registers }
  394. OS_8,
  395. OS_S8:
  396. Op:=A_STB;
  397. OS_16,
  398. OS_S16:
  399. Op:=A_STH;
  400. OS_32,
  401. OS_S32:
  402. Op:=A_ST;
  403. else
  404. InternalError(2002122100);
  405. end;
  406. handle_load_store(list,true,op,reg,ref);
  407. end;
  408. procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);
  409. var
  410. op:tasmop;
  411. begin
  412. case Fromsize of
  413. { signed integer registers }
  414. OS_S8:
  415. Op:=A_LDSB;{Load Signed Byte}
  416. OS_8:
  417. Op:=A_LDUB;{Load Unsigned Bye}
  418. OS_S16:
  419. Op:=A_LDSH;{Load Signed Halfword}
  420. OS_16:
  421. Op:=A_LDUH;{Load Unsigned Halfword}
  422. OS_S32,
  423. OS_32:
  424. Op:=A_LD;{Load Word}
  425. else
  426. InternalError(2002122101);
  427. end;
  428. handle_load_store(list,false,op,reg,ref);
  429. end;
  430. procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  431. begin
  432. if (reg1<>reg2) or
  433. (tcgsize2size[tosize]<tcgsize2size[fromsize]) or
  434. (
  435. (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  436. (tosize <> fromsize) and
  437. not(fromsize in [OS_32,OS_S32])
  438. ) then
  439. begin
  440. {$warning TODO Sign extension}
  441. case tosize of
  442. OS_8,OS_S8:
  443. a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
  444. OS_16,OS_S16:
  445. a_op_const_reg_reg(list,OP_AND,tosize,$ffff,reg1,reg2);
  446. OS_32,OS_S32:
  447. begin
  448. if reg1<>reg2 then
  449. list.Concat(taicpu.op_reg_reg(A_MOV,reg1,reg2));
  450. end;
  451. else
  452. internalerror(2002090901);
  453. end;
  454. end;
  455. end;
  456. procedure TCgSparc.a_loadaddr_ref_reg(list : TAasmOutput;const ref : TReference;r : tregister);
  457. var
  458. tmpref : treference;
  459. hreg : tregister;
  460. begin
  461. if (ref.base=NR_NO) and (ref.index<>NR_NO) then
  462. internalerror(200306171);
  463. { At least big offset (need SETHI), maybe base and maybe index }
  464. if assigned(ref.symbol) or
  465. (ref.offset<simm13lo) or
  466. (ref.offset>simm13hi) then
  467. begin
  468. if (ref.base<>r) and (ref.index<>r) then
  469. hreg:=r
  470. else
  471. hreg:=rg.getaddressregister(list);
  472. reference_reset(tmpref);
  473. tmpref.symbol := ref.symbol;
  474. tmpref.offset := ref.offset;
  475. tmpref.symaddr := refs_hi;
  476. list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
  477. { Only the low part is left }
  478. tmpref.symaddr:=refs_lo;
  479. list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
  480. if ref.base<>NR_NO then
  481. begin
  482. if ref.index<>NR_NO then
  483. begin
  484. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,hreg));
  485. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,r));
  486. end
  487. else
  488. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,r));
  489. end
  490. else
  491. begin
  492. if hreg<>r then
  493. list.Concat(taicpu.op_reg_reg(A_MOV,hreg,r));
  494. end;
  495. if hreg<>r then
  496. rg.ungetaddressregister(list,hreg);
  497. end
  498. else
  499. { At least small offset, maybe base and maybe index }
  500. if ref.offset<>0 then
  501. begin
  502. if ref.base<>NR_NO then
  503. begin
  504. if ref.index<>NR_NO then
  505. begin
  506. if (ref.base<>r) and (ref.index<>r) then
  507. hreg:=r
  508. else
  509. hreg:=rg.getaddressregister(list);
  510. list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),hreg));
  511. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,r));
  512. if hreg<>r then
  513. rg.ungetaddressregister(list,hreg);
  514. end
  515. else
  516. list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),r));
  517. end
  518. else
  519. list.concat(taicpu.op_reg_const_reg(A_ADD,NR_G0,aword(ref.offset),r));
  520. end
  521. else
  522. { Both base and index }
  523. if ref.index<>NR_NO then
  524. list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,r))
  525. else
  526. { Only base }
  527. if ref.base<>NR_NO then
  528. a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r)
  529. else
  530. internalerror(200306172);
  531. end;
  532. procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;size:tcgsize;reg1, reg2:tregister);
  533. begin
  534. if reg1<>reg2 then
  535. begin
  536. list.concat(taicpu.op_reg_reg(A_FMOVs,reg1,reg2));
  537. if size=OS_F64 then
  538. begin
  539. setsupreg(reg1,getsupreg(reg1)+1);
  540. setsupreg(reg2,getsupreg(reg2)+1);
  541. list.concat(taicpu.op_reg_reg(A_FMOVs,reg1,reg2));
  542. end;
  543. end;
  544. end;
  545. procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);
  546. const
  547. FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
  548. (A_LDF,A_LDDF);
  549. begin
  550. { several functions call this procedure with OS_32 or OS_64 }
  551. { so this makes life easier (FK) }
  552. case size of
  553. OS_32,OS_F32:
  554. size:=OS_F32;
  555. OS_64,OS_F64,OS_C64:
  556. size:=OS_F64;
  557. else
  558. internalerror(200201121);
  559. end;
  560. handle_load_store(list,false,fpuloadinstr[size],reg,ref);
  561. end;
  562. procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);
  563. const
  564. FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
  565. (A_STF,A_STDF);
  566. begin
  567. { several functions call this procedure with OS_32 or OS_64 }
  568. { so this makes life easier (FK) }
  569. case size of
  570. OS_32,OS_F32:
  571. size:=OS_F32;
  572. OS_64,OS_F64,OS_C64:
  573. size:=OS_F64;
  574. else
  575. internalerror(200201121);
  576. end;
  577. handle_load_store(list,true,fpuloadinstr[size],reg,ref);
  578. end;
  579. procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;size:tcgsize;a:AWord;reg:TRegister);
  580. begin
  581. if Op in [OP_NEG,OP_NOT] then
  582. internalerror(200306011);
  583. if (a=0) then
  584. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],reg,NR_G0,reg))
  585. else
  586. handle_reg_const_reg(list,TOpCG2AsmOp[op],reg,a,reg);
  587. end;
  588. procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  589. begin
  590. Case Op of
  591. OP_NEG,
  592. OP_NOT:
  593. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],src,dst));
  594. else
  595. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
  596. end;
  597. end;
  598. procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);
  599. var
  600. power : longInt;
  601. begin
  602. case op of
  603. OP_IMUL :
  604. begin
  605. if not(cs_check_overflow in aktlocalswitches) and
  606. ispowerof2(a,power) then
  607. begin
  608. { can be done with a shift }
  609. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  610. exit;
  611. end;
  612. end;
  613. OP_SUB,
  614. OP_ADD :
  615. begin
  616. if (a=0) then
  617. begin
  618. a_load_reg_reg(list,size,size,src,dst);
  619. exit;
  620. end;
  621. end;
  622. end;
  623. handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
  624. end;
  625. procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
  626. begin
  627. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
  628. end;
  629. {*************** compare instructructions ****************}
  630. procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);
  631. begin
  632. if (a=0) then
  633. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg,NR_G0,NR_G0))
  634. else
  635. handle_reg_const_reg(list,A_SUBcc,reg,a,NR_G0);
  636. a_jmp_cond(list,cmp_op,l);
  637. end;
  638. procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);
  639. begin
  640. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg2,reg1,NR_G0));
  641. a_jmp_cond(list,cmp_op,l);
  642. end;
  643. procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
  644. begin
  645. List.Concat(TAiCpu.op_sym(A_BA,objectlibrary.newasmsymbol(l.name)));
  646. { Delay slot }
  647. list.Concat(TAiCpu.Op_none(A_NOP));
  648. end;
  649. procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel);
  650. var
  651. ai:TAiCpu;
  652. begin
  653. ai:=TAiCpu.Op_sym(A_Bxx,l);
  654. ai.SetCondition(TOpCmp2AsmCond[cond]);
  655. list.Concat(ai);
  656. { Delay slot }
  657. list.Concat(TAiCpu.Op_none(A_NOP));
  658. end;
  659. procedure TCgSparc.a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);
  660. var
  661. ai:taicpu;
  662. begin
  663. ai := Taicpu.op_sym(A_Bxx,l);
  664. ai.SetCondition(flags_to_cond(f));
  665. list.Concat(ai);
  666. { Delay slot }
  667. list.Concat(TAiCpu.Op_none(A_NOP));
  668. end;
  669. procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);
  670. var
  671. hl : tasmlabel;
  672. begin
  673. objectlibrary.getlabel(hl);
  674. a_load_const_reg(list,size,1,reg);
  675. a_jmp_flags(list,f,hl);
  676. a_load_const_reg(list,size,0,reg);
  677. a_label(list,hl);
  678. end;
  679. procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);
  680. var
  681. hl : tasmlabel;
  682. begin
  683. if not(cs_check_overflow in aktlocalswitches) then
  684. exit;
  685. objectlibrary.getlabel(hl);
  686. if not((def.deftype=pointerdef)or
  687. ((def.deftype=orddef)and
  688. (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,bool8bit,bool16bit,bool32bit]))) then
  689. begin
  690. //r.enum:=R_CR7;
  691. //list.concat(taicpu.op_reg(A_MCRXR,r));
  692. //a_jmp_cond(list,A_Bxx,C_OV,hl)
  693. a_jmp_always(list,hl)
  694. end
  695. else
  696. a_jmp_cond(list,OC_AE,hl);
  697. a_call_name(list,'FPC_OVERFLOW');
  698. a_label(list,hl);
  699. end;
  700. { *********** entry/exit code and address loading ************ }
  701. procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
  702. begin
  703. { Althogh the SPARC architecture require only word alignment, software
  704. convention and the operating system require every stack frame to be double word
  705. aligned }
  706. LocalSize:=align(LocalSize,8);
  707. { Execute the SAVE instruction to get a new register window and create a new
  708. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  709. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  710. after execution of that instruction is the called function stack pointer}
  711. list.concat(Taicpu.Op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,aword(-LocalSize),NR_STACK_POINTER_REG));
  712. end;
  713. procedure TCgSparc.g_restore_all_registers(list:TaasmOutput;accused,acchiused:boolean);
  714. begin
  715. { The sparc port uses the sparc standard calling convetions so this function has no used }
  716. end;
  717. procedure TCgSparc.g_restore_frame_pointer(list:TAasmOutput);
  718. begin
  719. { This function intontionally does nothing as frame pointer is restored in the
  720. delay slot of the return instrucion done in g_return_from_proc}
  721. end;
  722. procedure TCgSparc.g_restore_standard_registers(list:taasmoutput;usedinproc:Tsuperregisterset);
  723. begin
  724. { The sparc port uses the sparc standard calling convetions so this function has no used }
  725. end;
  726. procedure TCgSparc.g_return_from_proc(list:TAasmOutput;parasize:aword);
  727. begin
  728. { According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  729. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  730. real RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  731. delay slot, so an inversion is possible such as
  732. RET (=JMPL %i7+8,%g0)
  733. RESTORE (=RESTORE %g0,0,%g0)
  734. If no inversion we can use just
  735. RESTORE (=RESTORE %g0,0,%g0)
  736. RET (=JMPL %i7+8,%g0)
  737. NOP
  738. }
  739. list.concat(Taicpu.op_none(A_RET));
  740. { We use trivial restore in the delay slot of the JMPL instruction, as we
  741. already set result onto %i0 }
  742. list.concat(Taicpu.op_none(A_RESTORE));
  743. end;
  744. procedure TCgSparc.g_save_all_registers(list : taasmoutput);
  745. begin
  746. { The sparc port uses the sparc standard calling convetions so this function has no used }
  747. end;
  748. procedure TCgSparc.g_save_standard_registers(list : taasmoutput; usedinproc:Tsuperregisterset);
  749. begin
  750. { The sparc port uses the sparc standard calling convetions so this function has no used }
  751. end;
  752. { ************* concatcopy ************ }
  753. procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean);
  754. var
  755. hreg,
  756. countreg: TRegister;
  757. src, dst: TReference;
  758. lab: tasmlabel;
  759. count, count2: aword;
  760. orgsrc, orgdst: boolean;
  761. begin
  762. if len > high(longint) then
  763. internalerror(2002072704);
  764. { make sure short loads are handled as optimally as possible }
  765. if not loadref then
  766. begin
  767. if (len <= 8) and (byte(len) in [1,2,4,8]) then
  768. begin
  769. if len < 8 then
  770. begin
  771. a_load_ref_ref(list,int_cgsize(len),int_cgsize(len),source,dest);
  772. if delsource then
  773. reference_release(list,source);
  774. end
  775. else
  776. begin
  777. a_reg_alloc(list,NR_F0);
  778. a_loadfpu_ref_reg(list,OS_F64,source,NR_F0);
  779. if delsource then
  780. reference_release(list,source);
  781. a_loadfpu_reg_ref(list,OS_F64,NR_F0,dest);
  782. a_reg_dealloc(list,NR_F0);
  783. end;
  784. exit;
  785. end;
  786. end;
  787. reference_reset(src);
  788. reference_reset(dst);
  789. { load the address of source into src.base }
  790. if loadref then
  791. begin
  792. src.base:=rg.getaddressregister(list);
  793. a_load_ref_reg(list,OS_32,OS_32,source,src.base);
  794. orgsrc := false;
  795. end
  796. else
  797. if not issimpleref(source) or
  798. (
  799. (source.index<>NR_NO) and
  800. (((source.offset+longint(len))>simm13hi) or
  801. ((source.offset+longint(len))<simm13lo))
  802. ) then
  803. begin
  804. src.base:=rg.getaddressregister(list);
  805. a_loadaddr_ref_reg(list,source,src.base);
  806. orgsrc := false;
  807. end
  808. else
  809. begin
  810. src := source;
  811. orgsrc := true;
  812. end;
  813. if not orgsrc and delsource then
  814. reference_release(list,source);
  815. { load the address of dest into dst.base }
  816. if not issimpleref(dest) or
  817. (
  818. (dest.index<>NR_NO) and
  819. (((dest.offset + longint(len)) > simm13hi) or
  820. ((dest.offset + longint(len)) < simm13lo))
  821. ) then
  822. begin
  823. dst.base:=rg.getaddressregister(list);
  824. a_loadaddr_ref_reg(list,dest,dst.base);
  825. orgdst := false;
  826. end
  827. else
  828. begin
  829. dst := dest;
  830. orgdst := true;
  831. end;
  832. { generate a loop }
  833. count:=len div 8;
  834. if count>4 then
  835. begin
  836. { the offsets are zero after the a_loadaddress_ref_reg and just }
  837. { have to be set to 8. I put an Inc there so debugging may be }
  838. { easier (should offset be different from zero here, it will be }
  839. { easy to notice in the generated assembler }
  840. inc(dst.offset,8);
  841. inc(src.offset,8);
  842. list.concat(taicpu.op_reg_const_reg(A_SUB,src.base,8,src.base));
  843. list.concat(taicpu.op_reg_const_reg(A_SUB,dst.base,8,dst.base));
  844. countreg:=rg.getregisterint(list,OS_INT);
  845. a_load_const_reg(list,OS_INT,count,countreg);
  846. { explicitely allocate R_O0 since it can be used safely here }
  847. { (for holding date that's being copied) }
  848. a_reg_alloc(list,NR_F0);
  849. objectlibrary.getlabel(lab);
  850. a_label(list, lab);
  851. list.concat(taicpu.op_reg_const_reg(A_SUB,countreg,1,countreg));
  852. list.concat(taicpu.op_ref_reg(A_LDF,src,NR_F0));
  853. list.concat(taicpu.op_reg_ref(A_STD,NR_F0,dst));
  854. //a_jmp(list,A_BC,C_NE,0,lab);
  855. rg.ungetregisterint(list,countreg);
  856. a_reg_dealloc(list,NR_F0);
  857. len := len mod 8;
  858. end;
  859. { unrolled loop }
  860. count:=len and 7;
  861. if count>0 then
  862. begin
  863. a_reg_alloc(list,NR_F0);
  864. for count2 := 1 to count do
  865. begin
  866. a_loadfpu_ref_reg(list,OS_F64,src,NR_F0);
  867. a_loadfpu_reg_ref(list,OS_F64,NR_F0,dst);
  868. inc(src.offset,8);
  869. inc(dst.offset,8);
  870. end;
  871. a_reg_dealloc(list,NR_F0);
  872. len := len mod 8;
  873. end;
  874. if (len and 4) <> 0 then
  875. begin
  876. hreg:=rg.getregisterint(list,OS_INT);
  877. a_load_ref_reg(list,OS_32,OS_32,src,hreg);
  878. a_load_reg_ref(list,OS_32,OS_32,hreg,dst);
  879. inc(src.offset,4);
  880. inc(dst.offset,4);
  881. rg.ungetregisterint(list,hreg);
  882. end;
  883. { copy the leftovers }
  884. if (len and 2) <> 0 then
  885. begin
  886. hreg:=rg.getregisterint(list,OS_INT);
  887. a_load_ref_reg(list,OS_16,OS_16,src,hreg);
  888. a_load_reg_ref(list,OS_16,OS_16,hreg,dst);
  889. inc(src.offset,2);
  890. inc(dst.offset,2);
  891. rg.ungetregisterint(list,hreg);
  892. end;
  893. if (len and 1) <> 0 then
  894. begin
  895. hreg:=rg.getregisterint(list,OS_INT);
  896. a_load_ref_reg(list,OS_8,OS_8,src,hreg);
  897. a_load_reg_ref(list,OS_8,OS_8,hreg,dst);
  898. rg.ungetregisterint(list,hreg);
  899. end;
  900. if orgsrc then
  901. begin
  902. if delsource then
  903. reference_release(list,source);
  904. end
  905. else
  906. rg.ungetregisterint(list,src.base);
  907. if not orgdst then
  908. rg.ungetregisterint(list,dst.base);
  909. end;
  910. {****************************************************************************
  911. TCG64Sparc
  912. ****************************************************************************}
  913. procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  914. begin
  915. case op of
  916. OP_ADD :
  917. begin
  918. op1:=A_ADD;
  919. op2:=A_ADDX;
  920. end;
  921. OP_SUB :
  922. begin
  923. op1:=A_SUB;
  924. op2:=A_SUBX;
  925. end;
  926. OP_XOR :
  927. begin
  928. op1:=A_XOR;
  929. op2:=A_XOR;
  930. end;
  931. OP_OR :
  932. begin
  933. op1:=A_OR;
  934. op2:=A_OR;
  935. end;
  936. OP_AND :
  937. begin
  938. op1:=A_AND;
  939. op2:=A_AND;
  940. end;
  941. else
  942. internalerror(200203241);
  943. end;
  944. end;
  945. procedure TCg64Sparc.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  946. var
  947. op1,op2 : TAsmOp;
  948. begin
  949. case op of
  950. OP_NEG :
  951. begin
  952. list.concat(taicpu.op_reg_reg_reg(A_XNOR,NR_G0,regsrc.reghi,regdst.reghi));
  953. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
  954. list.concat(taicpu.op_reg_const_reg(A_ADDX,regdst.reglo,aword(-1),regdst.reglo));
  955. exit;
  956. end;
  957. OP_NOT :
  958. begin
  959. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
  960. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
  961. exit;
  962. end;
  963. end;
  964. get_64bit_ops(op,op1,op2);
  965. list.concat(taicpu.op_reg_reg_reg(op1,regdst.reglo,regsrc.reglo,regdst.reglo));
  966. list.concat(taicpu.op_reg_reg_reg(op2,regdst.reghi,regsrc.reghi,regdst.reghi));
  967. end;
  968. procedure TCg64Sparc.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  969. var
  970. op1,op2:TAsmOp;
  971. begin
  972. case op of
  973. OP_NEG,
  974. OP_NOT :
  975. internalerror(200306017);
  976. end;
  977. get_64bit_ops(op,op1,op2);
  978. tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reglo,lo(value),regdst.reglo);
  979. tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reghi,hi(value),regdst.reghi);
  980. end;
  981. begin
  982. cg:=TCgSparc.Create;
  983. cg64:=TCg64Sparc.Create;
  984. end.
  985. {
  986. $Log$
  987. Revision 1.69 2003-10-01 20:34:49 peter
  988. * procinfo unit contains tprocinfo
  989. * cginfo renamed to cgbase
  990. * moved cgmessage to verbose
  991. * fixed ppc and sparc compiles
  992. Revision 1.68 2003/09/14 21:35:52 peter
  993. * flags2reg fixed
  994. * fixed 64bit not
  995. Revision 1.67 2003/09/14 19:19:04 peter
  996. * updates for new ra
  997. Revision 1.66 2003/09/03 15:55:01 peter
  998. * NEWRA branch merged
  999. Revision 1.65.2.1 2003/09/01 21:02:55 peter
  1000. * sparc updates for new tregister
  1001. Revision 1.65 2003/07/08 21:24:59 peter
  1002. * sparc fixes
  1003. Revision 1.64 2003/07/06 22:10:13 peter
  1004. * operand order of cmp fixed
  1005. Revision 1.63 2003/07/06 17:58:22 peter
  1006. * framepointer fixes for sparc
  1007. * parent framepointer code more generic
  1008. Revision 1.62 2003/07/03 21:09:53 peter
  1009. * delay slot NOPs and comments added
  1010. * a_loadaddr_ref_reg fixed and optimized to reuse passed register
  1011. if it is not used by the ref
  1012. Revision 1.61 2003/07/02 22:18:04 peter
  1013. * paraloc splitted in callerparaloc,calleeparaloc
  1014. * sparc calling convention updates
  1015. Revision 1.60 2003/06/17 16:35:56 peter
  1016. * a_loadaddr_ref_reg fixed
  1017. Revision 1.59 2003/06/13 21:19:32 peter
  1018. * current_procdef removed, use current_procinfo.procdef instead
  1019. Revision 1.58 2003/06/12 16:43:07 peter
  1020. * newra compiles for sparc
  1021. Revision 1.57 2003/06/04 20:59:37 mazen
  1022. + added size of destination in code gen methods
  1023. + making g_overflowcheck declaration same as
  1024. ancestor's method declaration
  1025. Revision 1.56 2003/06/01 21:38:06 peter
  1026. * getregisterfpu size parameter added
  1027. * op_const_reg size parameter added
  1028. * sparc updates
  1029. Revision 1.55 2003/06/01 01:04:35 peter
  1030. * reference fixes
  1031. Revision 1.54 2003/05/31 01:00:51 peter
  1032. * register fixes
  1033. Revision 1.53 2003/05/30 23:57:08 peter
  1034. * more sparc cleanup
  1035. * accumulator removed, splitted in function_return_reg (called) and
  1036. function_result_reg (caller)
  1037. Revision 1.52 2003/05/28 23:18:31 florian
  1038. * started to fix and clean up the sparc port
  1039. Revision 1.51 2003/05/26 22:04:57 mazen
  1040. * added 64 bit value support to fix a problem in RTL
  1041. Revision 1.50 2003/05/23 22:33:48 florian
  1042. * fix some small flaws which prevent sparc linux system unit from compiling
  1043. * some reformatting done
  1044. Revision 1.49 2003/05/22 16:11:22 florian
  1045. * fixed sparc compilation partially
  1046. Revision 1.48 2003/05/07 15:04:30 mazen
  1047. * invalid genrated code for CASE statement fixed
  1048. Revision 1.47 2003/05/06 20:25:20 mazen
  1049. * Invalid genrated code : A_JMPL changed to A_BA
  1050. Revision 1.46 2003/05/06 15:02:40 mazen
  1051. * fixed a bug in a_load_const_reg related to max 13bit value limit
  1052. for immediat value ==> use of A_SETHI for greater values
  1053. Revision 1.45 2003/04/29 11:58:21 mazen
  1054. * fixed bug of output generated assembler for a_cmp_const_ref_label
  1055. Revision 1.44 2003/04/28 09:44:42 mazen
  1056. + NOP after conditional jump instruction to prevent delay slot execution
  1057. Revision 1.43 2003/04/27 11:21:36 peter
  1058. * aktprocdef renamed to current_procinfo.procdef
  1059. * procinfo renamed to current_procinfo
  1060. * procinfo will now be stored in current_module so it can be
  1061. cleaned up properly
  1062. * gen_main_procsym changed to create_main_proc and release_main_proc
  1063. to also generate a tprocinfo structure
  1064. * fixed unit implicit initfinal
  1065. Revision 1.42 2003/03/16 20:45:45 mazen
  1066. * fixing an LD operation without refernce in loading address parameters
  1067. Revision 1.41 2003/03/10 21:59:54 mazen
  1068. * fixing index overflow in handling new registers arrays.
  1069. Revision 1.40 2003/02/25 21:41:44 mazen
  1070. * code re-aligned 2 spaces
  1071. Revision 1.39 2003/02/19 22:00:16 daniel
  1072. * Code generator converted to new register notation
  1073. - Horribily outdated todo.txt removed
  1074. Revision 1.38 2003/02/18 22:00:20 mazen
  1075. * asm condition generation modified by TAiCpu.SetCondition
  1076. Revision 1.37 2003/02/05 21:48:34 mazen
  1077. * fixing run time errors related to unimplemented abstract methods in CG
  1078. + giving empty emplementations for some RTL functions
  1079. Revision 1.36 2003/01/22 22:30:03 mazen
  1080. - internal errors rmoved from a_loar_reg_reg when reg sizes differs from 32
  1081. Revision 1.35 2003/01/20 22:21:36 mazen
  1082. * many stuff related to RTL fixed
  1083. Revision 1.34 2003/01/08 18:43:58 daniel
  1084. * Tregister changed into a record
  1085. Revision 1.33 2003/01/07 22:03:40 mazen
  1086. * adding unequaln node support to sparc compiler
  1087. Revision 1.32 2003/01/06 22:51:47 mazen
  1088. * fixing bugs related to load_reg_ref
  1089. Revision 1.31 2003/01/05 21:32:35 mazen
  1090. * fixing several bugs compiling the RTL
  1091. Revision 1.30 2003/01/05 13:36:53 florian
  1092. * x86-64 compiles
  1093. + very basic support for float128 type (x86-64 only)
  1094. Revision 1.29 2002/12/25 20:59:49 mazen
  1095. - many emitXXX removed from cga.pas in order to remove that file.
  1096. Revision 1.28 2002/12/22 19:26:31 mazen
  1097. * many internal errors related to unimplemented nodes are fixed
  1098. Revision 1.27 2002/12/21 23:21:47 mazen
  1099. + added support for the shift nodes
  1100. + added debug output on screen with -an command line option
  1101. Revision 1.26 2002/11/25 19:21:49 mazen
  1102. * fixed support of nSparcInline
  1103. Revision 1.25 2002/11/25 17:43:28 peter
  1104. * splitted defbase in defutil,symutil,defcmp
  1105. * merged isconvertable and is_equal into compare_defs(_ext)
  1106. * made operator search faster by walking the list only once
  1107. Revision 1.24 2002/11/17 17:49:09 mazen
  1108. + return_result_reg and FUNCTION_RESULT_REG are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
  1109. Revision 1.23 2002/11/10 19:07:46 mazen
  1110. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1111. Revision 1.22 2002/11/06 11:31:24 mazen
  1112. * op_reg_reg_reg don't need any more a TOpSize parameter
  1113. Revision 1.21 2002/11/05 16:15:00 mazen
  1114. *** empty log message ***
  1115. Revision 1.20 2002/11/03 20:22:40 mazen
  1116. * parameter handling updated
  1117. Revision 1.19 2002/10/28 20:59:17 mazen
  1118. * TOpSize values changed S_L --> S_SW
  1119. Revision 1.18 2002/10/22 13:43:01 mazen
  1120. - cga.pas redueced to an empty unit
  1121. Revision 1.17 2002/10/20 19:01:38 mazen
  1122. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1123. Revision 1.16 2002/10/13 21:46:07 mazen
  1124. * assembler output format fixed
  1125. Revision 1.15 2002/10/11 13:35:14 mazen
  1126. *** empty log message ***
  1127. Revision 1.14 2002/10/10 19:57:51 mazen
  1128. * Just to update repsitory
  1129. Revision 1.13 2002/10/10 15:10:39 mazen
  1130. * Internal error fixed, but usually i386 parameter model used
  1131. Revision 1.12 2002/10/08 17:17:03 mazen
  1132. *** empty log message ***
  1133. Revision 1.11 2002/10/07 20:33:04 mazen
  1134. word alignement modified in g_stack_frame
  1135. Revision 1.10 2002/10/04 21:57:42 mazen
  1136. * register allocation for parameters now done in cpupara
  1137. Revision 1.9 2002/10/02 22:20:28 mazen
  1138. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1139. Revision 1.8 2002/10/01 21:35:58 mazen
  1140. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1141. Revision 1.7 2002/10/01 21:06:29 mazen
  1142. attinst.inc --> strinst.inc
  1143. Revision 1.6 2002/10/01 17:41:50 florian
  1144. * fixed log and id
  1145. }