cgcpu.pas 52 KB

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