cgcpu.pas 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. {*****************************************************************************}
  2. { File : cgcpu.pas }
  3. { Author : Mazen NEIFER }
  4. { Project : Free Pascal Compiler (FPC) }
  5. { Creation date : 2002\04\26 }
  6. { Licence : GPL }
  7. { Bug report : [email protected] }
  8. {*****************************************************************************}
  9. {
  10. $Id$
  11. Copyright (c) 1998-2000 by Florian Klaempfl
  12. This program is free software;you can redistribute it and/or modify
  13. it under the terms of the GNU General Public License as published by
  14. the Free Software Foundation;either version 2 of the License, or
  15. (at your option) any later version.
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY;without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. GNU General Public License for more details.
  20. You should have received a copy of the GNU General Public License
  21. along with this program;if not, write to the Free Software
  22. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. ****************************************************************************}
  24. UNIT cgcpu;
  25. {This unit implements the code generator for the SPARC architecture}
  26. {$INCLUDE fpcdefs.inc}
  27. INTERFACE
  28. USES
  29. cginfo,cgbase,cgobj,cg64f32,
  30. aasmbase,aasmtai,aasmcpu,
  31. cpubase,cpuinfo,cpupara,
  32. node,symconst;
  33. TYPE
  34. tcgSPARC=CLASS(tcg)
  35. FreeParamRegSet:TRegisterSet;
  36. {This method is used to pass a parameter, which is located in a register, to a
  37. routine. It should give the parameter to the routine, as required by the
  38. specific processor ABI. It is overriden for each CPU target.
  39. Size : is the size of the operand in the register
  40. r : is the register source of the operand
  41. nr : is number of that parameter in the routine parameters list starting
  42. from one from left to right}
  43. procedure a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;const LocPara:TParaLocation);override;
  44. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);override;
  45. procedure a_param_ref(list:TAasmOutput;size:tcgsize;CONST r:TReference;CONST LocPara:TParaLocation);override;
  46. procedure a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);override;
  47. procedure a_call_name(list:TAasmOutput;CONST s:string);override;
  48. procedure a_call_ref(list:TAasmOutput;CONST ref:TReference);override;
  49. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override;
  50. procedure a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);override;
  51. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  52. procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);override;
  53. procedure a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);override;
  54. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  55. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  56. { move instructions }
  57. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  58. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);override;
  59. procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  60. procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  61. procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override;
  62. procedure a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);override;
  63. { fpu move instructions }
  64. procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  65. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  66. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  67. { vector register move instructions }
  68. procedure a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  69. procedure a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);override;
  70. procedure a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);override;
  71. procedure a_parammm_reg(list:TAasmOutput;reg:tregister);override;
  72. { comparison operations }
  73. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  74. procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;l:tasmlabel);override;
  75. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  76. procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);override;
  77. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  78. procedure a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);override;
  79. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);override;
  80. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  81. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  82. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  83. procedure g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  84. class function reg_cgsize(CONST reg:tregister):tcgsize;override;
  85. PRIVATE
  86. function IsSimpleRef(const ref:treference):boolean;
  87. procedure sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  88. procedure floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  89. procedure floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  90. procedure floatloadops(t:tcgsize;var op:tasmop;var s:topsize);
  91. procedure floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  92. END;
  93. TCg64fSPARC=class(tcg64f32)
  94. procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);override;
  95. procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override;
  96. procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override;
  97. procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);override;
  98. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  99. END;
  100. CONST
  101. 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);
  102. 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);
  103. TCGSize2OpSize:ARRAY[tcgsize]OF TOpSize=(S_NO,S_B,S_W,S_L,S_L,S_B,S_W,S_L,S_L,S_FS,S_FL,S_FX,S_IQ,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  104. IMPLEMENTATION
  105. USES
  106. globtype,globals,verbose,systems,cutils,
  107. symdef,symsym,defbase,paramgr,
  108. rgobj,tgobj,rgcpu;
  109. { we implement the following routines because otherwise we can't }
  110. { instantiate the class since it's abstract }
  111. procedure tcgSPARC.a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;CONST LocPara:TParaLocation);
  112. BEGIN
  113. IF(Size<>OS_32)AND(Size<>OS_S32)
  114. THEN
  115. InternalError(2002032212);
  116. List.Concat(taicpu.op_reg(A_LD,S_L,r));
  117. END;
  118. procedure tcgSPARC.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);
  119. BEGIN
  120. IF(Size<>OS_32)AND(Size<>OS_S32)
  121. THEN
  122. InternalError(2002032213);
  123. List.Concat(taicpu.op_const(A_LD,S_L,a));
  124. END;
  125. procedure tcgSPARC.a_param_ref(list:TAasmOutput;size:tcgsize;const r:TReference;const LocPara:TParaLocation);
  126. var
  127. ref: treference;
  128. tmpreg:TRegister;
  129. begin
  130. if Size<>OS_32
  131. then
  132. InternalError(2002100400);
  133. case locpara.loc of
  134. LOC_REGISTER,LOC_CREGISTER:
  135. a_load_ref_reg(list,size,r,locpara.register);
  136. LOC_REFERENCE:
  137. begin
  138. reference_reset(ref);
  139. ref.base:=locpara.reference.index;
  140. ref.offset:=locpara.reference.offset;
  141. tmpreg := get_scratch_reg_int(list);
  142. a_load_ref_reg(list,size,r,tmpreg);
  143. a_load_reg_ref(list,size,tmpreg,ref);
  144. free_scratch_reg(list,tmpreg);
  145. end;
  146. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  147. case size of
  148. OS_32:
  149. a_loadfpu_ref_reg(list,OS_F32,r,locpara.register);
  150. OS_64:
  151. a_loadfpu_ref_reg(list,OS_F64,r,locpara.register);
  152. else
  153. internalerror(2002072801);
  154. end;
  155. else
  156. internalerror(2002081103);
  157. end;
  158. if locpara.sp_fixup<>0
  159. then
  160. internalerror(2002081104);
  161. end;
  162. procedure tcgSPARC.a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);
  163. VAR
  164. tmpreg:TRegister;
  165. BEGIN
  166. IF r.segment<>R_NO
  167. THEN
  168. CGMessage(cg_e_cant_use_far_pointer_there);
  169. IF(r.base=R_NO)AND(r.index=R_NO)
  170. THEN
  171. list.concat(Taicpu.Op_sym_ofs(A_LD,S_L,r.symbol,r.offset))
  172. ELSE IF(r.base=R_NO)AND(r.index<>R_NO)AND
  173. (r.offset=0)AND(r.scalefactor=0)AND(r.symbol=nil)
  174. THEN
  175. list.concat(Taicpu.Op_reg(A_LD,S_L,r.index))
  176. ELSE IF(r.base<>R_NO)AND(r.index=R_NO)AND
  177. (r.offset=0)AND(r.symbol=nil)
  178. THEN
  179. list.concat(Taicpu.Op_reg(A_LD,S_L,r.base))
  180. ELSE
  181. BEGIN
  182. tmpreg:=get_scratch_reg_address(list);
  183. a_loadaddr_ref_reg(list,r,tmpreg);
  184. list.concat(taicpu.op_reg(A_LD,S_L,tmpreg));
  185. free_scratch_reg(list,tmpreg);
  186. END;
  187. END;
  188. procedure tcgSPARC.a_call_name(list:TAasmOutput;CONST s:string);
  189. BEGIN
  190. WITH List,objectlibrary DO
  191. BEGIN
  192. concat(taicpu.op_sym(A_CALL,S_NO,newasmsymbol(s)));
  193. concat(taicpu.op_none(A_NOP,S_NO));
  194. END;
  195. END;
  196. procedure tcgSPARC.a_call_ref(list:TAasmOutput;CONST ref:TReference);
  197. BEGIN
  198. list.concat(taicpu.op_ref(A_CALL,S_NO,ref));
  199. list.concat(taicpu.op_none(A_NOP,S_NO));
  200. END;
  201. {********************** load instructions ********************}
  202. procedure tcgSPARC.a_load_const_reg(list:TAasmOutput;size:TCGSize;a:aword;reg:TRegister);
  203. BEGIN
  204. WITH List DO
  205. IF a<>0
  206. THEN{R_G0 is usually set to zero, so we use it}
  207. Concat(taicpu.op_reg_const_reg(A_OR,TCGSize2OpSize[size],R_G0,a,reg))
  208. ELSE{The is no A_MOV in sparc, that's why we use A_OR with help of R_G0}
  209. Concat(taicpu.op_reg_reg_reg(A_OR,TCGSize2OpSize[size],R_G0,R_G0,reg));
  210. END;
  211. procedure tcgSPARC.a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);
  212. BEGIN
  213. WITH List DO
  214. IF a=0
  215. THEN
  216. Concat(taicpu.op_reg_ref(A_ST,TCGSize2OpSize[size],R_G0,ref))
  217. ELSE
  218. BEGIN
  219. a_load_const_reg(list,size,a,R_G1);
  220. list.concat(taicpu.op_reg_ref(A_ST,TCGSize2OpSize[size],R_G1,ref));
  221. END;
  222. END;
  223. procedure tcgSPARC.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;CONST ref:TReference);
  224. BEGIN
  225. list.concat(taicpu.op_reg_ref(A_LD,TCGSize2OpSize[size],reg,ref));
  226. END;
  227. procedure tcgSPARC.a_load_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);
  228. var
  229. op:tasmop;
  230. s:topsize;
  231. begin
  232. sizes2load(size,S_L,op,s);
  233. list.concat(taicpu.op_ref_reg(op,s,ref,reg));
  234. end;
  235. procedure tcgSPARC.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  236. var
  237. op:tasmop;
  238. s:topsize;
  239. begin
  240. if(reg1<>reg2)or
  241. (tcgsize2size[tosize]<tcgsize2size[fromsize])or
  242. ((tcgsize2size[tosize] = tcgsize2size[fromsize])and
  243. (tosize <> fromsize)and
  244. not(fromsize in [OS_32,OS_S32]))
  245. then
  246. with list do
  247. case fromsize of
  248. OS_8:
  249. InternalError(2002100800);{concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,reg2,reg1,0,31-8+1,31));}
  250. OS_S8:
  251. InternalError(2002100801);{concat(taicpu.op_reg_reg(A_EXTSB,reg2,reg1));}
  252. OS_16:
  253. InternalError(2002100802);{concat(taicpu.op_reg_reg_const_const_const(A_RLWINM,reg2,reg1,0,31-16+1,31));}
  254. OS_S16:
  255. InternalError(2002100803);{concat(taicpu.op_reg_reg(A_EXTSH,reg2,reg1));}
  256. OS_32,OS_S32:
  257. concat(taicpu.op_reg_reg_reg(A_OR,S_L,R_G0,reg1,reg2));
  258. else internalerror(2002090901);
  259. end;
  260. end;
  261. { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
  262. { R_ST means "the current value at the top of the fpu stack" (JM) }
  263. procedure tcgSPARC.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  264. begin
  265. if NOT (reg1 IN [R_F0..R_F31]) then
  266. begin
  267. list.concat(taicpu.op_reg(A_NONE,S_NO,
  268. trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset)));
  269. inc(trgcpu(rg).fpuvaroffset);
  270. end;
  271. if NOT (reg2 IN [R_F0..R_F31]) then
  272. begin
  273. list.concat(taicpu.op_reg(A_JMPL,S_NO,
  274. trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset)));
  275. dec(trgcpu(rg).fpuvaroffset);
  276. end;
  277. end;
  278. procedure tcgSPARC.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);
  279. begin
  280. floatload(list,size,ref);
  281. { if (reg <> R_ST) then
  282. a_loadfpu_reg_reg(list,R_ST,reg);}
  283. end;
  284. procedure tcgSPARC.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);
  285. begin
  286. { if reg <> R_ST then
  287. a_loadfpu_reg_reg(list,reg,R_ST);}
  288. floatstore(list,size,ref);
  289. end;
  290. procedure tcgSPARC.a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  291. begin
  292. // list.concat(taicpu.op_reg_reg(A_NONEQ,S_NO,reg1,reg2));
  293. end;
  294. procedure tcgSPARC.a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);
  295. begin
  296. // list.concat(taicpu.op_ref_reg(A_NONEQ,S_NO,ref,reg));
  297. end;
  298. procedure tcgSPARC.a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);
  299. begin
  300. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,ref));
  301. end;
  302. procedure tcgSPARC.a_parammm_reg(list:TAasmOutput;reg:tregister);
  303. VAR
  304. href:TReference;
  305. BEGIN
  306. // list.concat(taicpu.op_const_reg(A_SUB,S_L,8,R_RSP));
  307. // reference_reset_base(href,R_ESP,0);
  308. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,href));
  309. END;
  310. procedure tcgSPARC.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);
  311. var
  312. opcode:tasmop;
  313. power:LongInt;
  314. begin
  315. (* Case Op of
  316. OP_DIV, OP_IDIV:
  317. Begin
  318. if ispowerof2(a,power) then
  319. begin
  320. case op of
  321. OP_DIV:
  322. opcode := A_SHR;
  323. OP_IDIV:
  324. opcode := A_SAR;
  325. end;
  326. list.concat(taicpu.op_const_reg(opcode,S_L,power,
  327. reg));
  328. exit;
  329. end;
  330. { the rest should be handled specifically in the code }
  331. { generator because of the silly register usage restraints }
  332. internalerror(200109224);
  333. End;
  334. OP_MUL,OP_IMUL:
  335. begin
  336. if not(cs_check_overflow in aktlocalswitches) and
  337. ispowerof2(a,power) then
  338. begin
  339. list.concat(taicpu.op_const_reg(A_SHL,S_L,power,
  340. reg));
  341. exit;
  342. end;
  343. if op = OP_IMUL then
  344. list.concat(taicpu.op_const_reg(A_IMUL,S_L,
  345. a,reg))
  346. else
  347. { OP_MUL should be handled specifically in the code }
  348. { generator because of the silly register usage restraints }
  349. internalerror(200109225);
  350. end;
  351. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  352. if not(cs_check_overflow in aktlocalswitches) and
  353. (a = 1) and
  354. (op in [OP_ADD,OP_SUB]) then
  355. if op = OP_ADD then
  356. list.concat(taicpu.op_reg(A_INC,S_L,reg))
  357. else
  358. list.concat(taicpu.op_reg(A_DEC,S_L,reg))
  359. else if (a = 0) then
  360. if (op <> OP_AND) then
  361. exit
  362. else
  363. list.concat(taicpu.op_const_reg(A_NONE,S_L,0,reg))
  364. else if (a = high(aword)) and
  365. (op in [OP_AND,OP_OR,OP_XOR]) then
  366. begin
  367. case op of
  368. OP_AND:
  369. exit;
  370. OP_OR:
  371. list.concat(taicpu.op_const_reg(A_NONE,S_L,high(aword),reg));
  372. OP_XOR:
  373. list.concat(taicpu.op_reg(A_NOT,S_L,reg));
  374. end
  375. end
  376. else
  377. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],S_L,
  378. a,reg));
  379. OP_SHL,OP_SHR,OP_SAR:
  380. begin
  381. if (a and 31) <> 0 Then
  382. list.concat(taicpu.op_const_reg(
  383. TOpCG2AsmOp[op],S_L,a and 31,reg));
  384. if (a shr 5) <> 0 Then
  385. internalerror(68991);
  386. end
  387. else internalerror(68992);
  388. end;*)
  389. end;
  390. procedure tcgSPARC.a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);
  391. var
  392. opcode:tasmop;
  393. power:LongInt;
  394. begin
  395. (* Case Op of
  396. OP_DIV, OP_IDIV:
  397. Begin
  398. if ispowerof2(a,power) then
  399. begin
  400. case op of
  401. OP_DIV:
  402. opcode := A_SHR;
  403. OP_IDIV:
  404. opcode := A_SAR;
  405. end;
  406. list.concat(taicpu.op_const_ref(opcode,
  407. TCgSize2OpSize[size],power,ref));
  408. exit;
  409. end;
  410. { the rest should be handled specifically in the code }
  411. { generator because of the silly register usage restraints }
  412. internalerror(200109231);
  413. End;
  414. OP_MUL,OP_IMUL:
  415. begin
  416. if not(cs_check_overflow in aktlocalswitches) and
  417. ispowerof2(a,power) then
  418. begin
  419. list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
  420. power,ref));
  421. exit;
  422. end;
  423. { can't multiply a memory location directly with a CONSTant }
  424. if op = OP_IMUL then
  425. inherited a_op_const_ref(list,op,size,a,ref)
  426. else
  427. { OP_MUL should be handled specifically in the code }
  428. { generator because of the silly register usage restraints }
  429. internalerror(200109232);
  430. end;
  431. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  432. if not(cs_check_overflow in aktlocalswitches) and
  433. (a = 1) and
  434. (op in [OP_ADD,OP_SUB]) then
  435. if op = OP_ADD then
  436. list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
  437. else
  438. list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
  439. else if (a = 0) then
  440. if (op <> OP_AND) then
  441. exit
  442. else
  443. a_load_const_ref(list,size,0,ref)
  444. else if (a = high(aword)) and
  445. (op in [OP_AND,OP_OR,OP_XOR]) then
  446. begin
  447. case op of
  448. OP_AND:
  449. exit;
  450. OP_OR:
  451. list.concat(taicpu.op_const_ref(A_NONE,TCgSize2OpSize[size],high(aword),ref));
  452. OP_XOR:
  453. list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref));
  454. end
  455. end
  456. else
  457. list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
  458. TCgSize2OpSize[size],a,ref));
  459. OP_SHL,OP_SHR,OP_SAR:
  460. begin
  461. if (a and 31) <> 0 Then
  462. list.concat(taicpu.op_const_ref(
  463. TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
  464. if (a shr 5) <> 0 Then
  465. internalerror(68991);
  466. end
  467. else internalerror(68992);
  468. end;*)
  469. end;
  470. procedure tcgSPARC.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  471. var
  472. regloadsize:tcgsize;
  473. dstsize:topsize;
  474. tmpreg:tregister;
  475. popecx:boolean;
  476. begin
  477. (* dstsize := S_Q{makeregsize(dst,size)};
  478. case op of
  479. OP_NEG,OP_NOT:
  480. begin
  481. if src <> R_NO then
  482. internalerror(200112291);
  483. list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
  484. end;
  485. OP_MUL,OP_DIV,OP_IDIV:
  486. { special stuff, needs separate handling inside code }
  487. { generator }
  488. internalerror(200109233);
  489. OP_SHR,OP_SHL,OP_SAR:
  490. begin
  491. tmpreg := R_NO;
  492. { we need cl to hold the shift count, so if the destination }
  493. { is ecx, save it to a temp for now }
  494. if dst in [R_ECX,R_CX,R_CL] then
  495. begin
  496. case S_L of
  497. S_B:regloadsize := OS_8;
  498. S_W:regloadsize := OS_16;
  499. else regloadsize := OS_32;
  500. end;
  501. tmpreg := get_scratch_reg(list);
  502. a_load_reg_reg(list,regloadsize,OS_32,src,tmpreg);
  503. end;
  504. if not(src in [R_ECX,R_CX,R_CL]) then
  505. begin
  506. { is ecx still free (it's also free if it was allocated }
  507. { to dst, since we've moved dst somewhere else already) }
  508. if not((dst = R_ECX) or
  509. ((R_ECX in rg.unusedregsint) and
  510. { this will always be true, it's just here to }
  511. { allocate ecx }
  512. (rg.getexplicitregisterint(list,R_ECX) = R_ECX))) then
  513. begin
  514. list.concat(taicpu.op_reg(A_NONE,S_L,R_ECX));
  515. popecx := true;
  516. end;
  517. a_load_reg_reg(list,OS_8,OS_8,(src),R_CL);
  518. end
  519. else
  520. src := R_CL;
  521. { do the shift }
  522. if tmpreg = R_NO then
  523. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  524. R_CL,dst))
  525. else
  526. begin
  527. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],S_L,
  528. R_CL,tmpreg));
  529. { move result back to the destination }
  530. a_load_reg_reg(list,OS_32,OS_32,tmpreg,R_ECX);
  531. free_scratch_reg(list,tmpreg);
  532. end;
  533. if popecx then
  534. list.concat(taicpu.op_reg(A_POP,S_L,R_ECX))
  535. else if not (dst in [R_ECX,R_CX,R_CL]) then
  536. rg.ungetregisterint(list,R_ECX);
  537. end;
  538. else
  539. begin
  540. if S_L <> dstsize then
  541. internalerror(200109226);
  542. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  543. src,dst));
  544. end;
  545. end;*)
  546. end;
  547. procedure tcgSPARC.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);
  548. var
  549. opsize:topsize;
  550. begin
  551. (* case op of
  552. OP_NEG,OP_NOT,OP_IMUL:
  553. begin
  554. inherited a_op_ref_reg(list,op,size,ref,reg);
  555. end;
  556. OP_MUL,OP_DIV,OP_IDIV:
  557. { special stuff, needs separate handling inside code }
  558. { generator }
  559. internalerror(200109239);
  560. else
  561. begin
  562. opsize := S_Q{makeregsize(reg,size)};
  563. list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,ref,reg));
  564. end;
  565. end;*)
  566. end;
  567. procedure tcgSPARC.a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);
  568. var
  569. opsize:topsize;
  570. begin
  571. (* case op of
  572. OP_NEG,OP_NOT:
  573. begin
  574. if reg <> R_NO then
  575. internalerror(200109237);
  576. list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
  577. end;
  578. OP_IMUL:
  579. begin
  580. { this one needs a load/imul/store, which is the default }
  581. inherited a_op_ref_reg(list,op,size,ref,reg);
  582. end;
  583. OP_MUL,OP_DIV,OP_IDIV:
  584. { special stuff, needs separate handling inside code }
  585. { generator }
  586. internalerror(200109238);
  587. else
  588. begin
  589. opsize := tcgsize2opsize[size];
  590. list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref));
  591. end;
  592. end;*)
  593. end;
  594. procedure tcgSPARC.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;
  595. size:tcgsize;a:aword;src, dst:tregister);
  596. var
  597. tmpref:TReference;
  598. power:LongInt;
  599. opsize:topsize;
  600. begin
  601. opsize := S_L;
  602. if (opsize <> S_L) or
  603. not (size in [OS_32,OS_S32]) then
  604. begin
  605. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  606. exit;
  607. end;
  608. { if we get here, we have to do a 32 bit calculation, guaranteed }
  609. Case Op of
  610. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  611. OP_SAR:
  612. { can't do anything special for these }
  613. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  614. OP_IMUL:
  615. begin
  616. if not(cs_check_overflow in aktlocalswitches) and
  617. ispowerof2(a,power) then
  618. { can be done with a shift }
  619. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  620. list.concat(taicpu.op_reg_const_reg(A_SMUL,S_L,src,a,dst));
  621. end;
  622. OP_ADD, OP_SUB:
  623. if (a = 0) then
  624. a_load_reg_reg(list,size,size,src,dst)
  625. else
  626. begin
  627. reference_reset(tmpref);
  628. tmpref.base := src;
  629. tmpref.offset := LongInt(a);
  630. if op = OP_SUB then
  631. tmpref.offset := -tmpref.offset;
  632. list.concat(taicpu.op_ref_reg(A_NONE,S_L,tmpref,dst));
  633. end
  634. else internalerror(200112302);
  635. end;
  636. end;
  637. procedure tcgSPARC.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;
  638. size:tcgsize;src1, src2, dst:tregister);
  639. var
  640. tmpref:TReference;
  641. opsize:topsize;
  642. begin
  643. opsize := S_L;
  644. if (opsize <> S_L) or
  645. (S_L <> S_L) or
  646. not (size in [OS_32,OS_S32]) then
  647. begin
  648. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  649. exit;
  650. end;
  651. { if we get here, we have to do a 32 bit calculation, guaranteed }
  652. Case Op of
  653. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  654. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  655. { can't do anything special for these }
  656. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  657. OP_IMUL:
  658. list.concat(taicpu.op_reg_reg_reg(A_SMUL,S_L,src1,src2,dst));
  659. OP_ADD:
  660. begin
  661. reference_reset(tmpref);
  662. tmpref.base := src1;
  663. tmpref.index := src2;
  664. tmpref.scalefactor := 1;
  665. list.concat(taicpu.op_ref_reg(A_NONE,S_L,tmpref,dst));
  666. end
  667. else internalerror(200112303);
  668. end;
  669. end;
  670. {*************** compare instructructions ****************}
  671. procedure tcgSPARC.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;
  672. l:tasmlabel);
  673. begin
  674. if (a = 0) then
  675. list.concat(taicpu.op_reg_reg(A_CMP,S_L,reg,reg))
  676. else
  677. list.concat(taicpu.op_const_reg(A_CMP,S_L,a,reg));
  678. a_jmp_cond(list,cmp_op,l);
  679. end;
  680. procedure tcgSPARC.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;
  681. l:tasmlabel);
  682. begin
  683. list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,ref));
  684. a_jmp_cond(list,cmp_op,l);
  685. end;
  686. procedure tcgSPARC.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;
  687. reg1,reg2:tregister;l:tasmlabel);
  688. begin
  689. { if regsize(reg1) <> S_L then
  690. internalerror(200109226);
  691. list.concat(taicpu.op_reg_reg(A_CMP,regsize(reg1),reg1,reg2));
  692. a_jmp_cond(list,cmp_op,l);}
  693. end;
  694. procedure tcgSPARC.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);
  695. var
  696. opsize:topsize;
  697. begin
  698. opsize := S_Q{makeregsize(reg,size)};
  699. list.concat(taicpu.op_ref_reg(A_CMP,opsize,ref,reg));
  700. a_jmp_cond(list,cmp_op,l);
  701. end;
  702. procedure tcgSPARC.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);
  703. var
  704. ai:taicpu;
  705. begin
  706. if cond=OC_None then
  707. ai := Taicpu.Op_sym(A_JMPL,S_NO,l)
  708. else
  709. begin
  710. ai:=Taicpu.Op_sym(A_JMPL,S_NO,l);
  711. ai.SetCondition(TOpCmp2AsmCond[cond]);
  712. end;
  713. ai.is_jmp:=true;
  714. list.concat(ai);
  715. end;
  716. procedure tcgSPARC.a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);
  717. var
  718. ai:taicpu;
  719. begin
  720. ai := Taicpu.op_sym(A_JMPL,S_NO,l);
  721. ai.SetCondition(flags_to_cond(f));
  722. ai.is_jmp := true;
  723. list.concat(ai);
  724. end;
  725. procedure tcgSPARC.g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);
  726. VAR
  727. ai:taicpu;
  728. hreg:tregister;
  729. BEGIN
  730. hreg := rg.makeregsize(reg,OS_8);
  731. // ai:=Taicpu.Op_reg(A_Setcc,S_B,hreg);
  732. ai.SetCondition(flags_to_cond(f));
  733. list.concat(ai);
  734. IF hreg<>reg
  735. THEN
  736. a_load_reg_reg(list,OS_8,OS_8,hreg,reg);
  737. END;
  738. { *********** entry/exit code and address loading ************ }
  739. procedure tcgSPARC.g_stackframe_entry(list:TAasmOutput;localsize:LongInt);
  740. var
  741. href:TReference;
  742. i:integer;
  743. again:tasmlabel;
  744. begin
  745. {According the the SPARC ABI the standard stack frame must include :
  746. * 16 word save for the in and local registers in case of overflow/underflow.
  747. this save area always must exist at the %o6+0,
  748. * software conventions requires space for the aggregate return value pointer, even if the word is not used,
  749. * althogh the first six words of arguments reside in registers, the standard
  750. stack frame reserves space for them. Arguments beond the sixth reside on the
  751. stack as in the Intel architecture,
  752. * other areas depend on the compiler and the code being compiled. The
  753. standard calling sequence does not define a maximum stack frame size, nor does
  754. it restrict how a language system uses the "unspecified" areas of the standard
  755. stack frame.}
  756. Dec(LocalSize,(16+1+5)*4);
  757. {Althogh the SPARC architecture require only word alignment, software
  758. convention and the operating system require every stack frame to be double word
  759. aligned}
  760. LocalSize:=(LocalSize+3)and $FFFFFFFC;
  761. {Execute the SAVE instruction to get a new register window and get a new stack
  762. frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state before
  763. execution of the SAVE instrucion so it is the caller %i6, when the %i6 after
  764. execution of that instrucion is the called function stack pointer}
  765. with list do
  766. concat(Taicpu.Op_reg_const_reg(A_SAVE,S_L,Stack_Pointer_Reg,localsize,Stack_Pointer_Reg));
  767. end;
  768. procedure tcgSPARC.g_restore_frame_pointer(list:TAasmOutput);
  769. begin
  770. {This function intontionally does nothing as frame pointer is restored in the
  771. delay slot of the return instrucion done in g_return_from_proc}
  772. end;
  773. procedure tcgSPARC.g_return_from_proc(list:TAasmOutput;parasize:aword);
  774. var
  775. RetReference:TReference;
  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 %i6+8,%g0
  782. RESTORE %g0,0,%g0
  783. If no inversion we can use just
  784. RESTORE %g0,0,%g0
  785. JMPL %i6+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. reference_reset_base(RetReference,R_I7,8);
  791. concat(Taicpu.Op_ref_reg(A_JMPL,S_L,RetReference,R_G0));
  792. {We use trivial restore in the delay slot of the JMPL instruction, as we
  793. already set result onto %i0}
  794. concat(Taicpu.Op_reg_const_reg(A_RESTORE,S_L,R_G0,0,R_G0));
  795. end
  796. end;
  797. procedure tcgSPARC.a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);
  798. begin
  799. // list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,r));
  800. end;
  801. { ************* 64bit operations ************ }
  802. procedure TCg64fSPARC.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  803. begin
  804. case op of
  805. OP_ADD :
  806. begin
  807. op1:=A_ADD;
  808. op2:=A_ADD;
  809. end;
  810. OP_SUB :
  811. begin
  812. op1:=A_SUB;
  813. op2:=A_SUB;
  814. end;
  815. OP_XOR :
  816. begin
  817. op1:=A_XOR;
  818. op2:=A_XOR;
  819. end;
  820. OP_OR :
  821. begin
  822. op1:=A_OR;
  823. op2:=A_OR;
  824. end;
  825. OP_AND :
  826. begin
  827. op1:=A_AND;
  828. op2:=A_AND;
  829. end;
  830. else
  831. internalerror(200203241);
  832. end;
  833. end;
  834. procedure TCg64fSPARC.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);
  835. var
  836. op1,op2:TAsmOp;
  837. tempref:TReference;
  838. begin
  839. get_64bit_ops(op,op1,op2);
  840. list.concat(taicpu.op_ref_reg(op1,S_L,ref,reg.reglo));
  841. tempref:=ref;
  842. inc(tempref.offset,4);
  843. list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
  844. end;
  845. procedure TCg64fSPARC.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  846. var
  847. op1,op2:TAsmOp;
  848. begin
  849. get_64bit_ops(op,op1,op2);
  850. list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
  851. list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
  852. end;
  853. procedure TCg64fSPARC.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  854. var
  855. op1,op2:TAsmOp;
  856. begin
  857. case op of
  858. OP_AND,OP_OR,OP_XOR:
  859. WITH cg DO
  860. begin
  861. a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  862. a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  863. end;
  864. OP_ADD, OP_SUB:
  865. begin
  866. // can't use a_op_const_ref because this may use dec/inc
  867. get_64bit_ops(op,op1,op2);
  868. list.concat(taicpu.op_const_reg(op1,S_L,Lo(Value),regdst.reglo));
  869. list.concat(taicpu.op_const_reg(op2,S_L,Hi(Value),regdst.reghi));
  870. end;
  871. else
  872. internalerror(200204021);
  873. end;
  874. end;
  875. procedure TCg64fSPARC.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);
  876. var
  877. op1,op2:TAsmOp;
  878. tempref:TReference;
  879. begin
  880. case op of
  881. OP_AND,OP_OR,OP_XOR:
  882. WITH cg DO
  883. begin
  884. a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  885. tempref:=ref;
  886. inc(tempref.offset,4);
  887. a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  888. end;
  889. OP_ADD, OP_SUB:
  890. begin
  891. get_64bit_ops(op,op1,op2);
  892. // can't use a_op_const_ref because this may use dec/inc
  893. list.concat(taicpu.op_const_ref(op1,S_L,Lo(Value),ref));
  894. tempref:=ref;
  895. inc(tempref.offset,4);
  896. list.concat(taicpu.op_const_ref(op2,S_L,Hi(Value),tempref));
  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_L,src.base,8,src.base));
  987. list.concat(taicpu.op_reg_const_reg(A_SUB,S_L,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_L,countreg,1,countreg));
  996. list.concat(taicpu.op_reg_ref(A_LDF,S_L,R_F0,src));
  997. list.concat(taicpu.op_reg_ref(A_STD,S_L,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. CONST
  1056. regsize_2_cgsize:array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32);
  1057. begin
  1058. result := regsize_2_cgsize[S_L];
  1059. end;
  1060. {***************** This is private property, keep out! :) *****************}
  1061. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  1062. begin
  1063. if(ref.base=R_NONE)and(ref.index <> R_NO)
  1064. then
  1065. InternalError(2002100804);
  1066. result :=not(assigned(ref.symbol))and
  1067. (((ref.index = R_NO) and
  1068. (ref.offset >= low(smallint)) and
  1069. (ref.offset <= high(smallint))) or
  1070. ((ref.index <> R_NO) and
  1071. (ref.offset = 0)));
  1072. end;
  1073. procedure tcgSPARC.sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  1074. begin
  1075. case s2 of
  1076. S_B:
  1077. if S1 in [OS_8,OS_S8]
  1078. then
  1079. s3 := S_B
  1080. else
  1081. internalerror(200109221);
  1082. S_W:
  1083. case s1 of
  1084. OS_8,OS_S8:
  1085. s3 := S_BW;
  1086. OS_16,OS_S16:
  1087. s3 := S_W;
  1088. else
  1089. internalerror(200109222);
  1090. end;
  1091. S_L:
  1092. case s1 of
  1093. OS_8,OS_S8:
  1094. s3 := S_BL;
  1095. OS_16,OS_S16:
  1096. s3 := S_WL;
  1097. OS_32,OS_S32:
  1098. s3 := S_L;
  1099. else
  1100. internalerror(200109223);
  1101. end;
  1102. else internalerror(200109227);
  1103. end;
  1104. if s3 in [S_B,S_W,S_L]
  1105. then
  1106. op := A_LD
  1107. { else if s3=S_DW
  1108. then
  1109. op:=A_LDD
  1110. else if s3 in [OS_8,OS_16,OS_32]
  1111. then
  1112. op := A_NONE}
  1113. else
  1114. op := A_NONE;
  1115. end;
  1116. procedure tcgSPARC.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize);
  1117. BEGIN
  1118. (* case t of
  1119. OS_F32:begin
  1120. op:=A_FLD;
  1121. s:=S_FS;
  1122. end;
  1123. OS_F64:begin
  1124. op:=A_FLD;
  1125. { ???? }
  1126. s:=S_FL;
  1127. end;
  1128. OS_F80:begin
  1129. op:=A_FLD;
  1130. s:=S_FX;
  1131. end;
  1132. OS_C64:begin
  1133. op:=A_FILD;
  1134. s:=S_IQ;
  1135. end;
  1136. else internalerror(17);
  1137. end;*)
  1138. END;
  1139. procedure tcgSPARC.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1140. VAR
  1141. op:tasmop;
  1142. s:topsize;
  1143. BEGIN
  1144. floatloadops(t,op,s);
  1145. list.concat(Taicpu.Op_ref(op,s,ref));
  1146. inc(trgcpu(rg).fpuvaroffset);
  1147. END;
  1148. procedure tcgSPARC.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  1149. BEGIN
  1150. { case t of
  1151. OS_F32:begin
  1152. op:=A_FSTP;
  1153. s:=S_FS;
  1154. end;
  1155. OS_F64:begin
  1156. op:=A_FSTP;
  1157. s:=S_FL;
  1158. end;
  1159. OS_F80:begin
  1160. op:=A_FSTP;
  1161. s:=S_FX;
  1162. end;
  1163. OS_C64:begin
  1164. op:=A_FISTP;
  1165. s:=S_IQ;
  1166. end;
  1167. else
  1168. internalerror(17);
  1169. end;}
  1170. end;
  1171. procedure tcgSPARC.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1172. VAR
  1173. op:tasmop;
  1174. s:topsize;
  1175. BEGIN
  1176. floatstoreops(t,op,s);
  1177. list.concat(Taicpu.Op_ref(op,s,ref));
  1178. dec(trgcpu(rg).fpuvaroffset);
  1179. END;
  1180. BEGIN
  1181. cg:=tcgSPARC.create;
  1182. END.
  1183. {
  1184. $Log$
  1185. Revision 1.12 2002-10-08 17:17:03 mazen
  1186. *** empty log message ***
  1187. Revision 1.11 2002/10/07 20:33:04 mazen
  1188. word alignement modified in g_stack_frame
  1189. Revision 1.10 2002/10/04 21:57:42 mazen
  1190. * 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
  1191. Revision 1.9 2002/10/02 22:20:28 mazen
  1192. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1193. Revision 1.8 2002/10/01 21:35:58 mazen
  1194. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1195. Revision 1.7 2002/10/01 21:06:29 mazen
  1196. attinst.inc --> strinst.inc
  1197. Revision 1.6 2002/10/01 17:41:50 florian
  1198. * fixed log and id
  1199. }