cgcpu.pas 50 KB

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