cgcpu.pas 46 KB

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