cgcpu.pas 47 KB

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