cgcpu.pas 49 KB

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