cgcpu.pas 46 KB

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