cgcpu.pas 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350
  1. {******************************************************************************
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This program is free software;you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation;either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY;without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program;if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. *****************************************************************************}
  16. UNIT cgcpu;
  17. {This unit implements the code generator for the SPARC architecture}
  18. {$INCLUDE fpcdefs.inc}
  19. INTERFACE
  20. USES
  21. cginfo,cgbase,cgobj,cg64f32,
  22. aasmbase,aasmtai,aasmcpu,
  23. cpubase,cpuinfo,cpupara,
  24. node,symconst;
  25. TYPE
  26. tcgSPARC=CLASS(tcg)
  27. {This method is used to pass a parameter, which is located in a register, to a
  28. routine. It should give the parameter to the routine, as required by the
  29. specific processor ABI. It is overriden for each CPU target.
  30. Size : is the size of the operand in the register
  31. r : is the register source of the operand
  32. LocPara : is the location where the parameter will be stored}
  33. procedure a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;const LocPara:TParaLocation);override;
  34. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);override;
  35. procedure a_param_ref(list:TAasmOutput;size:tcgsize;CONST r:TReference;CONST LocPara:TParaLocation);override;
  36. procedure a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);override;
  37. procedure a_call_name(list:TAasmOutput;CONST s:string);override;
  38. procedure a_call_ref(list:TAasmOutput;CONST ref:TReference);override;
  39. {Branch Instruction}
  40. procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
  41. {General purpose instyructions}
  42. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override;
  43. procedure a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);override;
  44. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  45. procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);override;
  46. procedure a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);override;
  47. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  48. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  49. { move instructions }
  50. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  51. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);override;
  52. procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  53. procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  54. procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override;
  55. procedure a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);override;
  56. { fpu move instructions }
  57. procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  58. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  59. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  60. { vector register move instructions }
  61. procedure a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  62. procedure a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);override;
  63. procedure a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);override;
  64. procedure a_parammm_reg(list:TAasmOutput;reg:tregister);override;
  65. { comparison operations }
  66. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  67. procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;l:tasmlabel);override;
  68. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  69. procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);override;
  70. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  71. procedure a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);override;
  72. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);override;
  73. procedure g_overflowCheck(List:TAasmOutput;const p:TNode);override;
  74. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  75. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  76. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  77. procedure g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  78. class function reg_cgsize(CONST reg:tregister):tcgsize;override;
  79. PRIVATE
  80. function IsSimpleRef(const ref:treference):boolean;
  81. procedure sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  82. procedure floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  83. procedure floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  84. procedure floatloadops(t:tcgsize;var op:tasmop;var s:topsize);
  85. procedure floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  86. END;
  87. TCg64fSPARC=class(tcg64f32)
  88. procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);override;
  89. procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override;
  90. procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override;
  91. procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);override;
  92. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  93. END;
  94. CONST
  95. 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);
  96. 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);
  97. TCGSize2OpSize:ARRAY[tcgsize]OF TOpSize=(S_NO,S_B,S_W,S_SW,S_SW,S_B,S_W,S_SW,S_SW,S_FS,S_FD,S_FQ,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO,S_NO);
  98. IMPLEMENTATION
  99. USES
  100. globtype,globals,verbose,systems,cutils,
  101. symdef,symsym,defutil,paramgr,
  102. rgobj,tgobj,rgcpu,cpupi;
  103. { we implement the following routines because otherwise we can't }
  104. { instantiate the class since it's abstract }
  105. procedure tcgSPARC.a_param_reg(list:TAasmOutput;size:tcgsize;r:tregister;CONST LocPara:TParaLocation);
  106. BEGIN
  107. IF(Size<>OS_32)AND(Size<>OS_S32)
  108. THEN
  109. InternalError(2002032212);
  110. with list,LocPara do
  111. case Loc of
  112. LOC_REGISTER:
  113. if r<>Register
  114. then
  115. Concat(taicpu.op_Reg_Reg_Reg(A_OR,r,R_G0,Register));
  116. else
  117. InternalError(2002101002);
  118. end;
  119. end;
  120. procedure tcgSPARC.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);
  121. BEGIN
  122. with List do
  123. case Size of
  124. OS_32,OS_S32:
  125. Concat(taicpu.op_const(A_LD,a));
  126. OS_64,OS_S64:
  127. Concat(taicpu.op_const(A_LDD,a));
  128. else
  129. InternalError(2002032213);
  130. end;
  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_SW,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,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,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,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_SW,newasmsymbol(s)));
  200. concat(taicpu.op_none(A_NOP));
  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,ref));
  206. list.concat(taicpu.op_none(A_NOP));
  207. END;
  208. {********************** branch instructions ********************}
  209. procedure TCgSPARC.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
  210. begin
  211. List.Concat(TAiCpu.op_sym(A_BA,S_NO,objectlibrary.newasmsymbol(l.name)));
  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,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,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_ST,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_SW,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,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_SW,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_SW,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_SW,power,
  359. reg));
  360. exit;
  361. end;
  362. if op = OP_IMUL then
  363. list.concat(taicpu.op_const_reg(A_IMUL,S_SW,
  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_SW,reg))
  376. else
  377. list.concat(taicpu.op_reg(A_DEC,S_SW,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_SW,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_SW,high(aword),reg));
  391. OP_XOR:
  392. list.concat(taicpu.op_reg(A_NOT,S_SW,reg));
  393. end
  394. end
  395. else
  396. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],S_SW,
  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_SW,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_SW 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_SW,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_SW,
  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_SW,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_SW <> 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_SW;
  621. if (opsize <> S_SW) 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,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_SW;
  663. if (opsize <> S_SW) or
  664. (S_SW <> S_SW) 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,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_SW 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. procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const p:TNode);
  761. var
  762. hl:TAsmLabel;
  763. begin
  764. if not(cs_check_overflow in aktlocalswitches)
  765. then
  766. exit;
  767. objectlibrary.getlabel(hl);
  768. if not((p.resulttype.def.deftype=pointerdef) or
  769. ((p.resulttype.def.deftype=orddef) and
  770. (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  771. bool8bit,bool16bit,bool32bit])))
  772. then
  773. begin
  774. list.concat(taicpu.op_reg(A_NONE,R_NONE));
  775. a_jmp_always(list,hl)
  776. end
  777. else
  778. a_jmp_cond(list,OC_NONE,hl);
  779. a_call_name(list,'FPC_OVERFLOW');
  780. a_label(list,hl);
  781. end;
  782. { *********** entry/exit code and address loading ************ }
  783. procedure tcgSPARC.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
  784. var
  785. href:TReference;
  786. i:integer;
  787. again:tasmlabel;
  788. begin
  789. {Althogh the SPARC architecture require only word alignment, software
  790. convention and the operating system require every stack frame to be double word
  791. aligned}
  792. LocalSize:=(LocalSize+7)and $FFFFFFF8;
  793. {Execute the SAVE instruction to get a new register window and create a new
  794. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  795. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  796. after execution of that instruction is the called function stack pointer}
  797. with list do
  798. concat(Taicpu.Op_reg_const_reg(A_SAVE,Stack_Pointer_Reg,-LocalSize,Stack_Pointer_Reg));
  799. end;
  800. procedure tcgSPARC.g_restore_frame_pointer(list:TAasmOutput);
  801. begin
  802. {This function intontionally does nothing as frame pointer is restored in the
  803. delay slot of the return instrucion done in g_return_from_proc}
  804. end;
  805. procedure tcgSPARC.g_return_from_proc(list:TAasmOutput;parasize:aword);
  806. begin
  807. {According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  808. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  809. RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  810. delay slot, so an inversion is possible such as
  811. JMPL %i7+8,%g0
  812. RESTORE %g0,0,%g0
  813. If no inversion we can use just
  814. RESTORE %g0,0,%g0
  815. JMPL %i7+8,%g0
  816. NOP}
  817. with list do
  818. begin
  819. {Return address is computed by adding 8 to the CALL address saved onto %i6}
  820. concat(Taicpu.Op_caddr_reg(A_JMPL,R_I7,8,R_G0));
  821. {We use trivial restore in the delay slot of the JMPL instruction, as we
  822. already set result onto %i0}
  823. concat(Taicpu.Op_reg_const_reg(A_RESTORE,R_G0,0,R_G0));
  824. end
  825. end;
  826. procedure tcgSPARC.a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);
  827. begin
  828. // list.concat(taicpu.op_ref_reg(A_LEA,S_SW,ref,r));
  829. end;
  830. { ************* 64bit operations ************ }
  831. procedure TCg64fSPARC.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  832. begin
  833. case op of
  834. OP_ADD :
  835. begin
  836. op1:=A_ADD;
  837. op2:=A_ADD;
  838. end;
  839. OP_SUB :
  840. begin
  841. op1:=A_SUB;
  842. op2:=A_SUB;
  843. end;
  844. OP_XOR :
  845. begin
  846. op1:=A_XOR;
  847. op2:=A_XOR;
  848. end;
  849. OP_OR :
  850. begin
  851. op1:=A_OR;
  852. op2:=A_OR;
  853. end;
  854. OP_AND :
  855. begin
  856. op1:=A_AND;
  857. op2:=A_AND;
  858. end;
  859. else
  860. internalerror(200203241);
  861. end;
  862. end;
  863. procedure TCg64fSPARC.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);
  864. var
  865. op1,op2:TAsmOp;
  866. tempref:TReference;
  867. begin
  868. get_64bit_ops(op,op1,op2);
  869. list.concat(taicpu.op_ref_reg(op1,ref,reg.reglo));
  870. tempref:=ref;
  871. inc(tempref.offset,4);
  872. list.concat(taicpu.op_ref_reg(op2,tempref,reg.reghi));
  873. end;
  874. procedure TCg64fSPARC.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  875. var
  876. op1,op2:TAsmOp;
  877. begin
  878. get_64bit_ops(op,op1,op2);
  879. list.concat(taicpu.op_reg_reg(op1,regsrc.reglo,regdst.reglo));
  880. list.concat(taicpu.op_reg_reg(op2,regsrc.reghi,regdst.reghi));
  881. end;
  882. procedure TCg64fSPARC.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  883. var
  884. op1,op2:TAsmOp;
  885. begin
  886. case op of
  887. OP_AND,OP_OR,OP_XOR:
  888. WITH cg DO
  889. begin
  890. a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  891. a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  892. end;
  893. OP_ADD, OP_SUB:
  894. begin
  895. // can't use a_op_const_ref because this may use dec/inc
  896. get_64bit_ops(op,op1,op2);
  897. list.concat(taicpu.op_const_reg(op1,Lo(Value),regdst.reglo));
  898. list.concat(taicpu.op_const_reg(op2,Hi(Value),regdst.reghi));
  899. end;
  900. else
  901. internalerror(200204021);
  902. end;
  903. end;
  904. procedure TCg64fSPARC.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;const ref:TReference);
  905. var
  906. op1,op2:TAsmOp;
  907. tempref:TReference;
  908. begin
  909. case op of
  910. OP_AND,OP_OR,OP_XOR:
  911. with cg do
  912. begin
  913. a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  914. tempref:=ref;
  915. inc(tempref.offset,4);
  916. a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  917. end;
  918. OP_ADD, OP_SUB:
  919. begin
  920. get_64bit_ops(op,op1,op2);
  921. // can't use a_op_const_ref because this may use dec/inc
  922. { list.concat(taicpu.op_const_ref(op1,Lo(Value),ref));
  923. tempref:=ref;
  924. inc(tempref.offset,4);
  925. list.concat(taicpu.op_const_ref(op2,S_SW,Hi(Value),tempref));}
  926. InternalError(2002102101);
  927. end;
  928. else
  929. internalerror(200204022);
  930. end;
  931. end;
  932. { ************* concatcopy ************ }
  933. procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean);
  934. var
  935. countreg: TRegister;
  936. src, dst: TReference;
  937. lab: tasmlabel;
  938. count, count2: aword;
  939. orgsrc, orgdst: boolean;
  940. begin
  941. {$ifdef extdebug}
  942. if len > high(longint)
  943. then
  944. internalerror(2002072704);
  945. {$endif extdebug}
  946. { make sure short loads are handled as optimally as possible }
  947. if not loadref then
  948. if (len <= 8) and
  949. (byte(len) in [1,2,4,8]) then
  950. begin
  951. if len < 8 then
  952. begin
  953. a_load_ref_ref(list,int_cgsize(len),source,dest);
  954. if delsource then
  955. reference_release(list,source);
  956. end
  957. else
  958. begin
  959. a_reg_alloc(list,R_F0);
  960. a_loadfpu_ref_reg(list,OS_F64,source,R_F0);
  961. if delsource then
  962. reference_release(list,source);
  963. a_loadfpu_reg_ref(list,OS_F64,R_F0,dest);
  964. a_reg_dealloc(list,R_F0);
  965. end;
  966. exit;
  967. end;
  968. reference_reset(src);
  969. reference_reset(dst);
  970. { load the address of source into src.base }
  971. if loadref then
  972. begin
  973. src.base := get_scratch_reg_address(list);
  974. a_load_ref_reg(list,OS_32,source,src.base);
  975. orgsrc := false;
  976. end
  977. else if not issimpleref(source) or
  978. ((source.index <> R_NO) and
  979. ((source.offset + longint(len)) > high(smallint))) then
  980. begin
  981. src.base := get_scratch_reg_address(list);
  982. a_loadaddr_ref_reg(list,source,src.base);
  983. orgsrc := false;
  984. end
  985. else
  986. begin
  987. src := source;
  988. orgsrc := true;
  989. end;
  990. if not orgsrc and delsource then
  991. reference_release(list,source);
  992. { load the address of dest into dst.base }
  993. if not issimpleref(dest) or
  994. ((dest.index <> R_NO) and
  995. ((dest.offset + longint(len)) > high(smallint))) then
  996. begin
  997. dst.base := get_scratch_reg_address(list);
  998. a_loadaddr_ref_reg(list,dest,dst.base);
  999. orgdst := false;
  1000. end
  1001. else
  1002. begin
  1003. dst := dest;
  1004. orgdst := true;
  1005. end;
  1006. count := len div 8;
  1007. if count > 4 then
  1008. { generate a loop }
  1009. begin
  1010. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1011. { have to be set to 8. I put an Inc there so debugging may be }
  1012. { easier (should offset be different from zero here, it will be }
  1013. { easy to notice in the generated assembler }
  1014. inc(dst.offset,8);
  1015. inc(src.offset,8);
  1016. list.concat(taicpu.op_reg_const_reg(A_SUB,src.base,8,src.base));
  1017. list.concat(taicpu.op_reg_const_reg(A_SUB,dst.base,8,dst.base));
  1018. countreg := get_scratch_reg_int(list);
  1019. a_load_const_reg(list,OS_32,count,countreg);
  1020. { explicitely allocate R_O0 since it can be used safely here }
  1021. { (for holding date that's being copied) }
  1022. a_reg_alloc(list,R_F0);
  1023. objectlibrary.getlabel(lab);
  1024. a_label(list, lab);
  1025. list.concat(taicpu.op_reg_const_reg(A_SUB,countreg,1,countreg));
  1026. list.concat(taicpu.op_reg_ref(A_LDF,R_F0,src));
  1027. list.concat(taicpu.op_reg_ref(A_STD,R_F0,dst));
  1028. //a_jmp(list,A_BC,C_NE,0,lab);
  1029. free_scratch_reg(list,countreg);
  1030. a_reg_dealloc(list,R_F0);
  1031. len := len mod 8;
  1032. end;
  1033. count := len div 8;
  1034. if count > 0 then
  1035. { unrolled loop }
  1036. begin
  1037. a_reg_alloc(list,R_F0);
  1038. for count2 := 1 to count do
  1039. begin
  1040. a_loadfpu_ref_reg(list,OS_F64,src,R_F0);
  1041. a_loadfpu_reg_ref(list,OS_F64,R_F0,dst);
  1042. inc(src.offset,8);
  1043. inc(dst.offset,8);
  1044. end;
  1045. a_reg_dealloc(list,R_F0);
  1046. len := len mod 8;
  1047. end;
  1048. if (len and 4) <> 0 then
  1049. begin
  1050. a_reg_alloc(list,R_O0);
  1051. a_load_ref_reg(list,OS_32,src,R_O0);
  1052. a_load_reg_ref(list,OS_32,R_O0,dst);
  1053. inc(src.offset,4);
  1054. inc(dst.offset,4);
  1055. a_reg_dealloc(list,R_O0);
  1056. end;
  1057. { copy the leftovers }
  1058. if (len and 2) <> 0 then
  1059. begin
  1060. a_reg_alloc(list,R_O0);
  1061. a_load_ref_reg(list,OS_16,src,R_O0);
  1062. a_load_reg_ref(list,OS_16,R_O0,dst);
  1063. inc(src.offset,2);
  1064. inc(dst.offset,2);
  1065. a_reg_dealloc(list,R_O0);
  1066. end;
  1067. if (len and 1) <> 0 then
  1068. begin
  1069. a_reg_alloc(list,R_O0);
  1070. a_load_ref_reg(list,OS_8,src,R_O0);
  1071. a_load_reg_ref(list,OS_8,R_O0,dst);
  1072. a_reg_dealloc(list,R_O0);
  1073. end;
  1074. if orgsrc then
  1075. begin
  1076. if delsource then
  1077. reference_release(list,source);
  1078. end
  1079. else
  1080. free_scratch_reg(list,src.base);
  1081. if not orgdst then
  1082. free_scratch_reg(list,dst.base);
  1083. end;
  1084. function tcgSPARC.reg_cgsize(CONST reg:tregister):tcgsize;
  1085. begin
  1086. result:=OS_32;
  1087. end;
  1088. {***************** This is private property, keep out! :) *****************}
  1089. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  1090. begin
  1091. if(ref.base=R_NONE)and(ref.index <> R_NO)
  1092. then
  1093. InternalError(2002100804);
  1094. result :=not(assigned(ref.symbol))and
  1095. (((ref.index = R_NO) and
  1096. (ref.offset >= low(smallint)) and
  1097. (ref.offset <= high(smallint))) or
  1098. ((ref.index <> R_NO) and
  1099. (ref.offset = 0)));
  1100. end;
  1101. procedure tcgSPARC.sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  1102. begin
  1103. case s2 of
  1104. S_B:
  1105. if S1 in [OS_8,OS_S8]
  1106. then
  1107. s3 := S_B
  1108. else
  1109. internalerror(200109221);
  1110. S_W:
  1111. case s1 of
  1112. OS_8,OS_S8:
  1113. s3 := S_B;
  1114. OS_16,OS_S16:
  1115. s3 := S_H;
  1116. else
  1117. internalerror(200109222);
  1118. end;
  1119. S_SW:
  1120. case s1 of
  1121. OS_8,OS_S8:
  1122. s3 := S_B;
  1123. OS_16,OS_S16:
  1124. s3 := S_H;
  1125. OS_32,OS_S32:
  1126. s3 := S_W;
  1127. else
  1128. internalerror(200109223);
  1129. end;
  1130. else internalerror(200109227);
  1131. end;
  1132. if s3 in [S_B,S_W,S_SW]
  1133. then
  1134. op := A_LD
  1135. { else if s3=S_DW
  1136. then
  1137. op:=A_LDD
  1138. else if s3 in [OS_8,OS_16,OS_32]
  1139. then
  1140. op := A_NONE}
  1141. else
  1142. op := A_NONE;
  1143. end;
  1144. procedure tcgSPARC.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize);
  1145. BEGIN
  1146. (* case t of
  1147. OS_F32:begin
  1148. op:=A_FLD;
  1149. s:=S_FS;
  1150. end;
  1151. OS_F64:begin
  1152. op:=A_FLD;
  1153. { ???? }
  1154. s:=S_FL;
  1155. end;
  1156. OS_F80:begin
  1157. op:=A_FLD;
  1158. s:=S_FX;
  1159. end;
  1160. OS_C64:begin
  1161. op:=A_FILD;
  1162. s:=S_IQ;
  1163. end;
  1164. else internalerror(17);
  1165. end;*)
  1166. END;
  1167. procedure tcgSPARC.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1168. VAR
  1169. op:tasmop;
  1170. s:topsize;
  1171. BEGIN
  1172. floatloadops(t,op,s);
  1173. list.concat(Taicpu.Op_ref(op,ref));
  1174. { inc(trgcpu(rg).fpuvaroffset);}
  1175. END;
  1176. procedure tcgSPARC.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  1177. BEGIN
  1178. { case t of
  1179. OS_F32:begin
  1180. op:=A_FSTP;
  1181. s:=S_FS;
  1182. end;
  1183. OS_F64:begin
  1184. op:=A_FSTP;
  1185. s:=S_FL;
  1186. end;
  1187. OS_F80:begin
  1188. op:=A_FSTP;
  1189. s:=S_FX;
  1190. end;
  1191. OS_C64:begin
  1192. op:=A_FISTP;
  1193. s:=S_IQ;
  1194. end;
  1195. else
  1196. internalerror(17);
  1197. end;}
  1198. end;
  1199. procedure tcgSPARC.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1200. VAR
  1201. op:tasmop;
  1202. s:topsize;
  1203. BEGIN
  1204. floatstoreops(t,op,s);
  1205. list.concat(Taicpu.Op_ref(op,ref));
  1206. { dec(trgcpu(rg).fpuvaroffset);}
  1207. END;
  1208. BEGIN
  1209. cg:=tcgSPARC.create;
  1210. END.
  1211. {
  1212. $Log$
  1213. Revision 1.26 2002-11-25 19:21:49 mazen
  1214. * fixed support of nSparcInline
  1215. Revision 1.25 2002/11/25 17:43:28 peter
  1216. * splitted defbase in defutil,symutil,defcmp
  1217. * merged isconvertable and is_equal into compare_defs(_ext)
  1218. * made operator search faster by walking the list only once
  1219. Revision 1.24 2002/11/17 17:49:09 mazen
  1220. + return_result_reg and function_result_reg are now used, in all plateforms, to pass functions result between called function and its caller. See the explanation of each one
  1221. Revision 1.23 2002/11/10 19:07:46 mazen
  1222. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1223. Revision 1.22 2002/11/06 11:31:24 mazen
  1224. * op_reg_reg_reg don't need any more a TOpSize parameter
  1225. Revision 1.21 2002/11/05 16:15:00 mazen
  1226. *** empty log message ***
  1227. Revision 1.20 2002/11/03 20:22:40 mazen
  1228. * parameter handling updated
  1229. Revision 1.19 2002/10/28 20:59:17 mazen
  1230. * TOpSize values changed S_L --> S_SW
  1231. Revision 1.18 2002/10/22 13:43:01 mazen
  1232. - cga.pas redueced to an empty unit
  1233. Revision 1.17 2002/10/20 19:01:38 mazen
  1234. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1235. Revision 1.16 2002/10/13 21:46:07 mazen
  1236. * assembler output format fixed
  1237. Revision 1.15 2002/10/11 13:35:14 mazen
  1238. *** empty log message ***
  1239. Revision 1.14 2002/10/10 19:57:51 mazen
  1240. * Just to update repsitory
  1241. Revision 1.13 2002/10/10 15:10:39 mazen
  1242. * Internal error fixed, but usually i386 parameter model used
  1243. Revision 1.12 2002/10/08 17:17:03 mazen
  1244. *** empty log message ***
  1245. Revision 1.11 2002/10/07 20:33:04 mazen
  1246. word alignement modified in g_stack_frame
  1247. Revision 1.10 2002/10/04 21:57:42 mazen
  1248. * 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
  1249. Revision 1.9 2002/10/02 22:20:28 mazen
  1250. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1251. Revision 1.8 2002/10/01 21:35:58 mazen
  1252. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1253. Revision 1.7 2002/10/01 21:06:29 mazen
  1254. attinst.inc --> strinst.inc
  1255. Revision 1.6 2002/10/01 17:41:50 florian
  1256. * fixed log and id
  1257. }