cgcpu.pas 47 KB

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