cgcpu.pas 48 KB

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