cgcpu.pas 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. {*****************************************************************************}
  2. { File : cgcpu.pas }
  3. { Author : Mazen NEIFER }
  4. { Project : Free Pascal Compiler (FPC) }
  5. { Creation date : 2002\04\26 }
  6. { Last modification date : 2002\08\20 }
  7. { Licence : GPL }
  8. { Bug report : [email protected] }
  9. {*****************************************************************************}
  10. {
  11. $Id$
  12. Copyright (c) 1998-2000 by Florian Klaempfl
  13. This program is free software;you can redistribute it and/or modify
  14. it under the terms of the GNU General Public License as published by
  15. the Free Software Foundation;either version 2 of the License, or
  16. (at your option) any later version.
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY;without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. GNU General Public License for more details.
  21. You should have received a copy of the GNU General Public License
  22. along with this program;if not, write to the Free Software
  23. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24. ****************************************************************************}
  25. UNIT cgcpu;
  26. {This unit implements the code generator for the SPARC architecture}
  27. {$INCLUDE fpcdefs.inc}
  28. INTERFACE
  29. USES
  30. cginfo,cgbase,cgobj,cg64f32,
  31. aasmbase,aasmtai,aasmcpu,
  32. cpubase,cpuinfo,cpupara,
  33. node,symconst;
  34. TYPE
  35. tcgSPARC=CLASS(tcg)
  36. PROCEDURE a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;CONST LocPara:TParaLocation);OVERRIDE;
  37. {This method is used to pass a parameter, which is located in a register, to a
  38. routine. It should push/send the parameter to the routine, as required by the
  39. specific processor ABI. It is overriden for each CPU target.
  40. Size : is the size of the operand in the register
  41. r : is the register source of the operand
  42. nr : is number of that parameter in the routine parameters list starting
  43. from one from left to right}
  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,size: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. PROCEDURE sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  87. PROCEDURE floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  88. PROCEDURE floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  89. PROCEDURE floatloadops(t:tcgsize;var op:tasmop;var s:topsize);
  90. PROCEDURE floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  91. END;
  92. TCg64fSPARC=class(tcg64f32)
  93. PROCEDURE a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);OVERRIDE;
  94. PROCEDURE a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);OVERRIDE;
  95. PROCEDURE a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);OVERRIDE;
  96. PROCEDURE a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);OVERRIDE;
  97. PROCEDURE get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  98. END;
  99. CONST
  100. TOpCG2AsmOp:ARRAY[topcg]OF TAsmOp=(A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_UMUL, A_SMUL, A_NEG,A_NOT,A_OR,A_not,A_not,A_not,A_SUB,A_XOR);
  101. TOpCmp2AsmCond:ARRAY[topcmp]OF TAsmCond=(C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A);
  102. TCGSize2OpSize:ARRAY[tcgsize]OF TOpSize=(S_NO,S_B,S_W,S_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);
  103. IMPLEMENTATION
  104. USES
  105. globtype,globals,verbose,systems,cutils,
  106. symdef,symsym,defbase,paramgr,
  107. rgobj,tgobj,rgcpu;
  108. { we implement the following routines because otherwise we can't }
  109. { instantiate the class since it's abstract }
  110. PROCEDURE tcgSPARC.a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;CONST LocPara:TParaLocation);
  111. BEGIN
  112. IF(Size<>OS_32)AND(Size<>OS_S32)
  113. THEN
  114. InternalError(2002032212);
  115. List.Concat(taicpu.op_reg(A_LD,S_L,r));
  116. END;
  117. PROCEDURE tcgSPARC.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);
  118. BEGIN
  119. IF(Size<>OS_32)AND(Size<>OS_S32)
  120. THEN
  121. InternalError(2002032213);
  122. List.Concat(taicpu.op_const(A_LD,S_L,a));
  123. END;
  124. PROCEDURE tcgSPARC.a_param_ref(list:TAasmOutput;size:tcgsize;CONST r:TReference;CONST LocPara:TParaLocation);
  125. VAR
  126. tmpreg:TRegister;
  127. BEGIN
  128. IF((Size=OS_32)AND(Size=OS_S32))
  129. THEN
  130. InternalError(2002032214);
  131. list.concat(taicpu.op_ref(A_LD,S_L,r));
  132. END;
  133. PROCEDURE tcgSPARC.a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);
  134. VAR
  135. tmpreg:TRegister;
  136. BEGIN
  137. IF r.segment<>R_NO
  138. THEN
  139. CGMessage(cg_e_cant_use_far_pointer_there);
  140. IF(r.base=R_NO)AND(r.index=R_NO)
  141. THEN
  142. list.concat(Taicpu.Op_sym_ofs(A_LD,S_L,r.symbol,r.offset))
  143. ELSE IF(r.base=R_NO)AND(r.index<>R_NO)AND
  144. (r.offset=0)AND(r.scalefactor=0)AND(r.symbol=nil)
  145. THEN
  146. list.concat(Taicpu.Op_reg(A_LD,S_L,r.index))
  147. ELSE IF(r.base<>R_NO)AND(r.index=R_NO)AND
  148. (r.offset=0)AND(r.symbol=nil)
  149. THEN
  150. list.concat(Taicpu.Op_reg(A_LD,S_L,r.base))
  151. ELSE
  152. BEGIN
  153. tmpreg:=get_scratch_reg_address(list);
  154. a_loadaddr_ref_reg(list,r,tmpreg);
  155. list.concat(taicpu.op_reg(A_LD,S_L,tmpreg));
  156. free_scratch_reg(list,tmpreg);
  157. END;
  158. END;
  159. PROCEDURE tcgSPARC.a_call_name(list:TAasmOutput;CONST s:string);
  160. BEGIN
  161. WITH List,objectlibrary DO
  162. BEGIN
  163. concat(taicpu.op_sym(A_CALL,S_NO,newasmsymbol(s)));
  164. concat(taicpu.op_none(A_NOP,S_NO));
  165. END;
  166. END;
  167. PROCEDURE tcgSPARC.a_call_ref(list:TAasmOutput;CONST ref:TReference);
  168. BEGIN
  169. list.concat(taicpu.op_ref(A_CALL,S_NO,ref));
  170. list.concat(taicpu.op_none(A_NOP,S_NO));
  171. END;
  172. {********************** load instructions ********************}
  173. PROCEDURE tcgSPARC.a_load_const_reg(list:TAasmOutput;size:TCGSize;a:aword;reg:TRegister);
  174. BEGIN
  175. WITH List DO
  176. IF a<>0
  177. THEN{R_G0 is usually set to zero, so we use it}
  178. Concat(taicpu.op_reg_const_reg(A_OR,TCGSize2OpSize[size],R_G0,a,reg))
  179. ELSE{The is no A_MOV in sparc, that's why we use A_OR with help of R_G0}
  180. Concat(taicpu.op_reg_reg_reg(A_OR,TCGSize2OpSize[size],R_G0,R_G0,reg));
  181. END;
  182. PROCEDURE tcgSPARC.a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);
  183. BEGIN
  184. WITH List DO
  185. IF a=0
  186. THEN
  187. Concat(taicpu.op_reg_ref(A_ST,TCGSize2OpSize[size],R_G0,ref))
  188. ELSE
  189. BEGIN
  190. a_load_const_reg(list,size,a,R_G1);
  191. list.concat(taicpu.op_reg_ref(A_ST,TCGSize2OpSize[size],R_G1,ref));
  192. END;
  193. END;
  194. PROCEDURE tcgSPARC.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;CONST ref:TReference);
  195. BEGIN
  196. list.concat(taicpu.op_reg_ref(A_LD,TCGSize2OpSize[size],reg,ref));
  197. END;
  198. PROCEDURE tcgSPARC.a_load_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);
  199. VAR
  200. op:tasmop;
  201. s:topsize;
  202. begin
  203. sizes2load(size,S_L,op,s);
  204. list.concat(taicpu.op_ref_reg(op,s,ref,reg));
  205. end;
  206. PROCEDURE tcgSPARC.a_load_reg_reg(list:TAasmOutput;fromsize,size:tcgsize;reg1,reg2:tregister);
  207. var
  208. op:tasmop;
  209. s:topsize;
  210. begin
  211. sizes2load(size,S_L,op,s);
  212. if ((reg1) = (reg2)) then
  213. begin
  214. { "mov reg1, reg1" doesn't make sense }
  215. if op = A_NONE then
  216. exit;
  217. { optimize movzx with "and ffff,<reg>" operation }
  218. //if (op = A_NONEZX) then
  219. begin
  220. case size of
  221. OS_8:
  222. begin
  223. list.concat(taicpu.op_const_reg(A_AND,S_L,255,reg2));
  224. exit;
  225. end;
  226. OS_16:
  227. begin
  228. list.concat(taicpu.op_const_reg(A_AND,S_L,65535,reg2));
  229. exit;
  230. end;
  231. end;
  232. end;
  233. end;
  234. list.concat(taicpu.op_reg_reg(op,s,reg1,reg2));
  235. end;
  236. { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
  237. { R_ST means "the current value at the top of the fpu stack" (JM) }
  238. PROCEDURE tcgSPARC.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  239. begin
  240. if NOT (reg1 IN [R_F0..R_F31]) then
  241. begin
  242. list.concat(taicpu.op_reg(A_NONE,S_NO,
  243. trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset)));
  244. inc(trgcpu(rg).fpuvaroffset);
  245. end;
  246. if NOT (reg2 IN [R_F0..R_F31]) then
  247. begin
  248. list.concat(taicpu.op_reg(A_JMPL,S_NO,
  249. trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset)));
  250. dec(trgcpu(rg).fpuvaroffset);
  251. end;
  252. end;
  253. PROCEDURE tcgSPARC.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);
  254. begin
  255. floatload(list,size,ref);
  256. { if (reg <> R_ST) then
  257. a_loadfpu_reg_reg(list,R_ST,reg);}
  258. end;
  259. PROCEDURE tcgSPARC.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);
  260. begin
  261. { if reg <> R_ST then
  262. a_loadfpu_reg_reg(list,reg,R_ST);}
  263. floatstore(list,size,ref);
  264. end;
  265. PROCEDURE tcgSPARC.a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  266. begin
  267. // list.concat(taicpu.op_reg_reg(A_NONEQ,S_NO,reg1,reg2));
  268. end;
  269. PROCEDURE tcgSPARC.a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);
  270. begin
  271. // list.concat(taicpu.op_ref_reg(A_NONEQ,S_NO,ref,reg));
  272. end;
  273. PROCEDURE tcgSPARC.a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);
  274. begin
  275. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,ref));
  276. end;
  277. PROCEDURE tcgSPARC.a_parammm_reg(list:TAasmOutput;reg:tregister);
  278. VAR
  279. href:TReference;
  280. BEGIN
  281. // list.concat(taicpu.op_const_reg(A_SUB,S_L,8,R_RSP));
  282. // reference_reset_base(href,R_ESP,0);
  283. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,href));
  284. END;
  285. PROCEDURE tcgSPARC.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);
  286. var
  287. opcode:tasmop;
  288. power:LongInt;
  289. begin
  290. (* Case Op of
  291. OP_DIV, OP_IDIV:
  292. Begin
  293. if ispowerof2(a,power) then
  294. begin
  295. case op of
  296. OP_DIV:
  297. opcode := A_SHR;
  298. OP_IDIV:
  299. opcode := A_SAR;
  300. end;
  301. list.concat(taicpu.op_const_reg(opcode,S_L,power,
  302. reg));
  303. exit;
  304. end;
  305. { the rest should be handled specifically in the code }
  306. { generator because of the silly register usage restraints }
  307. internalerror(200109224);
  308. End;
  309. OP_MUL,OP_IMUL:
  310. begin
  311. if not(cs_check_overflow in aktlocalswitches) and
  312. ispowerof2(a,power) then
  313. begin
  314. list.concat(taicpu.op_const_reg(A_SHL,S_L,power,
  315. reg));
  316. exit;
  317. end;
  318. if op = OP_IMUL then
  319. list.concat(taicpu.op_const_reg(A_IMUL,S_L,
  320. a,reg))
  321. else
  322. { OP_MUL should be handled specifically in the code }
  323. { generator because of the silly register usage restraints }
  324. internalerror(200109225);
  325. end;
  326. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  327. if not(cs_check_overflow in aktlocalswitches) and
  328. (a = 1) and
  329. (op in [OP_ADD,OP_SUB]) then
  330. if op = OP_ADD then
  331. list.concat(taicpu.op_reg(A_INC,S_L,reg))
  332. else
  333. list.concat(taicpu.op_reg(A_DEC,S_L,reg))
  334. else if (a = 0) then
  335. if (op <> OP_AND) then
  336. exit
  337. else
  338. list.concat(taicpu.op_const_reg(A_NONE,S_L,0,reg))
  339. else if (a = high(aword)) and
  340. (op in [OP_AND,OP_OR,OP_XOR]) then
  341. begin
  342. case op of
  343. OP_AND:
  344. exit;
  345. OP_OR:
  346. list.concat(taicpu.op_const_reg(A_NONE,S_L,high(aword),reg));
  347. OP_XOR:
  348. list.concat(taicpu.op_reg(A_NOT,S_L,reg));
  349. end
  350. end
  351. else
  352. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],S_L,
  353. a,reg));
  354. OP_SHL,OP_SHR,OP_SAR:
  355. begin
  356. if (a and 31) <> 0 Then
  357. list.concat(taicpu.op_const_reg(
  358. TOpCG2AsmOp[op],S_L,a and 31,reg));
  359. if (a shr 5) <> 0 Then
  360. internalerror(68991);
  361. end
  362. else internalerror(68992);
  363. end;*)
  364. end;
  365. PROCEDURE tcgSPARC.a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);
  366. var
  367. opcode:tasmop;
  368. power:LongInt;
  369. begin
  370. (* Case Op of
  371. OP_DIV, OP_IDIV:
  372. Begin
  373. if ispowerof2(a,power) then
  374. begin
  375. case op of
  376. OP_DIV:
  377. opcode := A_SHR;
  378. OP_IDIV:
  379. opcode := A_SAR;
  380. end;
  381. list.concat(taicpu.op_const_ref(opcode,
  382. TCgSize2OpSize[size],power,ref));
  383. exit;
  384. end;
  385. { the rest should be handled specifically in the code }
  386. { generator because of the silly register usage restraints }
  387. internalerror(200109231);
  388. End;
  389. OP_MUL,OP_IMUL:
  390. begin
  391. if not(cs_check_overflow in aktlocalswitches) and
  392. ispowerof2(a,power) then
  393. begin
  394. list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
  395. power,ref));
  396. exit;
  397. end;
  398. { can't multiply a memory location directly with a CONSTant }
  399. if op = OP_IMUL then
  400. inherited a_op_const_ref(list,op,size,a,ref)
  401. else
  402. { OP_MUL should be handled specifically in the code }
  403. { generator because of the silly register usage restraints }
  404. internalerror(200109232);
  405. end;
  406. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  407. if not(cs_check_overflow in aktlocalswitches) and
  408. (a = 1) and
  409. (op in [OP_ADD,OP_SUB]) then
  410. if op = OP_ADD then
  411. list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
  412. else
  413. list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
  414. else if (a = 0) then
  415. if (op <> OP_AND) then
  416. exit
  417. else
  418. a_load_const_ref(list,size,0,ref)
  419. else if (a = high(aword)) and
  420. (op in [OP_AND,OP_OR,OP_XOR]) then
  421. begin
  422. case op of
  423. OP_AND:
  424. exit;
  425. OP_OR:
  426. list.concat(taicpu.op_const_ref(A_NONE,TCgSize2OpSize[size],high(aword),ref));
  427. OP_XOR:
  428. list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref));
  429. end
  430. end
  431. else
  432. list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
  433. TCgSize2OpSize[size],a,ref));
  434. OP_SHL,OP_SHR,OP_SAR:
  435. begin
  436. if (a and 31) <> 0 Then
  437. list.concat(taicpu.op_const_ref(
  438. TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
  439. if (a shr 5) <> 0 Then
  440. internalerror(68991);
  441. end
  442. else internalerror(68992);
  443. end;*)
  444. end;
  445. PROCEDURE tcgSPARC.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  446. var
  447. regloadsize:tcgsize;
  448. dstsize:topsize;
  449. tmpreg:tregister;
  450. popecx:boolean;
  451. begin
  452. (* dstsize := S_Q{makeregsize(dst,size)};
  453. case op of
  454. OP_NEG,OP_NOT:
  455. begin
  456. if src <> R_NO then
  457. internalerror(200112291);
  458. list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
  459. end;
  460. OP_MUL,OP_DIV,OP_IDIV:
  461. { special stuff, needs separate handling inside code }
  462. { generator }
  463. internalerror(200109233);
  464. OP_SHR,OP_SHL,OP_SAR:
  465. begin
  466. tmpreg := R_NO;
  467. { we need cl to hold the shift count, so if the destination }
  468. { is ecx, save it to a temp for now }
  469. if dst in [R_ECX,R_CX,R_CL] then
  470. begin
  471. case S_L of
  472. S_B:regloadsize := OS_8;
  473. S_W:regloadsize := OS_16;
  474. else regloadsize := OS_32;
  475. end;
  476. tmpreg := get_scratch_reg(list);
  477. a_load_reg_reg(list,regloadsize,OS_32,src,tmpreg);
  478. end;
  479. if not(src in [R_ECX,R_CX,R_CL]) then
  480. begin
  481. { is ecx still free (it's also free if it was allocated }
  482. { to dst, since we've moved dst somewhere else already) }
  483. if not((dst = R_ECX) or
  484. ((R_ECX in rg.unusedregsint) and
  485. { this will always be true, it's just here to }
  486. { allocate ecx }
  487. (rg.getexplicitregisterint(list,R_ECX) = R_ECX))) then
  488. begin
  489. list.concat(taicpu.op_reg(A_NONE,S_L,R_ECX));
  490. popecx := true;
  491. end;
  492. a_load_reg_reg(list,OS_8,OS_8,(src),R_CL);
  493. end
  494. else
  495. src := R_CL;
  496. { do the shift }
  497. if tmpreg = R_NO then
  498. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  499. R_CL,dst))
  500. else
  501. begin
  502. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],S_L,
  503. R_CL,tmpreg));
  504. { move result back to the destination }
  505. a_load_reg_reg(list,OS_32,OS_32,tmpreg,R_ECX);
  506. free_scratch_reg(list,tmpreg);
  507. end;
  508. if popecx then
  509. list.concat(taicpu.op_reg(A_POP,S_L,R_ECX))
  510. else if not (dst in [R_ECX,R_CX,R_CL]) then
  511. rg.ungetregisterint(list,R_ECX);
  512. end;
  513. else
  514. begin
  515. if S_L <> dstsize then
  516. internalerror(200109226);
  517. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  518. src,dst));
  519. end;
  520. end;*)
  521. end;
  522. PROCEDURE tcgSPARC.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);
  523. var
  524. opsize:topsize;
  525. begin
  526. (* case op of
  527. OP_NEG,OP_NOT,OP_IMUL:
  528. begin
  529. inherited a_op_ref_reg(list,op,size,ref,reg);
  530. end;
  531. OP_MUL,OP_DIV,OP_IDIV:
  532. { special stuff, needs separate handling inside code }
  533. { generator }
  534. internalerror(200109239);
  535. else
  536. begin
  537. opsize := S_Q{makeregsize(reg,size)};
  538. list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,ref,reg));
  539. end;
  540. end;*)
  541. end;
  542. PROCEDURE tcgSPARC.a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);
  543. var
  544. opsize:topsize;
  545. begin
  546. (* case op of
  547. OP_NEG,OP_NOT:
  548. begin
  549. if reg <> R_NO then
  550. internalerror(200109237);
  551. list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
  552. end;
  553. OP_IMUL:
  554. begin
  555. { this one needs a load/imul/store, which is the default }
  556. inherited a_op_ref_reg(list,op,size,ref,reg);
  557. end;
  558. OP_MUL,OP_DIV,OP_IDIV:
  559. { special stuff, needs separate handling inside code }
  560. { generator }
  561. internalerror(200109238);
  562. else
  563. begin
  564. opsize := tcgsize2opsize[size];
  565. list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref));
  566. end;
  567. end;*)
  568. end;
  569. PROCEDURE tcgSPARC.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;
  570. size:tcgsize;a:aword;src, dst:tregister);
  571. var
  572. tmpref:TReference;
  573. power:LongInt;
  574. opsize:topsize;
  575. begin
  576. opsize := S_L;
  577. if (opsize <> S_L) or
  578. not (size in [OS_32,OS_S32]) then
  579. begin
  580. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  581. exit;
  582. end;
  583. { if we get here, we have to do a 32 bit calculation, guaranteed }
  584. Case Op of
  585. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  586. OP_SAR:
  587. { can't do anything special for these }
  588. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  589. OP_IMUL:
  590. begin
  591. if not(cs_check_overflow in aktlocalswitches) and
  592. ispowerof2(a,power) then
  593. { can be done with a shift }
  594. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  595. list.concat(taicpu.op_reg_const_reg(A_SMUL,S_L,src,a,dst));
  596. end;
  597. OP_ADD, OP_SUB:
  598. if (a = 0) then
  599. a_load_reg_reg(list,size,size,src,dst)
  600. else
  601. begin
  602. reference_reset(tmpref);
  603. tmpref.base := src;
  604. tmpref.offset := LongInt(a);
  605. if op = OP_SUB then
  606. tmpref.offset := -tmpref.offset;
  607. list.concat(taicpu.op_ref_reg(A_NONE,S_L,tmpref,dst));
  608. end
  609. else internalerror(200112302);
  610. end;
  611. end;
  612. PROCEDURE tcgSPARC.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;
  613. size:tcgsize;src1, src2, dst:tregister);
  614. var
  615. tmpref:TReference;
  616. opsize:topsize;
  617. begin
  618. opsize := S_L;
  619. if (opsize <> S_L) or
  620. (S_L <> S_L) or
  621. not (size in [OS_32,OS_S32]) then
  622. begin
  623. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  624. exit;
  625. end;
  626. { if we get here, we have to do a 32 bit calculation, guaranteed }
  627. Case Op of
  628. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  629. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  630. { can't do anything special for these }
  631. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  632. OP_IMUL:
  633. list.concat(taicpu.op_reg_reg_reg(A_SMUL,S_L,src1,src2,dst));
  634. OP_ADD:
  635. begin
  636. reference_reset(tmpref);
  637. tmpref.base := src1;
  638. tmpref.index := src2;
  639. tmpref.scalefactor := 1;
  640. list.concat(taicpu.op_ref_reg(A_NONE,S_L,tmpref,dst));
  641. end
  642. else internalerror(200112303);
  643. end;
  644. end;
  645. {*************** compare instructructions ****************}
  646. PROCEDURE tcgSPARC.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;
  647. l:tasmlabel);
  648. begin
  649. if (a = 0) then
  650. list.concat(taicpu.op_reg_reg(A_CMP,S_L,reg,reg))
  651. else
  652. list.concat(taicpu.op_const_reg(A_CMP,S_L,a,reg));
  653. a_jmp_cond(list,cmp_op,l);
  654. end;
  655. PROCEDURE tcgSPARC.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;
  656. l:tasmlabel);
  657. begin
  658. list.concat(taicpu.op_const_ref(A_CMP,TCgSize2OpSize[size],a,ref));
  659. a_jmp_cond(list,cmp_op,l);
  660. end;
  661. PROCEDURE tcgSPARC.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;
  662. reg1,reg2:tregister;l:tasmlabel);
  663. begin
  664. { if regsize(reg1) <> S_L then
  665. internalerror(200109226);
  666. list.concat(taicpu.op_reg_reg(A_CMP,regsize(reg1),reg1,reg2));
  667. a_jmp_cond(list,cmp_op,l);}
  668. end;
  669. PROCEDURE tcgSPARC.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);
  670. var
  671. opsize:topsize;
  672. begin
  673. opsize := S_Q{makeregsize(reg,size)};
  674. list.concat(taicpu.op_ref_reg(A_CMP,opsize,ref,reg));
  675. a_jmp_cond(list,cmp_op,l);
  676. end;
  677. PROCEDURE tcgSPARC.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);
  678. var
  679. ai:taicpu;
  680. begin
  681. if cond=OC_None then
  682. ai := Taicpu.Op_sym(A_JMPL,S_NO,l)
  683. else
  684. begin
  685. ai:=Taicpu.Op_sym(A_JMPL,S_NO,l);
  686. ai.SetCondition(TOpCmp2AsmCond[cond]);
  687. end;
  688. ai.is_jmp:=true;
  689. list.concat(ai);
  690. end;
  691. PROCEDURE tcgSPARC.a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);
  692. var
  693. ai:taicpu;
  694. begin
  695. ai := Taicpu.op_sym(A_JMPL,S_NO,l);
  696. ai.SetCondition(flags_to_cond(f));
  697. ai.is_jmp := true;
  698. list.concat(ai);
  699. end;
  700. PROCEDURE tcgSPARC.g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);
  701. VAR
  702. ai:taicpu;
  703. hreg:tregister;
  704. BEGIN
  705. hreg := rg.makeregsize(reg,OS_8);
  706. // ai:=Taicpu.Op_reg(A_Setcc,S_B,hreg);
  707. ai.SetCondition(flags_to_cond(f));
  708. list.concat(ai);
  709. IF hreg<>reg
  710. THEN
  711. a_load_reg_reg(list,OS_8,OS_8,hreg,reg);
  712. END;
  713. { *********** entry/exit code and address loading ************ }
  714. procedure tcgSPARC.g_stackframe_entry(list:TAasmOutput;localsize:LongInt);
  715. var
  716. href:TReference;
  717. i:integer;
  718. again:tasmlabel;
  719. begin
  720. {According the the SPARC ABI the standard stack frame must include :
  721. * 16 word save for the in and local registers in case of overflow/underflow.
  722. this save area always must exist at the %o6+0,
  723. * software conventions requires space for the aggregate return value pointer, even if the word is not used,
  724. * althogh the first six words of arguments reside in registers, the standard
  725. stack frame reserves space for them. Arguments beond the sixth reside on the
  726. stack as in the Intel architecture,
  727. * other areas depend on the compiler and the code being compiled. The
  728. standard calling sequence does not define a maximum stack frame size, nor does
  729. it restrict how a language system uses the "unspecified" areas of the standard
  730. stack frame.}
  731. Dec(LocalSize,(16+1+5)*4);
  732. {Althogh the SPARC architecture require only word alignment, software
  733. convention and the operating system require every stack frame to be double word
  734. aligned}
  735. if(LocalSize and $00000003)<>0
  736. then
  737. LocalSize:=(LocalSize and $FFFFFFFC)+4;
  738. {Execute the SAVE instruction to get a new register window and get a new stack
  739. frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state before
  740. execution of the SAVE instrucion so it is the caller %i6, when the %i6 after
  741. execution of that instrucion is the called function stack pointer}
  742. with list do
  743. concat(Taicpu.Op_reg_const_reg(A_SAVE,S_L,Stack_Pointer_Reg,localsize,Stack_Pointer_Reg));
  744. end;
  745. procedure tcgSPARC.g_restore_frame_pointer(list:TAasmOutput);
  746. begin
  747. {This function intontionally does nothing as frame pointer is restored in the
  748. delay slot of the return instrucion done in g_return_from_proc}
  749. end;
  750. procedure tcgSPARC.g_return_from_proc(list:TAasmOutput;parasize:aword);
  751. var
  752. RetReference:TReference;
  753. begin
  754. {According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  755. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  756. RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  757. delay slot, so an inversion is possible such as
  758. JMPL %i6+8,%g0
  759. RESTORE %g0,0,%g0
  760. If no inversion we can use just
  761. RESTORE %g0,0,%g0
  762. JMPL %i6+8,%g0
  763. NOP}
  764. with list do
  765. begin
  766. {Return address is computed by adding 8 to the CALL address saved onto %i6}
  767. reference_reset_base(RetReference,R_I7,8);
  768. concat(Taicpu.Op_ref_reg(A_JMPL,S_L,RetReference,R_G0));
  769. {We use trivial restore in the delay slot of the JMPL instruction, as we
  770. already set result onto %i0}
  771. concat(Taicpu.Op_reg_const_reg(A_RESTORE,S_L,R_G0,0,R_G0));
  772. end
  773. end;
  774. PROCEDURE tcgSPARC.a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);
  775. begin
  776. // list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,r));
  777. end;
  778. { ************* 64bit operations ************ }
  779. PROCEDURE TCg64fSPARC.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  780. begin
  781. case op of
  782. OP_ADD :
  783. begin
  784. op1:=A_ADD;
  785. op2:=A_ADD;
  786. end;
  787. OP_SUB :
  788. begin
  789. op1:=A_SUB;
  790. op2:=A_SUB;
  791. end;
  792. OP_XOR :
  793. begin
  794. op1:=A_XOR;
  795. op2:=A_XOR;
  796. end;
  797. OP_OR :
  798. begin
  799. op1:=A_OR;
  800. op2:=A_OR;
  801. end;
  802. OP_AND :
  803. begin
  804. op1:=A_AND;
  805. op2:=A_AND;
  806. end;
  807. else
  808. internalerror(200203241);
  809. end;
  810. end;
  811. PROCEDURE TCg64fSPARC.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);
  812. var
  813. op1,op2:TAsmOp;
  814. tempref:TReference;
  815. begin
  816. get_64bit_ops(op,op1,op2);
  817. list.concat(taicpu.op_ref_reg(op1,S_L,ref,reg.reglo));
  818. tempref:=ref;
  819. inc(tempref.offset,4);
  820. list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
  821. end;
  822. PROCEDURE TCg64fSPARC.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  823. var
  824. op1,op2:TAsmOp;
  825. begin
  826. get_64bit_ops(op,op1,op2);
  827. list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
  828. list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
  829. end;
  830. PROCEDURE TCg64fSPARC.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  831. var
  832. op1,op2:TAsmOp;
  833. begin
  834. case op of
  835. OP_AND,OP_OR,OP_XOR:
  836. WITH cg DO
  837. begin
  838. a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  839. a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  840. end;
  841. OP_ADD, OP_SUB:
  842. begin
  843. // can't use a_op_const_ref because this may use dec/inc
  844. get_64bit_ops(op,op1,op2);
  845. list.concat(taicpu.op_const_reg(op1,S_L,Lo(Value),regdst.reglo));
  846. list.concat(taicpu.op_const_reg(op2,S_L,Hi(Value),regdst.reghi));
  847. end;
  848. else
  849. internalerror(200204021);
  850. end;
  851. end;
  852. PROCEDURE TCg64fSPARC.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);
  853. var
  854. op1,op2:TAsmOp;
  855. tempref:TReference;
  856. begin
  857. case op of
  858. OP_AND,OP_OR,OP_XOR:
  859. WITH cg DO
  860. begin
  861. a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  862. tempref:=ref;
  863. inc(tempref.offset,4);
  864. a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  865. end;
  866. OP_ADD, OP_SUB:
  867. begin
  868. get_64bit_ops(op,op1,op2);
  869. // can't use a_op_const_ref because this may use dec/inc
  870. list.concat(taicpu.op_const_ref(op1,S_L,Lo(Value),ref));
  871. tempref:=ref;
  872. inc(tempref.offset,4);
  873. list.concat(taicpu.op_const_ref(op2,S_L,Hi(Value),tempref));
  874. end;
  875. else
  876. internalerror(200204022);
  877. end;
  878. end;
  879. { ************* concatcopy ************ }
  880. PROCEDURE tcgSPARC.g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);
  881. { temp implementation, until it's permanenty moved here from cga.pas }
  882. var
  883. oldlist:TAasmOutput;
  884. begin
  885. if list <> exprasmlist then
  886. begin
  887. oldlist := exprasmlist;
  888. exprasmlist := list;
  889. end;
  890. // cga.concatcopy(source,dest,len,delsource,loadref);
  891. if list <> exprasmlist then
  892. list := oldlist;
  893. end;
  894. function tcgSPARC.reg_cgsize(CONST reg:tregister):tcgsize;
  895. // CONST
  896. // regsize_2_cgsize:array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32);
  897. begin
  898. //result := regsize_2_cgsize[S_L];
  899. end;
  900. {***************** This is private property, keep out! :) *****************}
  901. PROCEDURE tcgSPARC.sizes2load(s1:tcgsize;s2:topsize;VAR op:tasmop;VAR s3:topsize);
  902. BEGIN
  903. { case s2 of
  904. S_B:
  905. if S1 in [OS_8,OS_S8] then
  906. s3 := S_B
  907. else internalerror(200109221);
  908. S_W:
  909. case s1 of
  910. OS_8,OS_S8:
  911. s3 := S_BW;
  912. OS_16,OS_S16:
  913. s3 := S_W;
  914. else internalerror(200109222);
  915. end;
  916. S_L:
  917. case s1 of
  918. OS_8,OS_S8:
  919. s3 := S_BL;
  920. OS_16,OS_S16:
  921. s3 := S_WL;
  922. OS_32,OS_S32:
  923. s3 := S_L;
  924. else internalerror(200109223);
  925. end;
  926. else internalerror(200109227);
  927. end;
  928. if s3 in [S_B,S_W,S_L] then
  929. op := A_NONE
  930. else if s1 in [OS_8,OS_16,OS_32] then
  931. op := A_NONEZX
  932. else
  933. op := A_NONESX;}
  934. END;
  935. PROCEDURE tcgSPARC.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize);
  936. BEGIN
  937. (* case t of
  938. OS_F32:begin
  939. op:=A_FLD;
  940. s:=S_FS;
  941. end;
  942. OS_F64:begin
  943. op:=A_FLD;
  944. { ???? }
  945. s:=S_FL;
  946. end;
  947. OS_F80:begin
  948. op:=A_FLD;
  949. s:=S_FX;
  950. end;
  951. OS_C64:begin
  952. op:=A_FILD;
  953. s:=S_IQ;
  954. end;
  955. else internalerror(17);
  956. end;*)
  957. END;
  958. PROCEDURE tcgSPARC.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  959. VAR
  960. op:tasmop;
  961. s:topsize;
  962. BEGIN
  963. floatloadops(t,op,s);
  964. list.concat(Taicpu.Op_ref(op,s,ref));
  965. inc(trgcpu(rg).fpuvaroffset);
  966. END;
  967. PROCEDURE tcgSPARC.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  968. BEGIN
  969. { case t of
  970. OS_F32:begin
  971. op:=A_FSTP;
  972. s:=S_FS;
  973. end;
  974. OS_F64:begin
  975. op:=A_FSTP;
  976. s:=S_FL;
  977. end;
  978. OS_F80:begin
  979. op:=A_FSTP;
  980. s:=S_FX;
  981. end;
  982. OS_C64:begin
  983. op:=A_FISTP;
  984. s:=S_IQ;
  985. end;
  986. else
  987. internalerror(17);
  988. end;}
  989. end;
  990. PROCEDURE tcgSPARC.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  991. VAR
  992. op:tasmop;
  993. s:topsize;
  994. BEGIN
  995. floatstoreops(t,op,s);
  996. list.concat(Taicpu.Op_ref(op,s,ref));
  997. dec(trgcpu(rg).fpuvaroffset);
  998. END;
  999. BEGIN
  1000. cg:=tcgSPARC.create;
  1001. END.
  1002. {
  1003. $Log$
  1004. Revision 1.8 2002-10-01 21:35:58 mazen
  1005. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1006. Revision 1.7 2002/10/01 21:06:29 mazen
  1007. attinst.inc --> strinst.inc
  1008. Revision 1.6 2002/10/01 17:41:50 florian
  1009. * fixed log and id
  1010. }