cgcpu.pas 38 KB

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