cgcpu.pas 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  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;fromsize,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_LD,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_LD,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_LD,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_LD,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_LD,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_LD,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_LD,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_LD,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;fromsize,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,regloadsize,OS_32,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_NONE,S_L,R_ECX));
  488. popecx := true;
  489. end;
  490. a_load_reg_reg(list,OS_8,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,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,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,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. {Reserve space to save register window in case of overflow/underflow}
  719. Inc(LocalSize,16);{located between %o6 and %o6+15}
  720. WITH list DO
  721. concat(Taicpu.Op_reg_const_reg(A_SAVE,S_L,Stack_Pointer_Reg,localsize,Stack_Pointer_Reg));
  722. END;
  723. PROCEDURE tcgSPARC.g_restore_frame_pointer(list:TAasmOutput);
  724. BEGIN
  725. list.concat(Taicpu.Op_none(A_RESTORE,S_NO));
  726. END;
  727. PROCEDURE tcgSPARC.g_return_from_proc(list:TAasmOutput;parasize:aword);
  728. BEGIN
  729. { Routines with the poclearstack flag set use only a ret }
  730. { also routines with parasize=0 }
  731. WITH List DO
  732. (*IF(po_clearstack IN aktprocdef.procoptions)
  733. THEN
  734. { complex return values are removed from stack in C code PM }
  735. IF ret_in_param(aktprocdef.rettype.def)
  736. THEN
  737. Concat(Taicpu.Op_const(A_RET,S_NO,4))
  738. ELSE
  739. Concat(Taicpu.Op_none(A_RET,S_NO))
  740. ELSE*)
  741. IF(parasize=0)
  742. THEN
  743. Concat(Taicpu.Op_none(A_RET,S_NO))
  744. ELSE
  745. BEGIN
  746. { parameters are limited to 65535 bytes because }
  747. { ret allows only imm16 }
  748. IF(parasize>65535)
  749. THEN
  750. CGMessage(cg_e_parasize_too_big);
  751. Concat(Taicpu.Op_const(A_RET,S_NO,parasize));
  752. END;
  753. END;
  754. PROCEDURE tcgSPARC.a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);
  755. begin
  756. // list.concat(taicpu.op_ref_reg(A_LEA,S_L,ref,r));
  757. end;
  758. { ************* 64bit operations ************ }
  759. PROCEDURE TCg64fSPARC.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  760. begin
  761. case op of
  762. OP_ADD :
  763. begin
  764. op1:=A_ADD;
  765. op2:=A_ADD;
  766. end;
  767. OP_SUB :
  768. begin
  769. op1:=A_SUB;
  770. op2:=A_SUB;
  771. end;
  772. OP_XOR :
  773. begin
  774. op1:=A_XOR;
  775. op2:=A_XOR;
  776. end;
  777. OP_OR :
  778. begin
  779. op1:=A_OR;
  780. op2:=A_OR;
  781. end;
  782. OP_AND :
  783. begin
  784. op1:=A_AND;
  785. op2:=A_AND;
  786. end;
  787. else
  788. internalerror(200203241);
  789. end;
  790. end;
  791. PROCEDURE TCg64fSPARC.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);
  792. var
  793. op1,op2:TAsmOp;
  794. tempref:TReference;
  795. begin
  796. get_64bit_ops(op,op1,op2);
  797. list.concat(taicpu.op_ref_reg(op1,S_L,ref,reg.reglo));
  798. tempref:=ref;
  799. inc(tempref.offset,4);
  800. list.concat(taicpu.op_ref_reg(op2,S_L,tempref,reg.reghi));
  801. end;
  802. PROCEDURE TCg64fSPARC.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  803. var
  804. op1,op2:TAsmOp;
  805. begin
  806. get_64bit_ops(op,op1,op2);
  807. list.concat(taicpu.op_reg_reg(op1,S_L,regsrc.reglo,regdst.reglo));
  808. list.concat(taicpu.op_reg_reg(op2,S_L,regsrc.reghi,regdst.reghi));
  809. end;
  810. PROCEDURE TCg64fSPARC.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  811. var
  812. op1,op2:TAsmOp;
  813. begin
  814. case op of
  815. OP_AND,OP_OR,OP_XOR:
  816. WITH cg DO
  817. begin
  818. a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  819. a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  820. end;
  821. OP_ADD, OP_SUB:
  822. begin
  823. // can't use a_op_const_ref because this may use dec/inc
  824. get_64bit_ops(op,op1,op2);
  825. list.concat(taicpu.op_const_reg(op1,S_L,Lo(Value),regdst.reglo));
  826. list.concat(taicpu.op_const_reg(op2,S_L,Hi(Value),regdst.reghi));
  827. end;
  828. else
  829. internalerror(200204021);
  830. end;
  831. end;
  832. PROCEDURE TCg64fSPARC.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);
  833. var
  834. op1,op2:TAsmOp;
  835. tempref:TReference;
  836. begin
  837. case op of
  838. OP_AND,OP_OR,OP_XOR:
  839. WITH cg DO
  840. begin
  841. a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  842. tempref:=ref;
  843. inc(tempref.offset,4);
  844. a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  845. end;
  846. OP_ADD, OP_SUB:
  847. begin
  848. get_64bit_ops(op,op1,op2);
  849. // can't use a_op_const_ref because this may use dec/inc
  850. list.concat(taicpu.op_const_ref(op1,S_L,Lo(Value),ref));
  851. tempref:=ref;
  852. inc(tempref.offset,4);
  853. list.concat(taicpu.op_const_ref(op2,S_L,Hi(Value),tempref));
  854. end;
  855. else
  856. internalerror(200204022);
  857. end;
  858. end;
  859. { ************* concatcopy ************ }
  860. PROCEDURE tcgSPARC.g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);
  861. { temp implementation, until it's permanenty moved here from cga.pas }
  862. var
  863. oldlist:TAasmOutput;
  864. begin
  865. if list <> exprasmlist then
  866. begin
  867. oldlist := exprasmlist;
  868. exprasmlist := list;
  869. end;
  870. // cga.concatcopy(source,dest,len,delsource,loadref);
  871. if list <> exprasmlist then
  872. list := oldlist;
  873. end;
  874. function tcgSPARC.reg_cgsize(CONST reg:tregister):tcgsize;
  875. // CONST
  876. // regsize_2_cgsize:array[S_B..S_L] of tcgsize = (OS_8,OS_16,OS_32);
  877. begin
  878. //result := regsize_2_cgsize[S_L];
  879. end;
  880. {***************** This is private property, keep out! :) *****************}
  881. PROCEDURE tcgSPARC.sizes2load(s1:tcgsize;s2:topsize;VAR op:tasmop;VAR s3:topsize);
  882. BEGIN
  883. { case s2 of
  884. S_B:
  885. if S1 in [OS_8,OS_S8] then
  886. s3 := S_B
  887. else internalerror(200109221);
  888. S_W:
  889. case s1 of
  890. OS_8,OS_S8:
  891. s3 := S_BW;
  892. OS_16,OS_S16:
  893. s3 := S_W;
  894. else internalerror(200109222);
  895. end;
  896. S_L:
  897. case s1 of
  898. OS_8,OS_S8:
  899. s3 := S_BL;
  900. OS_16,OS_S16:
  901. s3 := S_WL;
  902. OS_32,OS_S32:
  903. s3 := S_L;
  904. else internalerror(200109223);
  905. end;
  906. else internalerror(200109227);
  907. end;
  908. if s3 in [S_B,S_W,S_L] then
  909. op := A_NONE
  910. else if s1 in [OS_8,OS_16,OS_32] then
  911. op := A_NONEZX
  912. else
  913. op := A_NONESX;}
  914. END;
  915. PROCEDURE tcgSPARC.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize);
  916. BEGIN
  917. (* case t of
  918. OS_F32:begin
  919. op:=A_FLD;
  920. s:=S_FS;
  921. end;
  922. OS_F64:begin
  923. op:=A_FLD;
  924. { ???? }
  925. s:=S_FL;
  926. end;
  927. OS_F80:begin
  928. op:=A_FLD;
  929. s:=S_FX;
  930. end;
  931. OS_C64:begin
  932. op:=A_FILD;
  933. s:=S_IQ;
  934. end;
  935. else internalerror(17);
  936. end;*)
  937. END;
  938. PROCEDURE tcgSPARC.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  939. VAR
  940. op:tasmop;
  941. s:topsize;
  942. BEGIN
  943. floatloadops(t,op,s);
  944. list.concat(Taicpu.Op_ref(op,s,ref));
  945. inc(trgcpu(rg).fpuvaroffset);
  946. END;
  947. PROCEDURE tcgSPARC.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  948. BEGIN
  949. { case t of
  950. OS_F32:begin
  951. op:=A_FSTP;
  952. s:=S_FS;
  953. end;
  954. OS_F64:begin
  955. op:=A_FSTP;
  956. s:=S_FL;
  957. end;
  958. OS_F80:begin
  959. op:=A_FSTP;
  960. s:=S_FX;
  961. end;
  962. OS_C64:begin
  963. op:=A_FISTP;
  964. s:=S_IQ;
  965. end;
  966. else
  967. internalerror(17);
  968. end;}
  969. end;
  970. PROCEDURE tcgSPARC.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  971. VAR
  972. op:tasmop;
  973. s:topsize;
  974. BEGIN
  975. floatstoreops(t,op,s);
  976. list.concat(Taicpu.Op_ref(op,s,ref));
  977. dec(trgcpu(rg).fpuvaroffset);
  978. END;
  979. BEGIN
  980. cg:=tcgSPARC.create;
  981. END.