cgcpu.pas 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394
  1. {******************************************************************************
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  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. UNIT cgcpu;
  17. {This unit implements the code generator for the SPARC architecture}
  18. {$INCLUDE fpcdefs.inc}
  19. INTERFACE
  20. USES
  21. cginfo,cgbase,cgobj,cg64f32,
  22. aasmbase,aasmtai,aasmcpu,
  23. cpubase,cpuinfo,cpupara,
  24. node,symconst;
  25. TYPE
  26. tcgSPARC=CLASS(tcg)
  27. {This method is used to pass a parameter, which is located in a register, to a
  28. routine. It should give the parameter to the routine, as required by the
  29. specific processor ABI. It is overriden for each CPU target.
  30. Size : is the size of the operand in the register
  31. r : is the register source of the operand
  32. LocPara : is the location where the parameter will be stored}
  33. procedure a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;const LocPara:TParaLocation);override;
  34. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);override;
  35. procedure a_param_ref(list:TAasmOutput;sz:tcgsize;CONST r:TReference;CONST LocPara:TParaLocation);override;
  36. procedure a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);override;
  37. procedure a_call_name(list:TAasmOutput;CONST s:string);override;
  38. procedure a_call_ref(list:TAasmOutput;CONST ref:TReference);override;
  39. procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override;
  40. {Branch Instruction}
  41. procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
  42. {General purpose instyructions}
  43. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override;
  44. procedure a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);override;
  45. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  46. procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);override;
  47. procedure a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);override;
  48. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  49. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  50. { move instructions }
  51. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  52. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);override;
  53. procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  54. procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  55. procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override;
  56. procedure a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);override;
  57. { fpu move instructions }
  58. procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  59. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  60. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  61. { vector register move instructions }
  62. procedure a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  63. procedure a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);override;
  64. procedure a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);override;
  65. procedure a_parammm_reg(list:TAasmOutput;reg:tregister);override;
  66. { comparison operations }
  67. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  68. procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;l:tasmlabel);override;
  69. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  70. procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);override;
  71. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  72. procedure a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);override;
  73. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);override;
  74. procedure g_overflowCheck(List:TAasmOutput;const p:TNode);override;
  75. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  76. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  77. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  78. procedure g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  79. class function reg_cgsize(CONST reg:tregister):tcgsize;override;
  80. PRIVATE
  81. function IsSimpleRef(const ref:treference):boolean;
  82. procedure sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  83. procedure floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  84. procedure floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  85. procedure floatloadops(t:tcgsize;var op:tasmop;var s:topsize);
  86. procedure floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  87. END;
  88. TCg64fSPARC=class(tcg64f32)
  89. procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);override;
  90. procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override;
  91. procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override;
  92. procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);override;
  93. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  94. END;
  95. CONST
  96. TOpCG2AsmOp:ARRAY[topcg]OF TAsmOp=(A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_UMUL, A_SMUL, A_NEG,A_NOT,A_OR,A_not,A_not,A_not,A_SUB,A_XOR);
  97. TOpCmp2AsmCond:ARRAY[topcmp]OF TAsmCond=(C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
  98. TCGSize2OpSize:ARRAY[tcgsize]OF TOpSize=(S_NO,S_B,S_W,S_SW,S_SW,S_B,S_W,S_SW,S_SW,S_FS,S_FD,S_FQ,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  99. IMPLEMENTATION
  100. USES
  101. globtype,globals,verbose,systems,cutils,
  102. symdef,symsym,defutil,paramgr,
  103. rgobj,tgobj,rgcpu,cpupi;
  104. { we implement the following routines because otherwise we can't }
  105. { instantiate the class since it's abstract }
  106. procedure tcgSPARC.a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;CONST LocPara:TParaLocation);
  107. BEGIN
  108. IF(Size<>OS_32)AND(Size<>OS_S32)
  109. THEN
  110. InternalError(2002032212);
  111. with list,LocPara do
  112. case Loc of
  113. LOC_REGISTER:
  114. if r<>Register
  115. then
  116. Concat(taicpu.op_Reg_Reg_Reg(A_OR,r,R_G0,Register));
  117. else
  118. InternalError(2002101002);
  119. end;
  120. end;
  121. procedure tcgSPARC.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);
  122. BEGIN
  123. with List do
  124. case Size of
  125. OS_32,OS_S32:
  126. Concat(taicpu.op_const(A_LD,a));
  127. OS_64,OS_S64:
  128. Concat(taicpu.op_const(A_LDD,a));
  129. else
  130. InternalError(2002032213);
  131. end;
  132. END;
  133. procedure tcgSPARC.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation);
  134. var
  135. ref: treference;
  136. tmpreg:TRegister;
  137. begin
  138. with LocPara do
  139. case locpara.loc of
  140. LOC_REGISTER,LOC_CREGISTER:
  141. a_load_ref_reg(list,sz,r,Register);
  142. LOC_REFERENCE:
  143. begin
  144. {Code conventions need the parameters being allocated in %o6+92. See
  145. comment on g_stack_frame}
  146. if locpara.sp_fixup<92
  147. then
  148. InternalError(2002081104);
  149. reference_reset(ref);
  150. ref.base:=locpara.reference.index;
  151. ref.offset:=locpara.reference.offset;
  152. tmpreg := get_scratch_reg_int(list);
  153. a_load_ref_reg(list,sz,r,tmpreg);
  154. a_load_reg_ref(list,sz,tmpreg,ref);
  155. free_scratch_reg(list,tmpreg);
  156. end;
  157. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  158. case sz of
  159. OS_32:
  160. a_loadfpu_ref_reg(list,OS_F32,r,locpara.register);
  161. OS_64:
  162. a_loadfpu_ref_reg(list,OS_F64,r,locpara.register);
  163. else
  164. internalerror(2002072801);
  165. end;
  166. else
  167. internalerror(2002081103);
  168. end;
  169. end;
  170. procedure tcgSPARC.a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);
  171. VAR
  172. tmpreg:TRegister;
  173. BEGIN
  174. IF r.segment<>R_NO
  175. THEN
  176. CGMessage(cg_e_cant_use_far_pointer_there);
  177. IF(r.base=R_NO)AND(r.index=R_NO)
  178. THEN
  179. list.concat(Taicpu.Op_sym_ofs(A_LD,S_SW,r.symbol,r.offset))
  180. ELSE IF(r.base=R_NO)AND(r.index<>R_NO)AND
  181. (r.offset=0)AND(r.scalefactor=0)AND(r.symbol=nil)
  182. THEN
  183. list.concat(Taicpu.Op_reg(A_LD,r.index))
  184. ELSE IF(r.base<>R_NO)AND(r.index=R_NO)AND
  185. (r.offset=0)AND(r.symbol=nil)
  186. THEN
  187. list.concat(Taicpu.Op_reg(A_LD,r.base))
  188. ELSE
  189. BEGIN
  190. tmpreg:=get_scratch_reg_address(list);
  191. a_loadaddr_ref_reg(list,r,tmpreg);
  192. list.concat(taicpu.op_reg(A_LD,tmpreg));
  193. free_scratch_reg(list,tmpreg);
  194. END;
  195. END;
  196. procedure tcgSPARC.a_call_name(list:TAasmOutput;CONST s:string);
  197. BEGIN
  198. WITH List,objectlibrary DO
  199. BEGIN
  200. concat(taicpu.op_sym(A_CALL,S_SW,newasmsymbol(s)));
  201. concat(taicpu.op_none(A_NOP));
  202. END;
  203. END;
  204. procedure tcgSPARC.a_call_ref(list:TAasmOutput;CONST ref:TReference);
  205. begin
  206. list.concat(taicpu.op_ref(A_CALL,ref));
  207. list.concat(taicpu.op_none(A_NOP));
  208. end;
  209. procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister);
  210. begin
  211. list.concat(taicpu.op_reg(A_JMPL,reg));
  212. if target_info.system=system_sparc_linux
  213. then
  214. list.concat(taicpu.op_none(A_NOP));
  215. procinfo.flags:=procinfo.flags or pi_do_call;
  216. end;
  217. {********************** branch instructions ********************}
  218. procedure TCgSPARC.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
  219. begin
  220. List.Concat(TAiCpu.op_sym(A_BA,S_NO,objectlibrary.newasmsymbol(l.name)));
  221. end;
  222. {********************** load instructions ********************}
  223. procedure tcgSPARC.a_load_const_reg(list:TAasmOutput;size:TCGSize;a:aword;reg:TRegister);
  224. BEGIN
  225. WITH List DO
  226. IF a<>0
  227. THEN{R_G0 is usually set to zero, so we use it}
  228. Concat(taicpu.op_reg_const_reg(A_OR,R_G0,a,reg))
  229. ELSE{The is no A_MOV in sparc, that's why we use A_OR with help of R_G0}
  230. Concat(taicpu.op_reg_reg_reg(A_OR,R_G0,R_G0,reg));
  231. END;
  232. procedure tcgSPARC.a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);
  233. BEGIN
  234. WITH List DO
  235. IF a=0
  236. THEN
  237. Concat(taicpu.op_reg_ref(A_ST,R_G0,ref))
  238. ELSE
  239. BEGIN
  240. a_load_const_reg(list,size,a,R_G1);
  241. case size of
  242. OS_32,OS_S32:
  243. Concat(taicpu.op_reg_ref(A_ST,R_G1,ref));
  244. OS_64,OS_S64:
  245. Concat(taicpu.op_reg_ref(A_STD,R_G1,ref));
  246. else
  247. InternalError(2002102100);
  248. end;
  249. END;
  250. END;
  251. procedure tcgSPARC.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;CONST ref:TReference);
  252. BEGIN
  253. list.concat(taicpu.op_reg_ref(A_ST,reg,ref));
  254. END;
  255. procedure tcgSPARC.a_load_ref_reg(list:TAasmOutput;size:TCgSize;const ref:TReference;reg:tregister);
  256. var
  257. op:tasmop;
  258. s:topsize;
  259. begin
  260. case size of
  261. { signed integer registers }
  262. OS_S8:
  263. Op:=A_LDSB;{Load Signed Byte}
  264. OS_S16:
  265. Op:=A_LDSH;{Load Signed Halfword}
  266. OS_S32:
  267. Op:=A_LD;{Load Word}
  268. OS_S64:
  269. Op:=A_LDD;{Load Double Word}
  270. { unsigned integer registers }
  271. //A_LDSTUB;{Load-Store Unsigned Byte}
  272. OS_8:
  273. Op:=A_LDUB;{Load Unsigned Bye}
  274. OS_16:
  275. Op:=A_LDUH;{Load Unsigned Halfword}
  276. OS_32:
  277. Op:=A_LD;{Load Word}
  278. OS_64:
  279. Op:=A_LDD;{Load Double Word}
  280. { floating-point real registers }
  281. OS_F32:
  282. Op:=A_LDF;{Load Floating-point word}
  283. //A_LDFSR
  284. OS_F64:
  285. Op:=A_LDDF;{Load Double Floating-point word}
  286. //A_LDC;{Load Coprocessor}
  287. //A_LDCSR;
  288. //A_LDDC;{Load Double Coprocessor}
  289. else
  290. InternalError(2002122100);
  291. end;
  292. with list do
  293. concat(taicpu.op_ref_reg(op,ref,reg));
  294. end;
  295. procedure tcgSPARC.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  296. var
  297. op:tasmop;
  298. s:topsize;
  299. begin
  300. if(reg1<>reg2)or
  301. (tcgsize2size[tosize]<tcgsize2size[fromsize])or
  302. ((tcgsize2size[tosize] = tcgsize2size[fromsize])and
  303. (tosize <> fromsize)and
  304. not(fromsize in [OS_32,OS_S32]))
  305. then
  306. with list do
  307. case fromsize of
  308. OS_8:
  309. InternalError(2002100800);{concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,reg2,reg1,0,31-8+1,31));}
  310. OS_S8:
  311. InternalError(2002100801);{concat(taicpu.op_reg_reg(A_EXTSB,reg2,reg1));}
  312. OS_16:
  313. InternalError(2002100802);{concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,reg2,reg1,0,31-16+1,31));}
  314. OS_S16:
  315. InternalError(2002100803);{concat(taicpu.op_reg_reg(A_EXTSH,reg2,reg1));}
  316. OS_32,OS_S32:
  317. concat(taicpu.op_reg_reg_reg(A_OR,R_G0,reg1,reg2));
  318. else internalerror(2002090901);
  319. end;
  320. end;
  321. { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
  322. { R_ST means "the current value at the top of the fpu stack" (JM) }
  323. procedure tcgSPARC.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  324. begin
  325. { if NOT (reg1 IN [R_F0..R_F31]) then
  326. begin
  327. list.concat(taicpu.op_reg(A_NONE,S_NO,
  328. trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset)));
  329. inc(trgcpu(rg).fpuvaroffset);
  330. end;
  331. if NOT (reg2 IN [R_F0..R_F31]) then
  332. begin
  333. list.concat(taicpu.op_reg(A_JMPL,S_NO,
  334. trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset)));
  335. dec(trgcpu(rg).fpuvaroffset);
  336. end;}
  337. end;
  338. procedure tcgSPARC.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);
  339. begin
  340. floatload(list,size,ref);
  341. { if (reg <> R_ST) then
  342. a_loadfpu_reg_reg(list,R_ST,reg);}
  343. end;
  344. procedure tcgSPARC.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);
  345. begin
  346. { if reg <> R_ST then
  347. a_loadfpu_reg_reg(list,reg,R_ST);}
  348. floatstore(list,size,ref);
  349. end;
  350. procedure tcgSPARC.a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  351. begin
  352. // list.concat(taicpu.op_reg_reg(A_NONEQ,S_NO,reg1,reg2));
  353. end;
  354. procedure tcgSPARC.a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);
  355. begin
  356. // list.concat(taicpu.op_ref_reg(A_NONEQ,S_NO,ref,reg));
  357. end;
  358. procedure tcgSPARC.a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);
  359. begin
  360. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,ref));
  361. end;
  362. procedure tcgSPARC.a_parammm_reg(list:TAasmOutput;reg:tregister);
  363. VAR
  364. href:TReference;
  365. BEGIN
  366. // list.concat(taicpu.op_const_reg(A_SUB,S_SW,8,R_RSP));
  367. // reference_reset_base(href,R_ESP,0);
  368. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,href));
  369. END;
  370. procedure tcgSPARC.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);
  371. var
  372. opcode:tasmop;
  373. power:LongInt;
  374. begin
  375. (* Case Op of
  376. OP_DIV, OP_IDIV:
  377. Begin
  378. if ispowerof2(a,power) then
  379. begin
  380. case op of
  381. OP_DIV:
  382. opcode := A_SHR;
  383. OP_IDIV:
  384. opcode := A_SAR;
  385. end;
  386. list.concat(taicpu.op_const_reg(opcode,S_SW,power,
  387. reg));
  388. exit;
  389. end;
  390. { the rest should be handled specifically in the code }
  391. { generator because of the silly register usage restraints }
  392. internalerror(200109224);
  393. End;
  394. OP_MUL,OP_IMUL:
  395. begin
  396. if not(cs_check_overflow in aktlocalswitches) and
  397. ispowerof2(a,power) then
  398. begin
  399. list.concat(taicpu.op_const_reg(A_SHL,S_SW,power,
  400. reg));
  401. exit;
  402. end;
  403. if op = OP_IMUL then
  404. list.concat(taicpu.op_const_reg(A_IMUL,S_SW,
  405. a,reg))
  406. else
  407. { OP_MUL should be handled specifically in the code }
  408. { generator because of the silly register usage restraints }
  409. internalerror(200109225);
  410. end;
  411. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  412. if not(cs_check_overflow in aktlocalswitches) and
  413. (a = 1) and
  414. (op in [OP_ADD,OP_SUB]) then
  415. if op = OP_ADD then
  416. list.concat(taicpu.op_reg(A_INC,S_SW,reg))
  417. else
  418. list.concat(taicpu.op_reg(A_DEC,S_SW,reg))
  419. else if (a = 0) then
  420. if (op <> OP_AND) then
  421. exit
  422. else
  423. list.concat(taicpu.op_const_reg(A_NONE,S_SW,0,reg))
  424. else if (a = high(aword)) and
  425. (op in [OP_AND,OP_OR,OP_XOR]) then
  426. begin
  427. case op of
  428. OP_AND:
  429. exit;
  430. OP_OR:
  431. list.concat(taicpu.op_const_reg(A_NONE,S_SW,high(aword),reg));
  432. OP_XOR:
  433. list.concat(taicpu.op_reg(A_NOT,S_SW,reg));
  434. end
  435. end
  436. else
  437. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],S_SW,
  438. a,reg));
  439. OP_SHL,OP_SHR,OP_SAR:
  440. begin
  441. if (a and 31) <> 0 Then
  442. list.concat(taicpu.op_const_reg(
  443. TOpCG2AsmOp[op],S_SW,a and 31,reg));
  444. if (a shr 5) <> 0 Then
  445. internalerror(68991);
  446. end
  447. else internalerror(68992);
  448. end;*)
  449. end;
  450. procedure tcgSPARC.a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);
  451. var
  452. opcode:tasmop;
  453. power:LongInt;
  454. begin
  455. (* Case Op of
  456. OP_DIV, OP_IDIV:
  457. Begin
  458. if ispowerof2(a,power) then
  459. begin
  460. case op of
  461. OP_DIV:
  462. opcode := A_SHR;
  463. OP_IDIV:
  464. opcode := A_SAR;
  465. end;
  466. list.concat(taicpu.op_const_ref(opcode,
  467. TCgSize2OpSize[size],power,ref));
  468. exit;
  469. end;
  470. { the rest should be handled specifically in the code }
  471. { generator because of the silly register usage restraints }
  472. internalerror(200109231);
  473. End;
  474. OP_MUL,OP_IMUL:
  475. begin
  476. if not(cs_check_overflow in aktlocalswitches) and
  477. ispowerof2(a,power) then
  478. begin
  479. list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
  480. power,ref));
  481. exit;
  482. end;
  483. { can't multiply a memory location directly with a CONSTant }
  484. if op = OP_IMUL then
  485. inherited a_op_const_ref(list,op,size,a,ref)
  486. else
  487. { OP_MUL should be handled specifically in the code }
  488. { generator because of the silly register usage restraints }
  489. internalerror(200109232);
  490. end;
  491. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  492. if not(cs_check_overflow in aktlocalswitches) and
  493. (a = 1) and
  494. (op in [OP_ADD,OP_SUB]) then
  495. if op = OP_ADD then
  496. list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
  497. else
  498. list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
  499. else if (a = 0) then
  500. if (op <> OP_AND) then
  501. exit
  502. else
  503. a_load_const_ref(list,size,0,ref)
  504. else if (a = high(aword)) and
  505. (op in [OP_AND,OP_OR,OP_XOR]) then
  506. begin
  507. case op of
  508. OP_AND:
  509. exit;
  510. OP_OR:
  511. list.concat(taicpu.op_const_ref(A_NONE,TCgSize2OpSize[size],high(aword),ref));
  512. OP_XOR:
  513. list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref));
  514. end
  515. end
  516. else
  517. list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
  518. TCgSize2OpSize[size],a,ref));
  519. OP_SHL,OP_SHR,OP_SAR:
  520. begin
  521. if (a and 31) <> 0 Then
  522. list.concat(taicpu.op_const_ref(
  523. TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
  524. if (a shr 5) <> 0 Then
  525. internalerror(68991);
  526. end
  527. else internalerror(68992);
  528. end;*)
  529. end;
  530. procedure tcgSPARC.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  531. var
  532. regloadsize:tcgsize;
  533. dstsize:topsize;
  534. tmpreg:tregister;
  535. popecx:boolean;
  536. begin
  537. (* dstsize := S_Q{makeregsize(dst,size)};
  538. case op of
  539. OP_NEG,OP_NOT:
  540. begin
  541. if src <> R_NO then
  542. internalerror(200112291);
  543. list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
  544. end;
  545. OP_MUL,OP_DIV,OP_IDIV:
  546. { special stuff, needs separate handling inside code }
  547. { generator }
  548. internalerror(200109233);
  549. OP_SHR,OP_SHL,OP_SAR:
  550. begin
  551. tmpreg := R_NO;
  552. { we need cl to hold the shift count, so if the destination }
  553. { is ecx, save it to a temp for now }
  554. if dst in [R_ECX,R_CX,R_CL] then
  555. begin
  556. case S_SW of
  557. S_B:regloadsize := OS_8;
  558. S_W:regloadsize := OS_16;
  559. else regloadsize := OS_32;
  560. end;
  561. tmpreg := get_scratch_reg(list);
  562. a_load_reg_reg(list,regloadsize,OS_32,src,tmpreg);
  563. end;
  564. if not(src in [R_ECX,R_CX,R_CL]) then
  565. begin
  566. { is ecx still free (it's also free if it was allocated }
  567. { to dst, since we've moved dst somewhere else already) }
  568. if not((dst = R_ECX) or
  569. ((R_ECX in rg.unusedregsint) and
  570. { this will always be true, it's just here to }
  571. { allocate ecx }
  572. (rg.getexplicitregisterint(list,R_ECX) = R_ECX))) then
  573. begin
  574. list.concat(taicpu.op_reg(A_NONE,S_SW,R_ECX));
  575. popecx := true;
  576. end;
  577. a_load_reg_reg(list,OS_8,OS_8,(src),R_CL);
  578. end
  579. else
  580. src := R_CL;
  581. { do the shift }
  582. if tmpreg = R_NO then
  583. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  584. R_CL,dst))
  585. else
  586. begin
  587. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],S_SW,
  588. R_CL,tmpreg));
  589. { move result back to the destination }
  590. a_load_reg_reg(list,OS_32,OS_32,tmpreg,R_ECX);
  591. free_scratch_reg(list,tmpreg);
  592. end;
  593. if popecx then
  594. list.concat(taicpu.op_reg(A_POP,S_SW,R_ECX))
  595. else if not (dst in [R_ECX,R_CX,R_CL]) then
  596. rg.ungetregisterint(list,R_ECX);
  597. end;
  598. else
  599. begin
  600. if S_SW <> dstsize then
  601. internalerror(200109226);
  602. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  603. src,dst));
  604. end;
  605. end;*)
  606. end;
  607. procedure tcgSPARC.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);
  608. var
  609. opsize:topsize;
  610. begin
  611. (* case op of
  612. OP_NEG,OP_NOT,OP_IMUL:
  613. begin
  614. inherited a_op_ref_reg(list,op,size,ref,reg);
  615. end;
  616. OP_MUL,OP_DIV,OP_IDIV:
  617. { special stuff, needs separate handling inside code }
  618. { generator }
  619. internalerror(200109239);
  620. else
  621. begin
  622. opsize := S_Q{makeregsize(reg,size)};
  623. list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,ref,reg));
  624. end;
  625. end;*)
  626. end;
  627. procedure tcgSPARC.a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);
  628. var
  629. opsize:topsize;
  630. begin
  631. (* case op of
  632. OP_NEG,OP_NOT:
  633. begin
  634. if reg <> R_NO then
  635. internalerror(200109237);
  636. list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
  637. end;
  638. OP_IMUL:
  639. begin
  640. { this one needs a load/imul/store, which is the default }
  641. inherited a_op_ref_reg(list,op,size,ref,reg);
  642. end;
  643. OP_MUL,OP_DIV,OP_IDIV:
  644. { special stuff, needs separate handling inside code }
  645. { generator }
  646. internalerror(200109238);
  647. else
  648. begin
  649. opsize := tcgsize2opsize[size];
  650. list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref));
  651. end;
  652. end;*)
  653. end;
  654. procedure tcgSPARC.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;
  655. size:tcgsize;a:aword;src, dst:tregister);
  656. var
  657. tmpref:TReference;
  658. power:LongInt;
  659. opsize:topsize;
  660. begin
  661. opsize := S_SW;
  662. if (opsize <> S_SW) or
  663. not (size in [OS_32,OS_S32]) then
  664. begin
  665. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  666. exit;
  667. end;
  668. { if we get here, we have to do a 32 bit calculation, guaranteed }
  669. Case Op of
  670. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  671. OP_SAR:
  672. { can't do anything special for these }
  673. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  674. OP_IMUL:
  675. begin
  676. if not(cs_check_overflow in aktlocalswitches) and
  677. ispowerof2(a,power) then
  678. { can be done with a shift }
  679. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  680. list.concat(taicpu.op_reg_const_reg(A_SMUL,src,a,dst));
  681. end;
  682. OP_ADD, OP_SUB:
  683. if (a = 0) then
  684. a_load_reg_reg(list,size,size,src,dst)
  685. else
  686. begin
  687. reference_reset(tmpref);
  688. tmpref.base := src;
  689. tmpref.offset := LongInt(a);
  690. if op = OP_SUB then
  691. tmpref.offset := -tmpref.offset;
  692. list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst));
  693. end
  694. else internalerror(200112302);
  695. end;
  696. end;
  697. procedure tcgSPARC.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;
  698. size:tcgsize;src1, src2, dst:tregister);
  699. var
  700. tmpref:TReference;
  701. opsize:topsize;
  702. begin
  703. opsize := S_SW;
  704. if (opsize <> S_SW) or
  705. (S_SW <> S_SW) or
  706. not (size in [OS_32,OS_S32]) then
  707. begin
  708. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  709. exit;
  710. end;
  711. { if we get here, we have to do a 32 bit calculation, guaranteed }
  712. Case Op of
  713. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  714. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  715. { can't do anything special for these }
  716. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  717. OP_IMUL:
  718. list.concat(taicpu.op_reg_reg_reg(A_SMUL,src1,src2,dst));
  719. OP_ADD:
  720. begin
  721. reference_reset(tmpref);
  722. tmpref.base := src1;
  723. tmpref.index := src2;
  724. tmpref.scalefactor := 1;
  725. list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst));
  726. end
  727. else internalerror(200112303);
  728. end;
  729. end;
  730. {*************** compare instructructions ****************}
  731. procedure tcgSPARC.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;
  732. l:tasmlabel);
  733. begin
  734. if (a = 0) then
  735. list.concat(taicpu.op_reg_reg(A_CMP,reg,reg))
  736. else
  737. list.concat(taicpu.op_const_reg(A_CMP,a,reg));
  738. a_jmp_cond(list,cmp_op,l);
  739. end;
  740. procedure tcgSPARC.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel);
  741. begin
  742. with List do
  743. begin
  744. Concat(taicpu.op_const(A_LD,a));
  745. Concat(taicpu.op_ref(A_CMP,ref));
  746. end;
  747. a_jmp_cond(list,cmp_op,l);
  748. end;
  749. procedure tcgSPARC.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;
  750. reg1,reg2:tregister;l:tasmlabel);
  751. begin
  752. { if regsize(reg1) <> S_SW then
  753. internalerror(200109226);
  754. list.concat(taicpu.op_reg_reg(A_CMP,regsize(reg1),reg1,reg2));
  755. a_jmp_cond(list,cmp_op,l);}
  756. end;
  757. procedure tcgSPARC.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);
  758. var
  759. TempReg:TRegister;
  760. begin
  761. TempReg:=cg.get_scratch_reg_int(List);
  762. a_load_ref_reg(list,OS_32,Ref,TempReg);
  763. list.concat(taicpu.op_reg_reg(A_SUBcc,TempReg,Reg));
  764. a_jmp_cond(list,cmp_op,l);
  765. cg.free_scratch_reg(exprasmlist,TempReg);
  766. end;
  767. procedure tcgSPARC.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);
  768. var
  769. ai:taicpu;
  770. begin
  771. if cond=OC_None then
  772. ai := Taicpu.Op_sym(A_JMPL,S_NO,l)
  773. else
  774. begin
  775. ai:=Taicpu.Op_sym(A_JMPL,S_NO,l);
  776. ai.SetCondition(TOpCmp2AsmCond[cond]);
  777. end;
  778. ai.is_jmp:=true;
  779. list.concat(ai);
  780. end;
  781. procedure tcgSPARC.a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);
  782. var
  783. ai:taicpu;
  784. begin
  785. ai := Taicpu.op_sym(A_JMPL,S_NO,l);
  786. ai.SetCondition(flags_to_cond(f));
  787. ai.is_jmp := true;
  788. list.concat(ai);
  789. end;
  790. procedure tcgSPARC.g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);
  791. VAR
  792. ai:taicpu;
  793. hreg:tregister;
  794. BEGIN
  795. hreg := rg.makeregsize(reg,OS_8);
  796. // ai:=Taicpu.Op_reg(A_Setcc,S_B,hreg);
  797. ai.SetCondition(flags_to_cond(f));
  798. list.concat(ai);
  799. IF hreg<>reg
  800. THEN
  801. a_load_reg_reg(list,OS_8,OS_8,hreg,reg);
  802. END;
  803. procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const p:TNode);
  804. var
  805. hl:TAsmLabel;
  806. begin
  807. if not(cs_check_overflow in aktlocalswitches)
  808. then
  809. exit;
  810. objectlibrary.getlabel(hl);
  811. if not((p.resulttype.def.deftype=pointerdef) or
  812. ((p.resulttype.def.deftype=orddef) and
  813. (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  814. bool8bit,bool16bit,bool32bit])))
  815. then
  816. begin
  817. list.concat(taicpu.op_reg(A_NONE,R_NONE));
  818. a_jmp_always(list,hl)
  819. end
  820. else
  821. a_jmp_cond(list,OC_NONE,hl);
  822. a_call_name(list,'FPC_OVERFLOW');
  823. a_label(list,hl);
  824. end;
  825. { *********** entry/exit code and address loading ************ }
  826. procedure tcgSPARC.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
  827. var
  828. href:TReference;
  829. i:integer;
  830. again:tasmlabel;
  831. begin
  832. {Althogh the SPARC architecture require only word alignment, software
  833. convention and the operating system require every stack frame to be double word
  834. aligned}
  835. LocalSize:=(LocalSize+7)and $FFFFFFF8;
  836. {Execute the SAVE instruction to get a new register window and create a new
  837. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  838. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  839. after execution of that instruction is the called function stack pointer}
  840. with list do
  841. concat(Taicpu.Op_reg_const_reg(A_SAVE,Stack_Pointer_Reg,-LocalSize,Stack_Pointer_Reg));
  842. end;
  843. procedure tcgSPARC.g_restore_frame_pointer(list:TAasmOutput);
  844. begin
  845. {This function intontionally does nothing as frame pointer is restored in the
  846. delay slot of the return instrucion done in g_return_from_proc}
  847. end;
  848. procedure tcgSPARC.g_return_from_proc(list:TAasmOutput;parasize:aword);
  849. begin
  850. {According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  851. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  852. RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  853. delay slot, so an inversion is possible such as
  854. JMPL %i7+8,%g0
  855. RESTORE %g0,0,%g0
  856. If no inversion we can use just
  857. RESTORE %g0,0,%g0
  858. JMPL %i7+8,%g0
  859. NOP}
  860. with list do
  861. begin
  862. {Return address is computed by adding 8 to the CALL address saved onto %i6}
  863. concat(Taicpu.Op_caddr_reg(A_JMPL,R_I7,8,R_G0));
  864. {We use trivial restore in the delay slot of the JMPL instruction, as we
  865. already set result onto %i0}
  866. concat(Taicpu.Op_reg_const_reg(A_RESTORE,R_G0,0,R_G0));
  867. end
  868. end;
  869. procedure tcgSPARC.a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);
  870. begin
  871. // list.concat(taicpu.op_ref_reg(A_LEA,S_SW,ref,r));
  872. end;
  873. { ************* 64bit operations ************ }
  874. procedure TCg64fSPARC.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  875. begin
  876. case op of
  877. OP_ADD :
  878. begin
  879. op1:=A_ADD;
  880. op2:=A_ADD;
  881. end;
  882. OP_SUB :
  883. begin
  884. op1:=A_SUB;
  885. op2:=A_SUB;
  886. end;
  887. OP_XOR :
  888. begin
  889. op1:=A_XOR;
  890. op2:=A_XOR;
  891. end;
  892. OP_OR :
  893. begin
  894. op1:=A_OR;
  895. op2:=A_OR;
  896. end;
  897. OP_AND :
  898. begin
  899. op1:=A_AND;
  900. op2:=A_AND;
  901. end;
  902. else
  903. internalerror(200203241);
  904. end;
  905. end;
  906. procedure TCg64fSPARC.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);
  907. var
  908. op1,op2:TAsmOp;
  909. tempref:TReference;
  910. begin
  911. get_64bit_ops(op,op1,op2);
  912. list.concat(taicpu.op_ref_reg(op1,ref,reg.reglo));
  913. tempref:=ref;
  914. inc(tempref.offset,4);
  915. list.concat(taicpu.op_ref_reg(op2,tempref,reg.reghi));
  916. end;
  917. procedure TCg64fSPARC.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  918. var
  919. op1,op2:TAsmOp;
  920. begin
  921. get_64bit_ops(op,op1,op2);
  922. list.concat(taicpu.op_reg_reg(op1,regsrc.reglo,regdst.reglo));
  923. list.concat(taicpu.op_reg_reg(op2,regsrc.reghi,regdst.reghi));
  924. end;
  925. procedure TCg64fSPARC.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  926. var
  927. op1,op2:TAsmOp;
  928. begin
  929. case op of
  930. OP_AND,OP_OR,OP_XOR:
  931. WITH cg DO
  932. begin
  933. a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  934. a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  935. end;
  936. OP_ADD, OP_SUB:
  937. begin
  938. // can't use a_op_const_ref because this may use dec/inc
  939. get_64bit_ops(op,op1,op2);
  940. list.concat(taicpu.op_const_reg(op1,Lo(Value),regdst.reglo));
  941. list.concat(taicpu.op_const_reg(op2,Hi(Value),regdst.reghi));
  942. end;
  943. else
  944. internalerror(200204021);
  945. end;
  946. end;
  947. procedure TCg64fSPARC.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;const ref:TReference);
  948. var
  949. op1,op2:TAsmOp;
  950. tempref:TReference;
  951. begin
  952. case op of
  953. OP_AND,OP_OR,OP_XOR:
  954. with cg do
  955. begin
  956. a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  957. tempref:=ref;
  958. inc(tempref.offset,4);
  959. a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  960. end;
  961. OP_ADD, OP_SUB:
  962. begin
  963. get_64bit_ops(op,op1,op2);
  964. // can't use a_op_const_ref because this may use dec/inc
  965. { list.concat(taicpu.op_const_ref(op1,Lo(Value),ref));
  966. tempref:=ref;
  967. inc(tempref.offset,4);
  968. list.concat(taicpu.op_const_ref(op2,S_SW,Hi(Value),tempref));}
  969. InternalError(2002102101);
  970. end;
  971. else
  972. internalerror(200204022);
  973. end;
  974. end;
  975. { ************* concatcopy ************ }
  976. procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean);
  977. var
  978. countreg: TRegister;
  979. src, dst: TReference;
  980. lab: tasmlabel;
  981. count, count2: aword;
  982. orgsrc, orgdst: boolean;
  983. begin
  984. {$ifdef extdebug}
  985. if len > high(longint)
  986. then
  987. internalerror(2002072704);
  988. {$endif extdebug}
  989. { make sure short loads are handled as optimally as possible }
  990. if not loadref then
  991. if (len <= 8) and
  992. (byte(len) in [1,2,4,8]) then
  993. begin
  994. if len < 8 then
  995. begin
  996. a_load_ref_ref(list,int_cgsize(len),source,dest);
  997. if delsource then
  998. reference_release(list,source);
  999. end
  1000. else
  1001. begin
  1002. a_reg_alloc(list,R_F0);
  1003. a_loadfpu_ref_reg(list,OS_F64,source,R_F0);
  1004. if delsource then
  1005. reference_release(list,source);
  1006. a_loadfpu_reg_ref(list,OS_F64,R_F0,dest);
  1007. a_reg_dealloc(list,R_F0);
  1008. end;
  1009. exit;
  1010. end;
  1011. reference_reset(src);
  1012. reference_reset(dst);
  1013. { load the address of source into src.base }
  1014. if loadref then
  1015. begin
  1016. src.base := get_scratch_reg_address(list);
  1017. a_load_ref_reg(list,OS_32,source,src.base);
  1018. orgsrc := false;
  1019. end
  1020. else if not issimpleref(source) or
  1021. ((source.index <> R_NO) and
  1022. ((source.offset + longint(len)) > high(smallint))) then
  1023. begin
  1024. src.base := get_scratch_reg_address(list);
  1025. a_loadaddr_ref_reg(list,source,src.base);
  1026. orgsrc := false;
  1027. end
  1028. else
  1029. begin
  1030. src := source;
  1031. orgsrc := true;
  1032. end;
  1033. if not orgsrc and delsource then
  1034. reference_release(list,source);
  1035. { load the address of dest into dst.base }
  1036. if not issimpleref(dest) or
  1037. ((dest.index <> R_NO) and
  1038. ((dest.offset + longint(len)) > high(smallint))) then
  1039. begin
  1040. dst.base := get_scratch_reg_address(list);
  1041. a_loadaddr_ref_reg(list,dest,dst.base);
  1042. orgdst := false;
  1043. end
  1044. else
  1045. begin
  1046. dst := dest;
  1047. orgdst := true;
  1048. end;
  1049. count := len div 8;
  1050. if count > 4 then
  1051. { generate a loop }
  1052. begin
  1053. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1054. { have to be set to 8. I put an Inc there so debugging may be }
  1055. { easier (should offset be different from zero here, it will be }
  1056. { easy to notice in the generated assembler }
  1057. inc(dst.offset,8);
  1058. inc(src.offset,8);
  1059. list.concat(taicpu.op_reg_const_reg(A_SUB,src.base,8,src.base));
  1060. list.concat(taicpu.op_reg_const_reg(A_SUB,dst.base,8,dst.base));
  1061. countreg := get_scratch_reg_int(list);
  1062. a_load_const_reg(list,OS_32,count,countreg);
  1063. { explicitely allocate R_O0 since it can be used safely here }
  1064. { (for holding date that's being copied) }
  1065. a_reg_alloc(list,R_F0);
  1066. objectlibrary.getlabel(lab);
  1067. a_label(list, lab);
  1068. list.concat(taicpu.op_reg_const_reg(A_SUB,countreg,1,countreg));
  1069. list.concat(taicpu.op_reg_ref(A_LDF,R_F0,src));
  1070. list.concat(taicpu.op_reg_ref(A_STD,R_F0,dst));
  1071. //a_jmp(list,A_BC,C_NE,0,lab);
  1072. free_scratch_reg(list,countreg);
  1073. a_reg_dealloc(list,R_F0);
  1074. len := len mod 8;
  1075. end;
  1076. count := len div 8;
  1077. if count > 0 then
  1078. { unrolled loop }
  1079. begin
  1080. a_reg_alloc(list,R_F0);
  1081. for count2 := 1 to count do
  1082. begin
  1083. a_loadfpu_ref_reg(list,OS_F64,src,R_F0);
  1084. a_loadfpu_reg_ref(list,OS_F64,R_F0,dst);
  1085. inc(src.offset,8);
  1086. inc(dst.offset,8);
  1087. end;
  1088. a_reg_dealloc(list,R_F0);
  1089. len := len mod 8;
  1090. end;
  1091. if (len and 4) <> 0 then
  1092. begin
  1093. a_reg_alloc(list,R_O0);
  1094. a_load_ref_reg(list,OS_32,src,R_O0);
  1095. a_load_reg_ref(list,OS_32,R_O0,dst);
  1096. inc(src.offset,4);
  1097. inc(dst.offset,4);
  1098. a_reg_dealloc(list,R_O0);
  1099. end;
  1100. { copy the leftovers }
  1101. if (len and 2) <> 0 then
  1102. begin
  1103. a_reg_alloc(list,R_O0);
  1104. a_load_ref_reg(list,OS_16,src,R_O0);
  1105. a_load_reg_ref(list,OS_16,R_O0,dst);
  1106. inc(src.offset,2);
  1107. inc(dst.offset,2);
  1108. a_reg_dealloc(list,R_O0);
  1109. end;
  1110. if (len and 1) <> 0 then
  1111. begin
  1112. a_reg_alloc(list,R_O0);
  1113. a_load_ref_reg(list,OS_8,src,R_O0);
  1114. a_load_reg_ref(list,OS_8,R_O0,dst);
  1115. a_reg_dealloc(list,R_O0);
  1116. end;
  1117. if orgsrc then
  1118. begin
  1119. if delsource then
  1120. reference_release(list,source);
  1121. end
  1122. else
  1123. free_scratch_reg(list,src.base);
  1124. if not orgdst then
  1125. free_scratch_reg(list,dst.base);
  1126. end;
  1127. function tcgSPARC.reg_cgsize(CONST reg:tregister):tcgsize;
  1128. begin
  1129. result:=OS_32;
  1130. end;
  1131. {***************** This is private property, keep out! :) *****************}
  1132. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  1133. begin
  1134. if(ref.base=R_NONE)and(ref.index <> R_NO)
  1135. then
  1136. InternalError(2002100804);
  1137. result :=not(assigned(ref.symbol))and
  1138. (((ref.index = R_NO) and
  1139. (ref.offset >= low(smallint)) and
  1140. (ref.offset <= high(smallint))) or
  1141. ((ref.index <> R_NO) and
  1142. (ref.offset = 0)));
  1143. end;
  1144. procedure tcgSPARC.sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  1145. begin
  1146. case s2 of
  1147. S_B:
  1148. if S1 in [OS_8,OS_S8]
  1149. then
  1150. s3 := S_B
  1151. else
  1152. internalerror(200109221);
  1153. S_W:
  1154. case s1 of
  1155. OS_8,OS_S8:
  1156. s3 := S_B;
  1157. OS_16,OS_S16:
  1158. s3 := S_H;
  1159. else
  1160. internalerror(200109222);
  1161. end;
  1162. S_SW:
  1163. case s1 of
  1164. OS_8,OS_S8:
  1165. s3 := S_B;
  1166. OS_16,OS_S16:
  1167. s3 := S_H;
  1168. OS_32,OS_S32:
  1169. s3 := S_W;
  1170. else
  1171. internalerror(200109223);
  1172. end;
  1173. else internalerror(200109227);
  1174. end;
  1175. if s3 in [S_B,S_W,S_SW]
  1176. then
  1177. op := A_LD
  1178. { else if s3=S_DW
  1179. then
  1180. op:=A_LDD
  1181. else if s3 in [OS_8,OS_16,OS_32]
  1182. then
  1183. op := A_NONE}
  1184. else
  1185. op := A_NONE;
  1186. end;
  1187. procedure tcgSPARC.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize);
  1188. BEGIN
  1189. (* case t of
  1190. OS_F32:begin
  1191. op:=A_FLD;
  1192. s:=S_FS;
  1193. end;
  1194. OS_F64:begin
  1195. op:=A_FLD;
  1196. { ???? }
  1197. s:=S_FL;
  1198. end;
  1199. OS_F80:begin
  1200. op:=A_FLD;
  1201. s:=S_FX;
  1202. end;
  1203. OS_C64:begin
  1204. op:=A_FILD;
  1205. s:=S_IQ;
  1206. end;
  1207. else internalerror(17);
  1208. end;*)
  1209. END;
  1210. procedure tcgSPARC.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1211. VAR
  1212. op:tasmop;
  1213. s:topsize;
  1214. BEGIN
  1215. floatloadops(t,op,s);
  1216. list.concat(Taicpu.Op_ref(op,ref));
  1217. { inc(trgcpu(rg).fpuvaroffset);}
  1218. END;
  1219. procedure tcgSPARC.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  1220. BEGIN
  1221. { case t of
  1222. OS_F32:begin
  1223. op:=A_FSTP;
  1224. s:=S_FS;
  1225. end;
  1226. OS_F64:begin
  1227. op:=A_FSTP;
  1228. s:=S_FL;
  1229. end;
  1230. OS_F80:begin
  1231. op:=A_FSTP;
  1232. s:=S_FX;
  1233. end;
  1234. OS_C64:begin
  1235. op:=A_FISTP;
  1236. s:=S_IQ;
  1237. end;
  1238. else
  1239. internalerror(17);
  1240. end;}
  1241. end;
  1242. procedure tcgSPARC.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1243. VAR
  1244. op:tasmop;
  1245. s:topsize;
  1246. BEGIN
  1247. floatstoreops(t,op,s);
  1248. list.concat(Taicpu.Op_ref(op,ref));
  1249. { dec(trgcpu(rg).fpuvaroffset);}
  1250. END;
  1251. BEGIN
  1252. cg:=tcgSPARC.create;
  1253. END.
  1254. {
  1255. $Log$
  1256. Revision 1.27 2002-12-21 23:21:47 mazen
  1257. + added support for the shift nodes
  1258. + added debug output on screen with -an command line option
  1259. Revision 1.26 2002/11/25 19:21:49 mazen
  1260. * fixed support of nSparcInline
  1261. Revision 1.25 2002/11/25 17:43:28 peter
  1262. * splitted defbase in defutil,symutil,defcmp
  1263. * merged isconvertable and is_equal into compare_defs(_ext)
  1264. * made operator search faster by walking the list only once
  1265. Revision 1.24 2002/11/17 17:49:09 mazen
  1266. + 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
  1267. Revision 1.23 2002/11/10 19:07:46 mazen
  1268. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1269. Revision 1.22 2002/11/06 11:31:24 mazen
  1270. * op_reg_reg_reg don't need any more a TOpSize parameter
  1271. Revision 1.21 2002/11/05 16:15:00 mazen
  1272. *** empty log message ***
  1273. Revision 1.20 2002/11/03 20:22:40 mazen
  1274. * parameter handling updated
  1275. Revision 1.19 2002/10/28 20:59:17 mazen
  1276. * TOpSize values changed S_L --> S_SW
  1277. Revision 1.18 2002/10/22 13:43:01 mazen
  1278. - cga.pas redueced to an empty unit
  1279. Revision 1.17 2002/10/20 19:01:38 mazen
  1280. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1281. Revision 1.16 2002/10/13 21:46:07 mazen
  1282. * assembler output format fixed
  1283. Revision 1.15 2002/10/11 13:35:14 mazen
  1284. *** empty log message ***
  1285. Revision 1.14 2002/10/10 19:57:51 mazen
  1286. * Just to update repsitory
  1287. Revision 1.13 2002/10/10 15:10:39 mazen
  1288. * Internal error fixed, but usually i386 parameter model used
  1289. Revision 1.12 2002/10/08 17:17:03 mazen
  1290. *** empty log message ***
  1291. Revision 1.11 2002/10/07 20:33:04 mazen
  1292. word alignement modified in g_stack_frame
  1293. Revision 1.10 2002/10/04 21:57:42 mazen
  1294. * register allocation for parameters now done in cpupara, but InternalError(200109223) in cgcpu.pas:1053 is still not fixed du to location_force problem in ncgutils.pas:419
  1295. Revision 1.9 2002/10/02 22:20:28 mazen
  1296. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1297. Revision 1.8 2002/10/01 21:35:58 mazen
  1298. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1299. Revision 1.7 2002/10/01 21:06:29 mazen
  1300. attinst.inc --> strinst.inc
  1301. Revision 1.6 2002/10/01 17:41:50 florian
  1302. * fixed log and id
  1303. }