cgcpu.pas 49 KB

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