cgcpu.pas 47 KB

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