cgcpu.pas 46 KB

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