cgcpu.pas 47 KB

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