cgcpu.pas 43 KB

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