cgcpu.pas 48 KB

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