cgcpu.pas 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the code generator for the SPARC
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit cgcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,parabase,
  22. cgbase,cgutils,cgobj,cg64f32,
  23. aasmbase,aasmtai,aasmdata,aasmcpu,
  24. cpubase,cpuinfo,
  25. node,symconst,SymType,symdef,
  26. rgcpu;
  27. type
  28. TCgSparc=class(tcg)
  29. protected
  30. function IsSimpleRef(const ref:treference):boolean;
  31. public
  32. procedure init_register_allocators;override;
  33. procedure done_register_allocators;override;
  34. function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override;
  35. { sparc special, needed by cg64 }
  36. procedure make_simple_ref(list:TAsmList;var ref: treference);
  37. procedure handle_load_store(list:TAsmList;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
  38. procedure handle_reg_const_reg(list:TAsmList;op:Tasmop;src:tregister;a:tcgint;dst:tregister);
  39. { parameter }
  40. procedure a_load_const_cgpara(list:TAsmList;size:tcgsize;a:tcgint;const paraloc:TCGPara);override;
  41. procedure a_load_ref_cgpara(list:TAsmList;sz:tcgsize;const r:TReference;const paraloc:TCGPara);override;
  42. procedure a_loadaddr_ref_cgpara(list:TAsmList;const r:TReference;const paraloc:TCGPara);override;
  43. procedure a_loadfpu_reg_cgpara(list : TAsmList;size : tcgsize;const r : tregister;const paraloc : TCGPara);override;
  44. procedure a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);override;
  45. procedure a_call_name(list:TAsmList;const s:string; weak: boolean);override;
  46. procedure a_call_reg(list:TAsmList;Reg:TRegister);override;
  47. { General purpose instructions }
  48. procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
  49. procedure a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:tcgint;reg:TRegister);override;
  50. procedure a_op_reg_reg(list:TAsmList;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  51. procedure a_op_const_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;a:tcgint;src, dst:tregister);override;
  52. procedure a_op_reg_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  53. procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
  54. procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);override;
  55. { move instructions }
  56. procedure a_load_const_reg(list:TAsmList;size:tcgsize;a:tcgint;reg:tregister);override;
  57. procedure a_load_const_ref(list:TAsmList;size:tcgsize;a:tcgint;const ref:TReference);override;
  58. procedure a_load_reg_ref(list:TAsmList;FromSize,ToSize:TCgSize;reg:TRegister;const ref:TReference);override;
  59. procedure a_load_ref_reg(list:TAsmList;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);override;
  60. procedure a_load_reg_reg(list:TAsmList;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
  61. procedure a_loadaddr_ref_reg(list:TAsmList;const ref:TReference;r:tregister);override;
  62. { fpu move instructions }
  63. procedure a_loadfpu_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1, reg2:tregister);override;
  64. procedure a_loadfpu_ref_reg(list:TAsmList;fromsize,tosize:tcgsize;const ref:TReference;reg:tregister);override;
  65. procedure a_loadfpu_reg_ref(list:TAsmList;fromsize,tosize:tcgsize;reg:tregister;const ref:TReference);override;
  66. { comparison operations }
  67. procedure a_cmp_const_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;a:tcgint;reg:tregister;l:tasmlabel);override;
  68. procedure a_cmp_reg_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  69. procedure a_jmp_always(List:TAsmList;l:TAsmLabel);override;
  70. procedure a_jmp_name(list : TAsmList;const s : string);override;
  71. procedure a_jmp_cond(list:TAsmList;cond:TOpCmp;l:tasmlabel);{ override;}
  72. procedure a_jmp_flags(list:TAsmList;const f:TResFlags;l:tasmlabel);override;
  73. procedure g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister);override;
  74. procedure g_overflowCheck(List:TAsmList;const Loc:TLocation;def:TDef);override;
  75. procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);override;
  76. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
  77. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);override;
  78. procedure g_maybe_got_init(list: TAsmList); override;
  79. procedure g_restore_registers(list:TAsmList);override;
  80. procedure g_save_registers(list : TAsmList);override;
  81. procedure g_concatcopy(list : TAsmList;const source,dest : treference;len : tcgint);override;
  82. procedure g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);override;
  83. procedure g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  84. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
  85. procedure g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string);override;
  86. { Transform unsupported methods into Internal errors }
  87. procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister); override;
  88. procedure g_stackpointer_alloc(list : TAsmList;localsize : longint);override;
  89. private
  90. g1_used : boolean;
  91. use_unlimited_pic_mode : boolean;
  92. end;
  93. TCg64Sparc=class(tcg64f32)
  94. private
  95. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
  96. public
  97. procedure a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);override;
  98. procedure a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);override;
  99. procedure a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);override;
  100. procedure a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);override;
  101. procedure a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);override;
  102. procedure a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64);override;
  103. procedure a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);override;
  104. procedure a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  105. procedure a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);override;
  106. end;
  107. procedure create_codegen;
  108. const
  109. TOpCG2AsmOp : array[topcg] of TAsmOp=(
  110. A_NONE,A_MOV,A_ADD,A_AND,A_UDIV,A_SDIV,A_SMUL,A_UMUL,A_NEG,A_NOT,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR,A_NONE,A_NONE
  111. );
  112. TOpCG2AsmOpWithFlags : array[topcg] of TAsmOp=(
  113. A_NONE,A_MOV,A_ADDcc,A_ANDcc,A_UDIVcc,A_SDIVcc,A_SMULcc,A_UMULcc,A_NEG,A_NOT,A_ORcc,A_SRA,A_SLL,A_SRL,A_SUBcc,A_XORcc,A_NONE,A_NONE
  114. );
  115. TOpCmp2AsmCond : array[topcmp] of TAsmCond=(C_NONE,
  116. C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A
  117. );
  118. implementation
  119. uses
  120. globals,verbose,systems,cutils,
  121. paramgr,fmodule,
  122. symtable,
  123. tgobj,
  124. procinfo,cpupi;
  125. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  126. begin
  127. result :=not(assigned(ref.symbol))and
  128. (((ref.index = NR_NO) and
  129. (ref.offset >= simm13lo) and
  130. (ref.offset <= simm13hi)) or
  131. ((ref.index <> NR_NO) and
  132. (ref.offset = 0)));
  133. end;
  134. procedure tcgsparc.make_simple_ref(list:TAsmList;var ref: treference);
  135. var
  136. href: treference;
  137. hreg,hreg2: tregister;
  138. begin
  139. if (ref.refaddr<>addr_no) then
  140. InternalError(2013022802);
  141. if (ref.base=NR_NO) then
  142. begin
  143. ref.base:=ref.index;
  144. ref.index:=NR_NO;
  145. end;
  146. if IsSimpleRef(ref) then
  147. exit;
  148. if (ref.symbol=nil) then
  149. begin
  150. hreg:=getintregister(list,OS_INT);
  151. if (ref.index=NR_NO) then
  152. a_load_const_reg(list,OS_INT,ref.offset,hreg)
  153. else
  154. begin
  155. if (ref.offset<simm13lo) or (ref.offset>simm13hi-sizeof(pint)) then
  156. begin
  157. a_load_const_reg(list,OS_INT,ref.offset,hreg);
  158. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,hreg));
  159. end
  160. else
  161. list.concat(taicpu.op_reg_const_reg(A_ADD,ref.index,ref.offset,hreg));
  162. end;
  163. if (ref.base=NR_NO) then
  164. ref.base:=hreg
  165. else
  166. ref.index:=hreg;
  167. ref.offset:=0;
  168. exit;
  169. end;
  170. reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
  171. hreg:=getintregister(list,OS_INT);
  172. if not (cs_create_pic in current_settings.moduleswitches) then
  173. begin
  174. { absolute loads allow any offset to be encoded into relocation }
  175. href.refaddr:=addr_high;
  176. list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
  177. if (ref.base=NR_NO) and (ref.index=NR_NO) then
  178. begin
  179. ref.base:=hreg;
  180. ref.refaddr:=addr_low;
  181. exit;
  182. end;
  183. { base present -> load the entire address and use it as index }
  184. href.refaddr:=addr_low;
  185. list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
  186. ref.symbol:=nil;
  187. ref.offset:=0;
  188. if (ref.index<>NR_NO) then
  189. list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.index,hreg,hreg));
  190. ref.index:=hreg;
  191. end
  192. else
  193. begin
  194. include(current_procinfo.flags,pi_needs_got);
  195. href.offset:=0;
  196. if use_unlimited_pic_mode then
  197. begin
  198. href.refaddr:=addr_high;
  199. list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
  200. href.refaddr:=addr_low;
  201. list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
  202. reference_reset_base(href,hreg,0,sizeof(pint));
  203. href.index:=current_procinfo.got;
  204. end
  205. else
  206. begin
  207. href.base:=current_procinfo.got;
  208. href.refaddr:=addr_pic;
  209. end;
  210. list.concat(taicpu.op_ref_reg(A_LD,href,hreg));
  211. ref.symbol:=nil;
  212. { hreg now holds symbol address. Add remaining members. }
  213. if (ref.offset>=simm13lo) and (ref.offset<=simm13hi-sizeof(pint)) then
  214. begin
  215. if (ref.base=NR_NO) then
  216. ref.base:=hreg
  217. else
  218. begin
  219. if (ref.offset<>0) then
  220. list.concat(taicpu.op_reg_const_reg(A_ADD,hreg,ref.offset,hreg));
  221. if (ref.index<>NR_NO) then
  222. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,hreg));
  223. ref.index:=hreg;
  224. ref.offset:=0;
  225. end;
  226. end
  227. else { large offset, need another register to deal with it }
  228. begin
  229. hreg2:=getintregister(list,OS_INT);
  230. a_load_const_reg(list,OS_INT,ref.offset,hreg2);
  231. if (ref.index<>NR_NO) then
  232. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg2,ref.index,hreg2));
  233. if (ref.base<>NR_NO) then
  234. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg2,ref.base,hreg2));
  235. ref.base:=hreg;
  236. ref.index:=hreg2;
  237. ref.offset:=0;
  238. end;
  239. end;
  240. end;
  241. procedure tcgsparc.handle_load_store(list:TAsmList;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
  242. begin
  243. make_simple_ref(list,ref);
  244. if isstore then
  245. list.concat(taicpu.op_reg_ref(op,reg,ref))
  246. else
  247. list.concat(taicpu.op_ref_reg(op,ref,reg));
  248. end;
  249. procedure tcgsparc.handle_reg_const_reg(list:TAsmList;op:Tasmop;src:tregister;a:tcgint;dst:tregister);
  250. var
  251. tmpreg : tregister;
  252. begin
  253. if (a<simm13lo) or
  254. (a>simm13hi) then
  255. begin
  256. if g1_used then
  257. tmpreg:=GetIntRegister(list,OS_INT)
  258. else
  259. begin
  260. tmpreg:=NR_G1;
  261. g1_used:=true;
  262. end;
  263. a_load_const_reg(list,OS_INT,a,tmpreg);
  264. list.concat(taicpu.op_reg_reg_reg(op,src,tmpreg,dst));
  265. if tmpreg=NR_G1 then
  266. g1_used:=false;
  267. end
  268. else
  269. list.concat(taicpu.op_reg_const_reg(op,src,a,dst));
  270. end;
  271. {****************************************************************************
  272. Assembler code
  273. ****************************************************************************}
  274. procedure Tcgsparc.init_register_allocators;
  275. begin
  276. inherited init_register_allocators;
  277. rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD,
  278. [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,RS_O7,
  279. RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7,
  280. RS_I0,RS_I1,RS_I2,RS_I3,RS_I4,RS_I5],
  281. first_int_imreg,[]);
  282. rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBFS,
  283. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
  284. RS_F8,RS_F9,RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,
  285. RS_F16,RS_F17,RS_F18,RS_F19,RS_F20,RS_F21,RS_F22,RS_F23,
  286. RS_F24,RS_F25,RS_F26,RS_F27,RS_F28,RS_F29,RS_F30,RS_F31],
  287. first_fpu_imreg,[]);
  288. { needs at least one element for rgobj not to crash }
  289. rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
  290. [RS_L0],first_mm_imreg,[]);
  291. end;
  292. procedure Tcgsparc.done_register_allocators;
  293. begin
  294. rg[R_INTREGISTER].free;
  295. rg[R_FPUREGISTER].free;
  296. rg[R_MMREGISTER].free;
  297. inherited done_register_allocators;
  298. end;
  299. function tcgsparc.getfpuregister(list:TAsmList;size:Tcgsize):Tregister;
  300. begin
  301. if size=OS_F64 then
  302. result:=rg[R_FPUREGISTER].getregister(list,R_SUBFD)
  303. else
  304. result:=rg[R_FPUREGISTER].getregister(list,R_SUBFS);
  305. end;
  306. procedure TCgSparc.a_load_const_cgpara(list:TAsmList;size:tcgsize;a:tcgint;const paraloc:TCGPara);
  307. var
  308. Ref:TReference;
  309. begin
  310. paraloc.check_simple_location;
  311. paramanager.alloccgpara(list,paraloc);
  312. case paraloc.location^.loc of
  313. LOC_REGISTER,LOC_CREGISTER:
  314. a_load_const_reg(list,size,a,paraloc.location^.register);
  315. LOC_REFERENCE:
  316. begin
  317. { Code conventions need the parameters being allocated in %o6+92 }
  318. with paraloc.location^.Reference do
  319. begin
  320. if (Index=NR_SP) and (Offset<Target_info.first_parm_offset) then
  321. InternalError(2002081104);
  322. reference_reset_base(ref,index,offset,paraloc.alignment);
  323. end;
  324. a_load_const_ref(list,size,a,ref);
  325. end;
  326. else
  327. InternalError(2002122200);
  328. end;
  329. end;
  330. procedure TCgSparc.a_load_ref_cgpara(list:TAsmList;sz:TCgSize;const r:TReference;const paraloc:TCGPara);
  331. var
  332. ref: treference;
  333. tmpreg:TRegister;
  334. begin
  335. paraloc.check_simple_location;
  336. paramanager.alloccgpara(list,paraloc);
  337. with paraloc.location^ do
  338. begin
  339. case loc of
  340. LOC_REGISTER,LOC_CREGISTER :
  341. a_load_ref_reg(list,sz,paraloc.location^.size,r,Register);
  342. LOC_REFERENCE:
  343. begin
  344. { Code conventions need the parameters being allocated in %o6+92 }
  345. with Reference do
  346. begin
  347. if (Index=NR_SP) and (Offset<Target_info.first_parm_offset) then
  348. InternalError(2002081104);
  349. reference_reset_base(ref,index,offset,paraloc.alignment);
  350. end;
  351. if g1_used then
  352. tmpreg:=GetIntRegister(list,OS_INT)
  353. else
  354. begin
  355. tmpreg:=NR_G1;
  356. g1_used:=true;
  357. end;
  358. a_load_ref_reg(list,sz,sz,r,tmpreg);
  359. a_load_reg_ref(list,sz,sz,tmpreg,ref);
  360. if tmpreg=NR_G1 then
  361. g1_used:=false;
  362. end;
  363. else
  364. internalerror(2002081103);
  365. end;
  366. end;
  367. end;
  368. procedure TCgSparc.a_loadaddr_ref_cgpara(list:TAsmList;const r:TReference;const paraloc:TCGPara);
  369. var
  370. Ref:TReference;
  371. TmpReg:TRegister;
  372. begin
  373. paraloc.check_simple_location;
  374. paramanager.alloccgpara(list,paraloc);
  375. with paraloc.location^ do
  376. begin
  377. case loc of
  378. LOC_REGISTER,LOC_CREGISTER:
  379. a_loadaddr_ref_reg(list,r,register);
  380. LOC_REFERENCE:
  381. begin
  382. reference_reset(ref,paraloc.alignment);
  383. ref.base := reference.index;
  384. ref.offset := reference.offset;
  385. tmpreg:=GetAddressRegister(list);
  386. a_loadaddr_ref_reg(list,r,tmpreg);
  387. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  388. end;
  389. else
  390. internalerror(2002080701);
  391. end;
  392. end;
  393. end;
  394. procedure tcgsparc.a_loadfpu_ref_cgpara(list : TAsmList;size : tcgsize;const ref : treference;const paraloc : TCGPara);
  395. var
  396. href,href2 : treference;
  397. hloc : pcgparalocation;
  398. begin
  399. href:=ref;
  400. hloc:=paraloc.location;
  401. while assigned(hloc) do
  402. begin
  403. paramanager.allocparaloc(list,hloc);
  404. case hloc^.loc of
  405. LOC_REGISTER,LOC_CREGISTER :
  406. a_load_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
  407. LOC_REFERENCE :
  408. begin
  409. reference_reset_base(href2,hloc^.reference.index,hloc^.reference.offset,paraloc.alignment);
  410. a_load_ref_ref(list,hloc^.size,hloc^.size,href,href2);
  411. end;
  412. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  413. a_loadfpu_ref_reg(list,hloc^.size,hloc^.size,href,hloc^.register);
  414. else
  415. internalerror(200408241);
  416. end;
  417. inc(href.offset,tcgsize2size[hloc^.size]);
  418. hloc:=hloc^.next;
  419. end;
  420. end;
  421. procedure tcgsparc.a_loadfpu_reg_cgpara(list : TAsmList;size : tcgsize;const r : tregister;const paraloc : TCGPara);
  422. var
  423. href : treference;
  424. begin
  425. { happens for function result loc }
  426. if paraloc.location^.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  427. begin
  428. paraloc.check_simple_location;
  429. paramanager.allocparaloc(list,paraloc.location);
  430. a_loadfpu_reg_reg(list,size,paraloc.location^.size,r,paraloc.location^.register);
  431. end
  432. else
  433. begin
  434. tg.GetTemp(list,TCGSize2Size[size],TCGSize2Size[size],tt_normal,href);
  435. a_loadfpu_reg_ref(list,size,size,r,href);
  436. a_loadfpu_ref_cgpara(list,size,href,paraloc);
  437. tg.Ungettemp(list,href);
  438. end;
  439. end;
  440. procedure TCgSparc.a_call_name(list:TAsmList;const s:string; weak: boolean);
  441. begin
  442. if not weak then
  443. list.concat(taicpu.op_sym(A_CALL,current_asmdata.RefAsmSymbol(s)))
  444. else
  445. list.concat(taicpu.op_sym(A_CALL,current_asmdata.WeakRefAsmSymbol(s)));
  446. { Delay slot }
  447. list.concat(taicpu.op_none(A_NOP));
  448. end;
  449. procedure TCgSparc.a_call_reg(list:TAsmList;Reg:TRegister);
  450. begin
  451. list.concat(taicpu.op_reg(A_CALL,reg));
  452. { Delay slot }
  453. list.concat(taicpu.op_none(A_NOP));
  454. end;
  455. {********************** load instructions ********************}
  456. procedure TCgSparc.a_load_const_reg(list : TAsmList;size : TCGSize;a : tcgint;reg : TRegister);
  457. begin
  458. { we don't use the set instruction here because it could be evalutated to two
  459. instructions which would cause problems with the delay slot (FK) }
  460. if (a=0) then
  461. list.concat(taicpu.op_reg(A_CLR,reg))
  462. { sethi allows to set the upper 22 bit, so we'll take full advantage of it }
  463. else if (aint(a) and aint($1fff))=0 then
  464. list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg))
  465. else if (a>=simm13lo) and (a<=simm13hi) then
  466. list.concat(taicpu.op_const_reg(A_MOV,a,reg))
  467. else
  468. begin
  469. list.concat(taicpu.op_const_reg(A_SETHI,aint(a) shr 10,reg));
  470. list.concat(taicpu.op_reg_const_reg(A_OR,reg,aint(a) and aint($3ff),reg));
  471. end;
  472. end;
  473. procedure TCgSparc.a_load_const_ref(list : TAsmList;size : tcgsize;a : tcgint;const ref : TReference);
  474. begin
  475. if a=0 then
  476. a_load_reg_ref(list,size,size,NR_G0,ref)
  477. else
  478. inherited a_load_const_ref(list,size,a,ref);
  479. end;
  480. procedure TCgSparc.a_load_reg_ref(list:TAsmList;FromSize,ToSize:TCGSize;reg:tregister;const Ref:TReference);
  481. var
  482. op : tasmop;
  483. begin
  484. if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
  485. fromsize := tosize;
  486. if (ref.alignment<>0) and
  487. (ref.alignment<tcgsize2size[tosize]) then
  488. begin
  489. a_load_reg_ref_unaligned(list,FromSize,ToSize,reg,ref);
  490. end
  491. else
  492. begin
  493. case tosize of
  494. { signed integer registers }
  495. OS_8,
  496. OS_S8:
  497. Op:=A_STB;
  498. OS_16,
  499. OS_S16:
  500. Op:=A_STH;
  501. OS_32,
  502. OS_S32:
  503. Op:=A_ST;
  504. else
  505. InternalError(2002122100);
  506. end;
  507. handle_load_store(list,true,op,reg,ref);
  508. end;
  509. end;
  510. procedure TCgSparc.a_load_ref_reg(list:TAsmList;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);
  511. var
  512. op : tasmop;
  513. begin
  514. if (TCGSize2Size[fromsize] >= TCGSize2Size[tosize]) then
  515. fromsize := tosize;
  516. if (ref.alignment<>0) and
  517. (ref.alignment<tcgsize2size[fromsize]) then
  518. begin
  519. a_load_ref_reg_unaligned(list,FromSize,ToSize,ref,reg);
  520. end
  521. else
  522. begin
  523. case fromsize of
  524. OS_S8:
  525. Op:=A_LDSB;{Load Signed Byte}
  526. OS_8:
  527. Op:=A_LDUB;{Load Unsigned Byte}
  528. OS_S16:
  529. Op:=A_LDSH;{Load Signed Halfword}
  530. OS_16:
  531. Op:=A_LDUH;{Load Unsigned Halfword}
  532. OS_S32,
  533. OS_32:
  534. Op:=A_LD;{Load Word}
  535. OS_S64,
  536. OS_64:
  537. Op:=A_LDD;{Load a Long Word}
  538. else
  539. InternalError(2002122101);
  540. end;
  541. handle_load_store(list,false,op,reg,ref);
  542. if (fromsize=OS_S8) and
  543. (tosize=OS_16) then
  544. a_load_reg_reg(list,fromsize,tosize,reg,reg);
  545. end;
  546. end;
  547. procedure TCgSparc.a_load_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  548. var
  549. instr : taicpu;
  550. begin
  551. if (tcgsize2size[fromsize] > tcgsize2size[tosize]) or
  552. ((tcgsize2size[fromsize] = tcgsize2size[tosize]) and
  553. (fromsize <> tosize)) or
  554. { needs to mask out the sign in the top 16 bits }
  555. ((fromsize = OS_S8) and
  556. (tosize = OS_16)) then
  557. case tosize of
  558. OS_8 :
  559. a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
  560. OS_16 :
  561. begin
  562. list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
  563. list.concat(taicpu.op_reg_const_reg(A_SRL,reg2,16,reg2));
  564. end;
  565. OS_32,
  566. OS_S32 :
  567. begin
  568. instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
  569. list.Concat(instr);
  570. { Notify the register allocator that we have written a move instruction so
  571. it can try to eliminate it. }
  572. add_move_instruction(instr);
  573. end;
  574. OS_S8 :
  575. begin
  576. list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,24,reg2));
  577. list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,24,reg2));
  578. end;
  579. OS_S16 :
  580. begin
  581. list.concat(taicpu.op_reg_const_reg(A_SLL,reg1,16,reg2));
  582. list.concat(taicpu.op_reg_const_reg(A_SRA,reg2,16,reg2));
  583. end;
  584. else
  585. internalerror(2002090901);
  586. end
  587. else
  588. begin
  589. instr:=taicpu.op_reg_reg(A_MOV,reg1,reg2);
  590. list.Concat(instr);
  591. { Notify the register allocator that we have written a move instruction so
  592. it can try to eliminate it. }
  593. add_move_instruction(instr);
  594. end;
  595. end;
  596. procedure TCgSparc.a_loadaddr_ref_reg(list : TAsmList;const ref : TReference;r : tregister);
  597. var
  598. href: treference;
  599. hreg: tregister;
  600. begin
  601. if (ref.base=NR_NO) and (ref.index<>NR_NO) then
  602. internalerror(200306171);
  603. if (ref.symbol=nil) then
  604. begin
  605. if (ref.base<>NR_NO) then
  606. begin
  607. if (ref.offset<simm13lo) or (ref.offset>simm13hi) then
  608. begin
  609. hreg:=getintregister(list,OS_INT);
  610. a_load_const_reg(list,OS_INT,ref.offset,hreg);
  611. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,r));
  612. if (ref.index<>NR_NO) then
  613. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
  614. end
  615. else if (ref.offset<>0) then
  616. begin
  617. list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,r));
  618. if (ref.index<>NR_NO) then
  619. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
  620. end
  621. else if (ref.index<>NR_NO) then
  622. list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,r))
  623. else
  624. a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r); { (try to) emit optimizable move }
  625. end
  626. else
  627. a_load_const_reg(list,OS_INT,ref.offset,r);
  628. exit;
  629. end;
  630. reference_reset_symbol(href,ref.symbol,ref.offset,ref.alignment);
  631. if (cs_create_pic in current_settings.moduleswitches) then
  632. begin
  633. include(current_procinfo.flags,pi_needs_got);
  634. href.offset:=0;
  635. if use_unlimited_pic_mode then
  636. begin
  637. href.refaddr:=addr_high;
  638. list.concat(taicpu.op_ref_reg(A_SETHI,href,r));
  639. href.refaddr:=addr_low;
  640. list.concat(taicpu.op_reg_ref_reg(A_OR,r,href,r));
  641. reference_reset_base(href,r,0,sizeof(pint));
  642. href.index:=current_procinfo.got;
  643. end
  644. else
  645. begin
  646. href.base:=current_procinfo.got;
  647. href.refaddr:=addr_pic; { should it be done THAT way?? }
  648. end;
  649. { load contents of GOT slot }
  650. list.concat(taicpu.op_ref_reg(A_LD,href,r));
  651. { add original base/index, if any }
  652. if (ref.base<>NR_NO) then
  653. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.base,r));
  654. if (ref.index<>NR_NO) then
  655. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
  656. { finally, add offset }
  657. if (ref.offset<simm13lo) or (ref.offset>simm13hi) then
  658. begin
  659. hreg:=getintregister(list,OS_INT);
  660. a_load_const_reg(list,OS_INT,ref.offset,hreg);
  661. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,r,r));
  662. end
  663. else if (ref.offset<>0) then
  664. list.concat(taicpu.op_reg_const_reg(A_ADD,r,ref.offset,r));
  665. end
  666. else
  667. begin
  668. { load symbol+offset }
  669. href.refaddr:=addr_high;
  670. list.concat(taicpu.op_ref_reg(A_SETHI,href,r));
  671. href.refaddr:=addr_low;
  672. list.concat(taicpu.op_reg_ref_reg(A_OR,r,href,r));
  673. { add original base/index, if any }
  674. if (ref.base<>NR_NO) then
  675. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.base,r));
  676. if (ref.index<>NR_NO) then
  677. list.concat(taicpu.op_reg_reg_reg(A_ADD,r,ref.index,r));
  678. end;
  679. end;
  680. procedure TCgSparc.a_loadfpu_reg_reg(list:TAsmList;fromsize,tosize:tcgsize;reg1, reg2:tregister);
  681. const
  682. FpuMovInstr : Array[OS_F32..OS_F64,OS_F32..OS_F64] of TAsmOp =
  683. ((A_FMOVS,A_FSTOD),(A_FDTOS,A_FMOVD));
  684. var
  685. op: TAsmOp;
  686. instr : taicpu;
  687. begin
  688. op:=fpumovinstr[fromsize,tosize];
  689. instr:=taicpu.op_reg_reg(op,reg1,reg2);
  690. list.Concat(instr);
  691. { Notify the register allocator that we have written a move instruction so
  692. it can try to eliminate it. }
  693. if (op = A_FMOVS) or
  694. (op = A_FMOVD) then
  695. add_move_instruction(instr);
  696. end;
  697. procedure TCgSparc.a_loadfpu_ref_reg(list:TAsmList;fromsize,tosize:tcgsize;const ref:TReference;reg:tregister);
  698. const
  699. FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
  700. (A_LDF,A_LDDF);
  701. var
  702. tmpreg: tregister;
  703. begin
  704. tmpreg:=NR_NO;
  705. if (fromsize<>tosize) then
  706. begin
  707. tmpreg:=reg;
  708. reg:=getfpuregister(list,fromsize);
  709. end;
  710. handle_load_store(list,false,fpuloadinstr[fromsize],reg,ref);
  711. if (fromsize<>tosize) then
  712. a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
  713. end;
  714. procedure TCgSparc.a_loadfpu_reg_ref(list:TAsmList;fromsize,tosize:tcgsize;reg:tregister;const ref:TReference);
  715. const
  716. FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
  717. (A_STF,A_STDF);
  718. var
  719. tmpreg: tregister;
  720. begin
  721. if (fromsize<>tosize) then
  722. begin
  723. tmpreg:=getfpuregister(list,tosize);
  724. a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
  725. reg:=tmpreg;
  726. end;
  727. handle_load_store(list,true,fpuloadinstr[tosize],reg,ref);
  728. end;
  729. procedure tcgsparc.maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
  730. const
  731. overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  732. begin
  733. if (op in overflowops) and
  734. (size in [OS_8,OS_S8,OS_16,OS_S16]) then
  735. a_load_reg_reg(list,OS_32,size,dst,dst);
  736. end;
  737. procedure TCgSparc.a_op_const_reg(list:TAsmList;Op:TOpCG;size:tcgsize;a:tcgint;reg:TRegister);
  738. begin
  739. optimize_op_const(op,a);
  740. case op of
  741. OP_NONE:
  742. exit;
  743. OP_MOVE:
  744. a_load_const_reg(list,size,a,reg);
  745. OP_NEG,OP_NOT:
  746. internalerror(200306011);
  747. else
  748. a_op_const_reg_reg(list,op,size,a,reg,reg);
  749. end;
  750. end;
  751. procedure TCgSparc.a_op_reg_reg(list:TAsmList;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  752. var
  753. a : aint;
  754. begin
  755. Case Op of
  756. OP_NEG :
  757. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],src,dst));
  758. OP_NOT :
  759. begin
  760. case size of
  761. OS_8 :
  762. a:=aint($ffffff00);
  763. OS_16 :
  764. a:=aint($ffff0000);
  765. else
  766. a:=0;
  767. end;
  768. handle_reg_const_reg(list,A_XNOR,src,a,dst);
  769. end;
  770. else
  771. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
  772. end;
  773. maybeadjustresult(list,op,size,dst);
  774. end;
  775. procedure TCgSparc.a_op_const_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;a:tcgint;src, dst:tregister);
  776. var
  777. l: TLocation;
  778. begin
  779. a_op_const_reg_reg_checkoverflow(list,op,size,a,src,dst,false,l);
  780. end;
  781. procedure TCgSparc.a_op_reg_reg_reg(list:TAsmList;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
  782. begin
  783. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
  784. maybeadjustresult(list,op,size,dst);
  785. end;
  786. procedure tcgsparc.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation);
  787. var
  788. tmpreg1,tmpreg2 : tregister;
  789. begin
  790. ovloc.loc:=LOC_VOID;
  791. optimize_op_const(op,a);
  792. case op of
  793. OP_NONE:
  794. begin
  795. a_load_reg_reg(list,size,size,src,dst);
  796. exit;
  797. end;
  798. OP_MOVE:
  799. begin
  800. a_load_const_reg(list,size,a,dst);
  801. exit;
  802. end;
  803. end;
  804. if setflags then
  805. begin
  806. handle_reg_const_reg(list,TOpCG2AsmOpWithFlags[op],src,a,dst);
  807. case op of
  808. OP_MUL:
  809. begin
  810. tmpreg1:=GetIntRegister(list,OS_INT);
  811. list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
  812. list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
  813. ovloc.loc:=LOC_FLAGS;
  814. ovloc.resflags:=F_NE;
  815. end;
  816. OP_IMUL:
  817. begin
  818. tmpreg1:=GetIntRegister(list,OS_INT);
  819. tmpreg2:=GetIntRegister(list,OS_INT);
  820. list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
  821. list.concat(taicpu.op_reg_const_reg(A_SRA,dst,31,tmpreg2));
  822. list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
  823. ovloc.loc:=LOC_FLAGS;
  824. ovloc.resflags:=F_NE;
  825. end;
  826. end;
  827. end
  828. else
  829. handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
  830. maybeadjustresult(list,op,size,dst);
  831. end;
  832. procedure tcgsparc.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tcgsize; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation);
  833. var
  834. tmpreg1,tmpreg2 : tregister;
  835. begin
  836. ovloc.loc:=LOC_VOID;
  837. if setflags then
  838. begin
  839. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOpWithFlags[op],src2,src1,dst));
  840. case op of
  841. OP_MUL:
  842. begin
  843. tmpreg1:=GetIntRegister(list,OS_INT);
  844. list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
  845. list.concat(taicpu.op_reg_reg(A_CMP,NR_G0,tmpreg1));
  846. ovloc.loc:=LOC_FLAGS;
  847. ovloc.resflags:=F_NE;
  848. end;
  849. OP_IMUL:
  850. begin
  851. tmpreg1:=GetIntRegister(list,OS_INT);
  852. tmpreg2:=GetIntRegister(list,OS_INT);
  853. list.concat(taicpu.op_reg_reg(A_MOV,NR_Y,tmpreg1));
  854. list.concat(taicpu.op_reg_const_reg(A_SRL,dst,31,tmpreg2));
  855. list.concat(taicpu.op_reg_reg(A_CMP,tmpreg1,tmpreg2));
  856. ovloc.loc:=LOC_FLAGS;
  857. ovloc.resflags:=F_NE;
  858. end;
  859. end;
  860. end
  861. else
  862. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
  863. maybeadjustresult(list,op,size,dst);
  864. end;
  865. {*************** compare instructructions ****************}
  866. procedure TCgSparc.a_cmp_const_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;a:tcgint;reg:tregister;l:tasmlabel);
  867. begin
  868. if (a=0) then
  869. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg,NR_G0,NR_G0))
  870. else
  871. handle_reg_const_reg(list,A_SUBcc,reg,a,NR_G0);
  872. a_jmp_cond(list,cmp_op,l);
  873. end;
  874. procedure TCgSparc.a_cmp_reg_reg_label(list:TAsmList;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);
  875. begin
  876. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg2,reg1,NR_G0));
  877. a_jmp_cond(list,cmp_op,l);
  878. end;
  879. procedure TCgSparc.a_jmp_always(List:TAsmList;l:TAsmLabel);
  880. begin
  881. List.Concat(TAiCpu.op_sym(A_BA,current_asmdata.RefAsmSymbol(l.name)));
  882. { Delay slot }
  883. list.Concat(TAiCpu.Op_none(A_NOP));
  884. end;
  885. procedure tcgsparc.a_jmp_name(list : TAsmList;const s : string);
  886. begin
  887. List.Concat(TAiCpu.op_sym(A_BA,current_asmdata.RefAsmSymbol(s)));
  888. { Delay slot }
  889. list.Concat(TAiCpu.Op_none(A_NOP));
  890. end;
  891. procedure TCgSparc.a_jmp_cond(list:TAsmList;cond:TOpCmp;l:TAsmLabel);
  892. var
  893. ai:TAiCpu;
  894. begin
  895. ai:=TAiCpu.Op_sym(A_Bxx,l);
  896. ai.SetCondition(TOpCmp2AsmCond[cond]);
  897. list.Concat(ai);
  898. { Delay slot }
  899. list.Concat(TAiCpu.Op_none(A_NOP));
  900. end;
  901. procedure TCgSparc.a_jmp_flags(list:TAsmList;const f:TResFlags;l:tasmlabel);
  902. var
  903. ai : taicpu;
  904. begin
  905. ai:=Taicpu.op_sym(A_Bxx,l);
  906. ai.SetCondition(flags_to_cond(f));
  907. list.Concat(ai);
  908. { Delay slot }
  909. list.Concat(TAiCpu.Op_none(A_NOP));
  910. end;
  911. procedure TCgSparc.g_flags2reg(list:TAsmList;Size:TCgSize;const f:tresflags;reg:TRegister);
  912. var
  913. hl : tasmlabel;
  914. begin
  915. current_asmdata.getjumplabel(hl);
  916. a_load_const_reg(list,size,1,reg);
  917. a_jmp_flags(list,f,hl);
  918. a_load_const_reg(list,size,0,reg);
  919. a_label(list,hl);
  920. end;
  921. procedure tcgsparc.g_overflowCheck(List:TAsmList;const Loc:TLocation;def:TDef);
  922. var
  923. l : tlocation;
  924. begin
  925. l.loc:=LOC_VOID;
  926. g_overflowCheck_loc(list,loc,def,l);
  927. end;
  928. procedure TCgSparc.g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;ovloc : tlocation);
  929. var
  930. hl : tasmlabel;
  931. ai:TAiCpu;
  932. hflags : tresflags;
  933. begin
  934. if not(cs_check_overflow in current_settings.localswitches) then
  935. exit;
  936. current_asmdata.getjumplabel(hl);
  937. case ovloc.loc of
  938. LOC_VOID:
  939. begin
  940. if not((def.typ=pointerdef) or
  941. ((def.typ=orddef) and
  942. (torddef(def).ordtype in [u64bit,u16bit,u32bit,u8bit,uchar,
  943. pasbool8,pasbool16,pasbool32,pasbool64]))) then
  944. begin
  945. ai:=TAiCpu.Op_sym(A_Bxx,hl);
  946. ai.SetCondition(C_NO);
  947. list.Concat(ai);
  948. { Delay slot }
  949. list.Concat(TAiCpu.Op_none(A_NOP));
  950. end
  951. else
  952. a_jmp_cond(list,OC_AE,hl);
  953. end;
  954. LOC_FLAGS:
  955. begin
  956. hflags:=ovloc.resflags;
  957. inverse_flags(hflags);
  958. cg.a_jmp_flags(list,hflags,hl);
  959. end;
  960. else
  961. internalerror(200409281);
  962. end;
  963. a_call_name(list,'FPC_OVERFLOW',false);
  964. a_label(list,hl);
  965. end;
  966. { *********** entry/exit code and address loading ************ }
  967. procedure TCgSparc.g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);
  968. begin
  969. if nostackframe then
  970. exit;
  971. { Althogh the SPARC architecture require only word alignment, software
  972. convention and the operating system require every stack frame to be double word
  973. aligned }
  974. LocalSize:=align(LocalSize,8);
  975. { Execute the SAVE instruction to get a new register window and create a new
  976. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  977. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  978. after execution of that instruction is the called function stack pointer}
  979. { constant can be 13 bit signed, since it's negative, size can be max. 4096 }
  980. if LocalSize>4096 then
  981. begin
  982. a_load_const_reg(list,OS_ADDR,-LocalSize,NR_G1);
  983. g1_used:=true;
  984. list.concat(Taicpu.Op_reg_reg_reg(A_SAVE,NR_STACK_POINTER_REG,NR_G1,NR_STACK_POINTER_REG));
  985. g1_used:=false;
  986. end
  987. else
  988. list.concat(Taicpu.Op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,-LocalSize,NR_STACK_POINTER_REG));
  989. end;
  990. procedure TCgSparc.g_maybe_got_init(list : TAsmList);
  991. var
  992. ref : treference;
  993. hl : tasmlabel;
  994. begin
  995. if (cs_create_pic in current_settings.moduleswitches) and
  996. ((pi_needs_got in current_procinfo.flags) or
  997. (current_procinfo.procdef.proctypeoption=potype_unitfinalize)) then
  998. begin
  999. current_asmdata.getjumplabel(hl);
  1000. list.concat(taicpu.op_sym(A_CALL,hl));
  1001. { ABI recommends the following sequence:
  1002. 1: call 2f
  1003. sethi %hi(_GLOBAL_OFFSET_TABLE_+(.-1b)), %l7
  1004. 2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_+(.-1b)), %l7
  1005. add %l7, %o7, %l7 }
  1006. reference_reset_symbol(ref,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),4,sizeof(pint));
  1007. ref.refaddr:=addr_high;
  1008. list.concat(taicpu.op_ref_reg(A_SETHI,ref,NR_L7));
  1009. cg.a_label(list,hl);
  1010. ref.refaddr:=addr_low;
  1011. ref.offset:=8;
  1012. list.concat(Taicpu.Op_reg_ref_reg(A_OR,NR_L7,ref,NR_L7));
  1013. list.concat(taicpu.op_reg_reg_reg(A_ADD,NR_L7,NR_O7,NR_L7));
  1014. { allocate NR_L7, so reg.allocator does not see it as available }
  1015. list.concat(tai_regalloc.alloc(NR_L7,nil));
  1016. end;
  1017. end;
  1018. procedure TCgSparc.g_restore_registers(list:TAsmList);
  1019. begin
  1020. { The sparc port uses the sparc standard calling convetions so this function has no used }
  1021. end;
  1022. procedure TCgSparc.g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean);
  1023. var
  1024. hr : treference;
  1025. begin
  1026. if paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef) then
  1027. begin
  1028. reference_reset(hr,sizeof(pint));
  1029. hr.offset:=12;
  1030. hr.refaddr:=addr_full;
  1031. if nostackframe then
  1032. begin
  1033. hr.base:=NR_O7;
  1034. list.concat(taicpu.op_ref_reg(A_JMPL,hr,NR_G0));
  1035. list.concat(Taicpu.op_none(A_NOP))
  1036. end
  1037. else
  1038. begin
  1039. { We use trivial restore in the delay slot of the JMPL instruction, as we
  1040. already set result onto %i0 }
  1041. hr.base:=NR_I7;
  1042. list.concat(taicpu.op_ref_reg(A_JMPL,hr,NR_G0));
  1043. list.concat(Taicpu.op_none(A_RESTORE));
  1044. end;
  1045. end
  1046. else
  1047. begin
  1048. if nostackframe then
  1049. begin
  1050. { Here we need to use RETL instead of RET so it uses %o7 }
  1051. list.concat(Taicpu.op_none(A_RETL));
  1052. list.concat(Taicpu.op_none(A_NOP))
  1053. end
  1054. else
  1055. begin
  1056. { We use trivial restore in the delay slot of the JMPL instruction, as we
  1057. already set result onto %i0 }
  1058. list.concat(Taicpu.op_none(A_RET));
  1059. list.concat(Taicpu.op_none(A_RESTORE));
  1060. end;
  1061. end;
  1062. end;
  1063. procedure TCgSparc.g_save_registers(list : TAsmList);
  1064. begin
  1065. { The sparc port uses the sparc standard calling convetions so this function has no used }
  1066. end;
  1067. { ************* concatcopy ************ }
  1068. procedure tcgsparc.g_concatcopy_move(list : TAsmList;const source,dest : treference;len : tcgint);
  1069. var
  1070. paraloc1,paraloc2,paraloc3 : TCGPara;
  1071. pd : tprocdef;
  1072. begin
  1073. pd:=search_system_proc('MOVE');
  1074. paraloc1.init;
  1075. paraloc2.init;
  1076. paraloc3.init;
  1077. paramanager.getintparaloc(pd,1,paraloc1);
  1078. paramanager.getintparaloc(pd,2,paraloc2);
  1079. paramanager.getintparaloc(pd,3,paraloc3);
  1080. a_load_const_cgpara(list,OS_SINT,len,paraloc3);
  1081. a_loadaddr_ref_cgpara(list,dest,paraloc2);
  1082. a_loadaddr_ref_cgpara(list,source,paraloc1);
  1083. paramanager.freecgpara(list,paraloc3);
  1084. paramanager.freecgpara(list,paraloc2);
  1085. paramanager.freecgpara(list,paraloc1);
  1086. alloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1087. alloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
  1088. a_call_name(list,'FPC_MOVE',false);
  1089. dealloccpuregisters(list,R_FPUREGISTER,paramanager.get_volatile_registers_fpu(pocall_default));
  1090. dealloccpuregisters(list,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  1091. paraloc3.done;
  1092. paraloc2.done;
  1093. paraloc1.done;
  1094. end;
  1095. procedure TCgSparc.g_concatcopy(list:TAsmList;const source,dest:treference;len:tcgint);
  1096. var
  1097. tmpreg1,
  1098. hreg,
  1099. countreg: TRegister;
  1100. src, dst: TReference;
  1101. lab: tasmlabel;
  1102. count, count2: aint;
  1103. function reference_is_reusable(const ref: treference): boolean;
  1104. begin
  1105. result:=(ref.base<>NR_NO) and (ref.index=NR_NO) and
  1106. (ref.symbol=nil) and
  1107. (ref.offset>=simm13lo) and (ref.offset+len<=simm13hi);
  1108. end;
  1109. begin
  1110. if len>high(longint) then
  1111. internalerror(2002072704);
  1112. { anybody wants to determine a good value here :)? }
  1113. if len>100 then
  1114. g_concatcopy_move(list,source,dest,len)
  1115. else
  1116. begin
  1117. count:=len div 4;
  1118. if (count<=4) and reference_is_reusable(source) then
  1119. src:=source
  1120. else
  1121. begin
  1122. reference_reset_base(src,getintregister(list,OS_ADDR),0,sizeof(aint));
  1123. a_loadaddr_ref_reg(list,source,src.base);
  1124. end;
  1125. if (count<=4) and reference_is_reusable(dest) then
  1126. dst:=dest
  1127. else
  1128. begin
  1129. reference_reset_base(dst,getintregister(list,OS_ADDR),0,sizeof(aint));
  1130. a_loadaddr_ref_reg(list,dest,dst.base);
  1131. end;
  1132. { generate a loop }
  1133. if count>4 then
  1134. begin
  1135. countreg:=GetIntRegister(list,OS_INT);
  1136. tmpreg1:=GetIntRegister(list,OS_INT);
  1137. a_load_const_reg(list,OS_INT,count,countreg);
  1138. current_asmdata.getjumplabel(lab);
  1139. a_label(list, lab);
  1140. list.concat(taicpu.op_ref_reg(A_LD,src,tmpreg1));
  1141. list.concat(taicpu.op_reg_ref(A_ST,tmpreg1,dst));
  1142. list.concat(taicpu.op_reg_const_reg(A_ADD,src.base,4,src.base));
  1143. list.concat(taicpu.op_reg_const_reg(A_ADD,dst.base,4,dst.base));
  1144. list.concat(taicpu.op_reg_const_reg(A_SUBcc,countreg,1,countreg));
  1145. a_jmp_cond(list,OC_NE,lab);
  1146. len := len mod 4;
  1147. end;
  1148. { unrolled loop }
  1149. count:=len div 4;
  1150. if count>0 then
  1151. begin
  1152. tmpreg1:=GetIntRegister(list,OS_INT);
  1153. for count2 := 1 to count do
  1154. begin
  1155. list.concat(taicpu.op_ref_reg(A_LD,src,tmpreg1));
  1156. list.concat(taicpu.op_reg_ref(A_ST,tmpreg1,dst));
  1157. inc(src.offset,4);
  1158. inc(dst.offset,4);
  1159. end;
  1160. len := len mod 4;
  1161. end;
  1162. if (len and 4) <> 0 then
  1163. begin
  1164. hreg:=GetIntRegister(list,OS_INT);
  1165. a_load_ref_reg(list,OS_32,OS_32,src,hreg);
  1166. a_load_reg_ref(list,OS_32,OS_32,hreg,dst);
  1167. inc(src.offset,4);
  1168. inc(dst.offset,4);
  1169. end;
  1170. { copy the leftovers }
  1171. if (len and 2) <> 0 then
  1172. begin
  1173. hreg:=GetIntRegister(list,OS_INT);
  1174. a_load_ref_reg(list,OS_16,OS_16,src,hreg);
  1175. a_load_reg_ref(list,OS_16,OS_16,hreg,dst);
  1176. inc(src.offset,2);
  1177. inc(dst.offset,2);
  1178. end;
  1179. if (len and 1) <> 0 then
  1180. begin
  1181. hreg:=GetIntRegister(list,OS_INT);
  1182. a_load_ref_reg(list,OS_8,OS_8,src,hreg);
  1183. a_load_reg_ref(list,OS_8,OS_8,hreg,dst);
  1184. end;
  1185. end;
  1186. end;
  1187. procedure tcgsparc.g_concatcopy_unaligned(list : TAsmList;const source,dest : treference;len : tcgint);
  1188. var
  1189. src, dst: TReference;
  1190. tmpreg1,
  1191. countreg: TRegister;
  1192. i : aint;
  1193. lab: tasmlabel;
  1194. begin
  1195. if len>31 then
  1196. g_concatcopy_move(list,source,dest,len)
  1197. else
  1198. begin
  1199. reference_reset(src,source.alignment);
  1200. reference_reset(dst,dest.alignment);
  1201. { load the address of source into src.base }
  1202. src.base:=GetAddressRegister(list);
  1203. a_loadaddr_ref_reg(list,source,src.base);
  1204. { load the address of dest into dst.base }
  1205. dst.base:=GetAddressRegister(list);
  1206. a_loadaddr_ref_reg(list,dest,dst.base);
  1207. { generate a loop }
  1208. if len>4 then
  1209. begin
  1210. countreg:=GetIntRegister(list,OS_INT);
  1211. tmpreg1:=GetIntRegister(list,OS_INT);
  1212. a_load_const_reg(list,OS_INT,len,countreg);
  1213. current_asmdata.getjumplabel(lab);
  1214. a_label(list, lab);
  1215. list.concat(taicpu.op_ref_reg(A_LDUB,src,tmpreg1));
  1216. list.concat(taicpu.op_reg_ref(A_STB,tmpreg1,dst));
  1217. list.concat(taicpu.op_reg_const_reg(A_ADD,src.base,1,src.base));
  1218. list.concat(taicpu.op_reg_const_reg(A_ADD,dst.base,1,dst.base));
  1219. list.concat(taicpu.op_reg_const_reg(A_SUBcc,countreg,1,countreg));
  1220. a_jmp_cond(list,OC_NE,lab);
  1221. end
  1222. else
  1223. begin
  1224. { unrolled loop }
  1225. tmpreg1:=GetIntRegister(list,OS_INT);
  1226. for i:=1 to len do
  1227. begin
  1228. list.concat(taicpu.op_ref_reg(A_LDUB,src,tmpreg1));
  1229. list.concat(taicpu.op_reg_ref(A_STB,tmpreg1,dst));
  1230. inc(src.offset);
  1231. inc(dst.offset);
  1232. end;
  1233. end;
  1234. end;
  1235. end;
  1236. procedure tcgsparc.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  1237. var
  1238. make_global : boolean;
  1239. href : treference;
  1240. begin
  1241. if not(procdef.proctypeoption in [potype_function,potype_procedure]) then
  1242. Internalerror(200006137);
  1243. if not assigned(procdef.struct) or
  1244. (procdef.procoptions*[po_classmethod, po_staticmethod,
  1245. po_methodpointer, po_interrupt, po_iocheck]<>[]) then
  1246. Internalerror(200006138);
  1247. if procdef.owner.symtabletype<>ObjectSymtable then
  1248. Internalerror(200109191);
  1249. make_global:=false;
  1250. if (not current_module.is_unit) or create_smartlink or
  1251. (procdef.owner.defowner.owner.symtabletype=globalsymtable) then
  1252. make_global:=true;
  1253. if make_global then
  1254. List.concat(Tai_symbol.Createname_global(labelname,AT_FUNCTION,0))
  1255. else
  1256. List.concat(Tai_symbol.Createname(labelname,AT_FUNCTION,0));
  1257. { set param1 interface to self }
  1258. g_adjust_self_value(list,procdef,ioffset);
  1259. if (po_virtualmethod in procdef.procoptions) and
  1260. not is_objectpascal_helper(procdef.struct) then
  1261. begin
  1262. if (procdef.extnumber=$ffff) then
  1263. Internalerror(200006139);
  1264. { mov 0(%rdi),%rax ; load vmt}
  1265. reference_reset_base(href,NR_O0,0,sizeof(pint));
  1266. cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,NR_G1);
  1267. g1_used:=true;
  1268. { jmp *vmtoffs(%eax) ; method offs }
  1269. reference_reset_base(href,NR_G1,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
  1270. list.concat(taicpu.op_ref_reg(A_LD,href,NR_G1));
  1271. list.concat(taicpu.op_reg(A_JMP,NR_G1));
  1272. g1_used:=false;
  1273. { Delay slot }
  1274. list.Concat(TAiCpu.Op_none(A_NOP));
  1275. end
  1276. else
  1277. begin
  1278. { Emit a branch, which is PIC-safe, but limited to 8 MByte range on SPARC.
  1279. Since interface wrappers are always located in the same unit with
  1280. their target methods, this limit applies (roughly) to code size of single
  1281. unit, not to entire program. It looks like a reasonable tradeoff.
  1282. If distance limit is ever exceeded, consider changing high-level compiler
  1283. logic to emit wrappers near target methods, not at the end of unit. }
  1284. a_jmp_name(list,procdef.mangledname);
  1285. end;
  1286. List.concat(Tai_symbol_end.Createname(labelname));
  1287. end;
  1288. procedure tcgsparc.g_external_wrapper(list : TAsmList; procdef: tprocdef; const externalname: string);
  1289. begin
  1290. { CALL overwrites %o7 with its own address, we use delay slot to restore it. }
  1291. list.concat(taicpu.op_reg_reg(A_MOV,NR_O7,NR_G1));
  1292. list.concat(taicpu.op_sym(A_CALL,current_asmdata.RefAsmSymbol(externalname)));
  1293. list.concat(taicpu.op_reg_reg(A_MOV,NR_G1,NR_O7));
  1294. end;
  1295. procedure tcgsparc.g_stackpointer_alloc(list : TAsmList;localsize : longint);
  1296. begin
  1297. Comment(V_Error,'tcgsparc.g_stackpointer_alloc method not implemented');
  1298. end;
  1299. procedure tcgsparc.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; size: TCGSize; src, dst: TRegister);
  1300. begin
  1301. Comment(V_Error,'tcgsparc.a_bit_scan_reg_reg method not implemented');
  1302. end;
  1303. {****************************************************************************
  1304. TCG64Sparc
  1305. ****************************************************************************}
  1306. procedure tcg64sparc.a_load64_reg_ref(list : TAsmList;reg : tregister64;const ref : treference);
  1307. var
  1308. tmpref: treference;
  1309. begin
  1310. { Override this function to prevent loading the reference twice }
  1311. tmpref:=ref;
  1312. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reghi,tmpref);
  1313. inc(tmpref.offset,4);
  1314. cg.a_load_reg_ref(list,OS_32,OS_32,reg.reglo,tmpref);
  1315. end;
  1316. procedure tcg64sparc.a_load64_ref_reg(list : TAsmList;const ref : treference;reg : tregister64);
  1317. var
  1318. tmpref: treference;
  1319. begin
  1320. { Override this function to prevent loading the reference twice }
  1321. tmpref:=ref;
  1322. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reghi);
  1323. inc(tmpref.offset,4);
  1324. cg.a_load_ref_reg(list,OS_32,OS_32,tmpref,reg.reglo);
  1325. end;
  1326. procedure tcg64sparc.a_load64_ref_cgpara(list : TAsmList;const r : treference;const paraloc : tcgpara);
  1327. var
  1328. hreg64 : tregister64;
  1329. begin
  1330. { Override this function to prevent loading the reference twice.
  1331. Use here some extra registers, but those are optimized away by the RA }
  1332. hreg64.reglo:=cg.GetIntRegister(list,OS_32);
  1333. hreg64.reghi:=cg.GetIntRegister(list,OS_32);
  1334. a_load64_ref_reg(list,r,hreg64);
  1335. a_load64_reg_cgpara(list,hreg64,paraloc);
  1336. end;
  1337. procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp;checkoverflow : boolean);
  1338. begin
  1339. case op of
  1340. OP_ADD :
  1341. begin
  1342. op1:=A_ADDCC;
  1343. if checkoverflow then
  1344. op2:=A_ADDXCC
  1345. else
  1346. op2:=A_ADDX;
  1347. end;
  1348. OP_SUB :
  1349. begin
  1350. op1:=A_SUBCC;
  1351. if checkoverflow then
  1352. op2:=A_SUBXCC
  1353. else
  1354. op2:=A_SUBX;
  1355. end;
  1356. OP_XOR :
  1357. begin
  1358. op1:=A_XOR;
  1359. op2:=A_XOR;
  1360. end;
  1361. OP_OR :
  1362. begin
  1363. op1:=A_OR;
  1364. op2:=A_OR;
  1365. end;
  1366. OP_AND :
  1367. begin
  1368. op1:=A_AND;
  1369. op2:=A_AND;
  1370. end;
  1371. else
  1372. internalerror(200203241);
  1373. end;
  1374. end;
  1375. procedure TCg64Sparc.a_op64_reg_reg(list:TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst:TRegister64);
  1376. var
  1377. op1,op2 : TAsmOp;
  1378. begin
  1379. case op of
  1380. OP_NEG :
  1381. begin
  1382. { Use the simple code: y=0-z }
  1383. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
  1384. list.concat(taicpu.op_reg_reg_reg(A_SUBX,NR_G0,regsrc.reghi,regdst.reghi));
  1385. exit;
  1386. end;
  1387. OP_NOT :
  1388. begin
  1389. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
  1390. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
  1391. exit;
  1392. end;
  1393. end;
  1394. get_64bit_ops(op,op1,op2,false);
  1395. list.concat(taicpu.op_reg_reg_reg(op1,regdst.reglo,regsrc.reglo,regdst.reglo));
  1396. list.concat(taicpu.op_reg_reg_reg(op2,regdst.reghi,regsrc.reghi,regdst.reghi));
  1397. end;
  1398. procedure TCg64Sparc.a_op64_const_reg(list:TAsmList;op:TOpCG;size : tcgsize;value:int64;regdst:TRegister64);
  1399. var
  1400. op1,op2:TAsmOp;
  1401. begin
  1402. case op of
  1403. OP_NEG,
  1404. OP_NOT :
  1405. internalerror(200306017);
  1406. end;
  1407. get_64bit_ops(op,op1,op2,false);
  1408. tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reglo,tcgint(lo(value)),regdst.reglo);
  1409. tcgsparc(cg).handle_reg_const_reg(list,op2,regdst.reghi,tcgint(hi(value)),regdst.reghi);
  1410. end;
  1411. procedure tcg64sparc.a_op64_const_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;value : int64; regsrc,regdst : tregister64);
  1412. var
  1413. l : tlocation;
  1414. begin
  1415. a_op64_const_reg_reg_checkoverflow(list,op,size,value,regsrc,regdst,false,l);
  1416. end;
  1417. procedure tcg64sparc.a_op64_reg_reg_reg(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64);
  1418. var
  1419. l : tlocation;
  1420. begin
  1421. a_op64_reg_reg_reg_checkoverflow(list,op,size,regsrc1,regsrc2,regdst,false,l);
  1422. end;
  1423. procedure tcg64sparc.a_op64_const_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;value : int64;regsrc,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  1424. var
  1425. op1,op2:TAsmOp;
  1426. begin
  1427. case op of
  1428. OP_NEG,
  1429. OP_NOT :
  1430. internalerror(200306017);
  1431. end;
  1432. get_64bit_ops(op,op1,op2,setflags);
  1433. tcgsparc(cg).handle_reg_const_reg(list,op1,regsrc.reglo,tcgint(lo(value)),regdst.reglo);
  1434. tcgsparc(cg).handle_reg_const_reg(list,op2,regsrc.reghi,tcgint(hi(value)),regdst.reghi);
  1435. end;
  1436. procedure tcg64sparc.a_op64_reg_reg_reg_checkoverflow(list: TAsmList;op:TOpCG;size : tcgsize;regsrc1,regsrc2,regdst : tregister64;setflags : boolean;var ovloc : tlocation);
  1437. var
  1438. op1,op2:TAsmOp;
  1439. begin
  1440. case op of
  1441. OP_NEG,
  1442. OP_NOT :
  1443. internalerror(200306017);
  1444. end;
  1445. get_64bit_ops(op,op1,op2,setflags);
  1446. list.concat(taicpu.op_reg_reg_reg(op1,regsrc2.reglo,regsrc1.reglo,regdst.reglo));
  1447. list.concat(taicpu.op_reg_reg_reg(op2,regsrc2.reghi,regsrc1.reghi,regdst.reghi));
  1448. end;
  1449. procedure create_codegen;
  1450. begin
  1451. cg:=TCgSparc.Create;
  1452. if target_info.system=system_sparc_linux then
  1453. TCgSparc(cg).use_unlimited_pic_mode:=true
  1454. else
  1455. TCgSparc(cg).use_unlimited_pic_mode:=false;
  1456. cg64:=TCg64Sparc.Create;
  1457. end;
  1458. end.