cgcpu.pas 46 KB

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