2
0

cgcpu.pas 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the code generator for the SPARC
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cgbase,cgobj,cg64f32,
  23. aasmbase,aasmtai,aasmcpu,
  24. cpubase,cpuinfo,
  25. node,symconst,SymType,
  26. rgcpu;
  27. type
  28. TCgSparc=class(tcg)
  29. protected
  30. rgint,
  31. rgfpu : trgcpu;
  32. function IsSimpleRef(const ref:treference):boolean;
  33. public
  34. procedure init_register_allocators;override;
  35. procedure done_register_allocators;override;
  36. function getintregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  37. function getaddressregister(list:Taasmoutput):Tregister;override;
  38. function getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  39. function getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;override;
  40. procedure getexplicitregister(list:Taasmoutput;r:Tregister);override;
  41. procedure ungetregister(list:Taasmoutput;r:Tregister);override;
  42. procedure add_move_instruction(instr:Taicpu);override;
  43. procedure do_register_allocation(list:Taasmoutput;headertai:tai);override;
  44. procedure allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
  45. procedure deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);override;
  46. { sparc special, needed by cg64 }
  47. procedure handle_load_store(list:taasmoutput;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
  48. procedure handle_reg_const_reg(list:taasmoutput;op:Tasmop;src:tregister;a:aword;dst:tregister);
  49. { parameter }
  50. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);override;
  51. procedure a_param_ref(list:TAasmOutput;sz:tcgsize;const r:TReference;const LocPara:TParaLocation);override;
  52. procedure a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation);override;
  53. procedure a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const locpara : tparalocation);override;
  54. procedure a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const locpara : tparalocation);override;
  55. procedure a_loadany_param_ref(list : taasmoutput;const locpara : tparalocation;const ref:treference;shuffle : pmmshuffle);override;
  56. procedure a_loadany_param_reg(list : taasmoutput;const locpara : tparalocation;const reg:tregister;shuffle : pmmshuffle);override;
  57. procedure a_call_name(list:TAasmOutput;const s:string);override;
  58. procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override;
  59. { General purpose instructions }
  60. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;size:tcgsize;a:AWord;reg:TRegister);override;
  61. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  62. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  63. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  64. { move instructions }
  65. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  66. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;const ref:TReference);override;
  67. procedure a_load_reg_ref(list:TAasmOutput;FromSize,ToSize:TCgSize;reg:TRegister;const ref:TReference);override;
  68. procedure a_load_ref_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);override;
  69. procedure a_load_reg_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;reg1,reg2:tregister);override;
  70. procedure a_loadaddr_ref_reg(list:TAasmOutput;const ref:TReference;r:tregister);override;
  71. { fpu move instructions }
  72. procedure a_loadfpu_reg_reg(list:TAasmOutput;size:tcgsize;reg1, reg2:tregister);override;
  73. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override;
  74. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override;
  75. { comparison operations }
  76. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  77. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  78. procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
  79. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  80. procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override;
  81. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override;
  82. procedure g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);override;
  83. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  84. procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override;
  85. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  86. procedure g_restore_standard_registers(list:taasmoutput);override;
  87. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  88. procedure g_save_all_registers(list : taasmoutput);override;
  89. procedure g_save_standard_registers(list : taasmoutput);override;
  90. procedure g_concatcopy(list:TAasmOutput;const source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  91. class function reg_cgsize(const reg:tregister):tcgsize;override;
  92. end;
  93. TCg64Sparc=class(tcg64f32)
  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 get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  97. end;
  98. const
  99. TOpCG2AsmOp : array[topcg] of TAsmOp=(
  100. A_NONE,A_ADD,A_AND,A_UDIV,A_SDIV,A_UMUL,A_SMUL,A_NEG,A_NOT,A_OR,A_SRA,A_SLL,A_SRL,A_SUB,A_XOR
  101. );
  102. TOpCmp2AsmCond : array[topcmp] of TAsmCond=(
  103. C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A
  104. );
  105. implementation
  106. uses
  107. globtype,globals,verbose,systems,cutils,
  108. symdef,symsym,defutil,paramgr,
  109. tgobj,cpupi;
  110. {****************************************************************************
  111. This is private property, keep out! :)
  112. ****************************************************************************}
  113. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  114. begin
  115. if (ref.base=NR_NO) and (ref.index<>NR_NO) then
  116. InternalError(2002100804);
  117. result :=not(assigned(ref.symbol))and
  118. (((ref.index = NR_NO) and
  119. (ref.offset >= simm13lo) and
  120. (ref.offset <= simm13hi)) or
  121. ((ref.index <> NR_NO) and
  122. (ref.offset = 0)));
  123. end;
  124. procedure tcgsparc.handle_load_store(list:taasmoutput;isstore:boolean;op: tasmop;reg:tregister;ref: treference);
  125. var
  126. tmpreg : tregister;
  127. tmpref : treference;
  128. begin
  129. tmpreg:=NR_NO;
  130. { Be sure to have a base register }
  131. if (ref.base=NR_NO) then
  132. begin
  133. ref.base:=ref.index;
  134. ref.index:=NR_NO;
  135. end;
  136. { When need to use SETHI, do it first }
  137. if assigned(ref.symbol) or
  138. (ref.offset<simm13lo) or
  139. (ref.offset>simm13hi) then
  140. begin
  141. tmpreg:=GetIntRegister(list,OS_INT);
  142. reference_reset(tmpref);
  143. tmpref.symbol:=ref.symbol;
  144. tmpref.offset:=ref.offset;
  145. tmpref.symaddr:=refs_hi;
  146. list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,tmpreg));
  147. { Load the low part is left }
  148. {$warning TODO Maybe not needed to load symbol}
  149. tmpref.symaddr:=refs_lo;
  150. list.concat(taicpu.op_reg_ref_reg(A_OR,tmpreg,tmpref,tmpreg));
  151. { The offset and symbol are loaded, reset in reference }
  152. ref.offset:=0;
  153. ref.symbol:=nil;
  154. { Only an index register or offset is allowed }
  155. if tmpreg<>NR_NO then
  156. begin
  157. if (ref.index<>NR_NO) then
  158. begin
  159. list.concat(taicpu.op_reg_reg_reg(A_ADD,tmpreg,ref.index,tmpreg));
  160. ref.index:=tmpreg;
  161. end
  162. else
  163. begin
  164. if ref.base<>NR_NO then
  165. ref.index:=tmpreg
  166. else
  167. ref.base:=tmpreg;
  168. end;
  169. end;
  170. end;
  171. if (ref.base<>NR_NO) then
  172. begin
  173. if (ref.index<>NR_NO) and
  174. ((ref.offset<>0) or assigned(ref.symbol)) then
  175. begin
  176. if tmpreg=NR_NO then
  177. tmpreg:=GetIntRegister(list,OS_INT);
  178. if (ref.index<>NR_NO) then
  179. begin
  180. list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,tmpreg));
  181. ref.index:=NR_NO;
  182. end;
  183. end;
  184. end;
  185. if isstore then
  186. list.concat(taicpu.op_reg_ref(op,reg,ref))
  187. else
  188. list.concat(taicpu.op_ref_reg(op,ref,reg));
  189. if (tmpreg<>NR_NO) then
  190. UnGetRegister(list,tmpreg);
  191. end;
  192. procedure tcgsparc.handle_reg_const_reg(list:taasmoutput;op:Tasmop;src:tregister;a:aword;dst:tregister);
  193. var
  194. tmpreg : tregister;
  195. begin
  196. if (longint(a)<simm13lo) or
  197. (longint(a)>simm13hi) then
  198. begin
  199. tmpreg:=GetIntRegister(list,OS_INT);
  200. list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,tmpreg));
  201. list.concat(taicpu.op_reg_const_reg(A_OR,tmpreg,a and aword($3ff),tmpreg));
  202. list.concat(taicpu.op_reg_reg_reg(op,src,tmpreg,dst));
  203. UnGetRegister(list,tmpreg);
  204. end
  205. else
  206. list.concat(taicpu.op_reg_const_reg(op,src,a,dst));
  207. end;
  208. {****************************************************************************
  209. Assembler code
  210. ****************************************************************************}
  211. procedure Tcgsparc.init_register_allocators;
  212. begin
  213. rgint:=Trgcpu.create(R_INTREGISTER,R_SUBWHOLE,
  214. [RS_O0,RS_O1,RS_O2,RS_O3,RS_O4,RS_O5,RS_O7,
  215. RS_L0,RS_L1,RS_L2,RS_L3,RS_L4,RS_L5,RS_L6,RS_L7],
  216. first_int_imreg,[]);
  217. rgfpu:=trgcpu.create(R_FPUREGISTER,R_SUBNONE,
  218. [RS_F0,RS_F1,RS_F2,RS_F3,RS_F4,RS_F5,RS_F6,RS_F7,
  219. RS_F8,RS_F9,RS_F10,RS_F11,RS_F12,RS_F13,RS_F14,RS_F15,
  220. RS_F16,RS_F17,RS_F18,RS_F19,RS_F20,RS_F21,RS_F22,RS_F23,
  221. RS_F24,RS_F25,RS_F26,RS_F27,RS_F28,RS_F29,RS_F30,RS_F31],
  222. first_fpu_imreg,[]);
  223. end;
  224. procedure Tcgsparc.done_register_allocators;
  225. begin
  226. rgint.free;
  227. rgfpu.free;
  228. end;
  229. function tcgsparc.getintregister(list:Taasmoutput;size:Tcgsize):Tregister;
  230. begin
  231. result:=rgint.getregister(list,R_SUBWHOLE);
  232. end;
  233. function tcgsparc.getaddressregister(list:Taasmoutput):Tregister;
  234. begin
  235. result:=rgint.getregister(list,R_SUBWHOLE);
  236. end;
  237. function tcgsparc.getfpuregister(list:Taasmoutput;size:Tcgsize):Tregister;
  238. begin
  239. if size=OS_F64 then
  240. result:=rgfpu.getregister(list,R_SUBFD)
  241. else
  242. result:=rgfpu.getregister(list,R_SUBWHOLE);
  243. end;
  244. function tcgsparc.getmmregister(list:Taasmoutput;size:Tcgsize):Tregister;
  245. begin
  246. internalerror(200310241);
  247. result:=RS_INVALID;
  248. end;
  249. procedure tcgsparc.getexplicitregister(list:Taasmoutput;r:Tregister);
  250. begin
  251. case getregtype(r) of
  252. R_INTREGISTER :
  253. rgint.getexplicitregister(list,r);
  254. R_FPUREGISTER :
  255. rgfpu.getexplicitregister(list,r);
  256. else
  257. internalerror(200310091);
  258. end;
  259. end;
  260. procedure tcgsparc.ungetregister(list:Taasmoutput;r:Tregister);
  261. begin
  262. case getregtype(r) of
  263. R_INTREGISTER :
  264. rgint.ungetregister(list,r);
  265. R_FPUREGISTER :
  266. rgfpu.ungetregister(list,r);
  267. else
  268. internalerror(200310091);
  269. end;
  270. end;
  271. procedure tcgsparc.allocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
  272. begin
  273. case rt of
  274. R_INTREGISTER :
  275. rgint.allocexplicitregisters(list,r);
  276. R_FPUREGISTER :
  277. rgfpu.allocexplicitregisters(list,r);
  278. R_MMREGISTER :;
  279. else
  280. internalerror(200310092);
  281. end;
  282. end;
  283. procedure tcgsparc.deallocexplicitregisters(list:Taasmoutput;rt:Tregistertype;r:Tcpuregisterset);
  284. begin
  285. case rt of
  286. R_INTREGISTER :
  287. rgint.deallocexplicitregisters(list,r);
  288. R_FPUREGISTER :
  289. rgfpu.deallocexplicitregisters(list,r);
  290. R_MMREGISTER :;
  291. else
  292. internalerror(200310093);
  293. end;
  294. end;
  295. procedure tcgsparc.add_move_instruction(instr:Taicpu);
  296. begin
  297. rgint.add_move_instruction(instr);
  298. end;
  299. procedure tcgsparc.do_register_allocation(list:Taasmoutput;headertai:tai);
  300. begin
  301. { Int }
  302. rgint.do_register_allocation(list,headertai);
  303. rgint.translate_registers(list);
  304. { FPU }
  305. rgfpu.do_register_allocation(list,headertai);
  306. rgfpu.translate_registers(list);
  307. end;
  308. function TCgSparc.reg_cgsize(const reg:tregister):tcgsize;
  309. begin
  310. result:=OS_32;
  311. end;
  312. procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);
  313. var
  314. Ref:TReference;
  315. begin
  316. case locpara.loc of
  317. LOC_REGISTER,LOC_CREGISTER:
  318. a_load_const_reg(list,size,a,locpara.register);
  319. LOC_REFERENCE:
  320. begin
  321. { Code conventions need the parameters being allocated in %o6+92 }
  322. if locpara.reference.offset<92 then
  323. InternalError(2002081104);
  324. reference_reset_base(ref,locpara.reference.index,locpara.reference.offset);
  325. a_load_const_ref(list,size,a,ref);
  326. end;
  327. else
  328. InternalError(2002122200);
  329. end;
  330. end;
  331. procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation);
  332. var
  333. ref: treference;
  334. tmpreg:TRegister;
  335. begin
  336. with LocPara do
  337. case loc of
  338. LOC_REGISTER,LOC_CREGISTER :
  339. a_load_ref_reg(list,sz,sz,r,Register);
  340. LOC_REFERENCE:
  341. begin
  342. { Code conventions need the parameters being allocated in %o6+92 }
  343. if locpara.reference.offset<92 then
  344. InternalError(2002081104);
  345. reference_reset_base(ref,locpara.reference.index,locpara.reference.offset);
  346. tmpreg:=GetIntRegister(list,OS_INT);
  347. a_load_ref_reg(list,sz,sz,r,tmpreg);
  348. a_load_reg_ref(list,sz,sz,tmpreg,ref);
  349. UnGetRegister(list,tmpreg);
  350. end;
  351. else
  352. internalerror(2002081103);
  353. end;
  354. end;
  355. procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation);
  356. var
  357. Ref:TReference;
  358. TmpReg:TRegister;
  359. begin
  360. case locpara.loc of
  361. LOC_REGISTER,LOC_CREGISTER:
  362. a_loadaddr_ref_reg(list,r,locpara.register);
  363. LOC_REFERENCE:
  364. begin
  365. reference_reset(ref);
  366. ref.base := locpara.reference.index;
  367. ref.offset := locpara.reference.offset;
  368. tmpreg:=GetAddressRegister(list);
  369. a_loadaddr_ref_reg(list,r,tmpreg);
  370. a_load_reg_ref(list,OS_ADDR,OS_ADDR,tmpreg,ref);
  371. UnGetRegister(list,tmpreg);
  372. end;
  373. else
  374. internalerror(2002080701);
  375. end;
  376. end;
  377. procedure tcgsparc.a_paramfpu_reg(list : taasmoutput;size : tcgsize;const r : tregister;const locpara : tparalocation);
  378. var
  379. href : treference;
  380. begin
  381. tg.GetTemp(list,TCGSize2Size[size],tt_normal,href);
  382. a_loadfpu_reg_ref(list,size,r,href);
  383. a_paramfpu_ref(list,size,href,locpara);
  384. tg.Ungettemp(list,href);
  385. end;
  386. procedure tcgsparc.a_paramfpu_ref(list : taasmoutput;size : tcgsize;const ref : treference;const locpara : tparalocation);
  387. var
  388. templocpara : tparalocation;
  389. begin
  390. { floats are pushed in the int registers }
  391. templocpara:=locpara;
  392. case locpara.size of
  393. OS_F32 :
  394. begin
  395. templocpara.size:=OS_32;
  396. a_param_ref(list,OS_32,ref,templocpara);
  397. end;
  398. OS_F64 :
  399. begin
  400. templocpara.size:=OS_64;
  401. cg64.a_param64_ref(list,ref,templocpara);
  402. end;
  403. else
  404. internalerror(200307021);
  405. end;
  406. end;
  407. procedure tcgsparc.a_loadany_param_ref(list : taasmoutput;const locpara : tparalocation;const ref:treference;shuffle : pmmshuffle);
  408. var
  409. href,
  410. tempref : treference;
  411. templocpara : tparalocation;
  412. begin
  413. { Load floats like ints }
  414. templocpara:=locpara;
  415. case locpara.size of
  416. OS_F32 :
  417. templocpara.size:=OS_32;
  418. OS_F64 :
  419. templocpara.size:=OS_64;
  420. end;
  421. { Word 0 is in register, word 1 is in reference }
  422. if (templocpara.loc=LOC_REFERENCE) and (templocpara.low_in_reg) then
  423. begin
  424. tempref:=ref;
  425. cg.a_load_reg_ref(list,OS_INT,OS_INT,templocpara.register,tempref);
  426. inc(tempref.offset,4);
  427. reference_reset_base(href,templocpara.reference.index,templocpara.reference.offset);
  428. cg.a_load_ref_ref(list,OS_INT,OS_INT,href,tempref);
  429. end
  430. else
  431. inherited a_loadany_param_ref(list,templocpara,ref,shuffle);
  432. end;
  433. procedure tcgsparc.a_loadany_param_reg(list : taasmoutput;const locpara : tparalocation;const reg:tregister;shuffle : pmmshuffle);
  434. var
  435. href : treference;
  436. begin
  437. { Word 0 is in register, word 1 is in reference, not
  438. possible to load it in 1 register }
  439. if (locpara.loc=LOC_REFERENCE) and (locpara.low_in_reg) then
  440. internalerror(200307011);
  441. { Float load use a temp reference }
  442. if locpara.size in [OS_F32,OS_F64] then
  443. begin
  444. tg.GetTemp(list,TCGSize2Size[locpara.size],tt_normal,href);
  445. a_loadany_param_ref(list,locpara,href,shuffle);
  446. a_loadfpu_ref_reg(list,locpara.size,href,reg);
  447. tg.Ungettemp(list,href);
  448. end
  449. else
  450. inherited a_loadany_param_reg(list,locpara,reg,shuffle);
  451. end;
  452. procedure TCgSparc.a_call_name(list:TAasmOutput;const s:string);
  453. begin
  454. list.concat(taicpu.op_sym(A_CALL,objectlibrary.newasmsymbol(s)));
  455. { Delay slot }
  456. list.concat(taicpu.op_none(A_NOP));
  457. end;
  458. procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister);
  459. begin
  460. list.concat(taicpu.op_reg(A_CALL,reg));
  461. { Delay slot }
  462. list.concat(taicpu.op_none(A_NOP));
  463. end;
  464. {********************** load instructions ********************}
  465. procedure TCgSparc.a_load_const_reg(list : TAasmOutput;size : TCGSize;a : aword;reg : TRegister);
  466. begin
  467. { we don't use the set instruction here because it could be evalutated to two
  468. instructions which would cause problems with the delay slot (FK) }
  469. { sethi allows to set the upper 22 bit, so we'll take full advantage of it }
  470. if (a and aword($1fff))=0 then
  471. list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,reg))
  472. else if (longint(a)>=simm13lo) and (longint(a)<=simm13hi) then
  473. list.concat(taicpu.op_reg_const_reg(A_OR,NR_G0,a,reg))
  474. else
  475. begin
  476. list.concat(taicpu.op_const_reg(A_SETHI,a shr 10,reg));
  477. list.concat(taicpu.op_reg_const_reg(A_OR,reg,a and aword($3ff),reg));
  478. end;
  479. end;
  480. procedure TCgSparc.a_load_const_ref(list : TAasmOutput;size : tcgsize;a : aword;const ref : TReference);
  481. begin
  482. if a=0 then
  483. a_load_reg_ref(list,size,size,NR_G0,ref)
  484. else
  485. inherited a_load_const_ref(list,size,a,ref);
  486. end;
  487. procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;FromSize,ToSize:TCGSize;reg:tregister;const Ref:TReference);
  488. var
  489. op:tasmop;
  490. begin
  491. case ToSize of
  492. { signed integer registers }
  493. OS_8,
  494. OS_S8:
  495. Op:=A_STB;
  496. OS_16,
  497. OS_S16:
  498. Op:=A_STH;
  499. OS_32,
  500. OS_S32:
  501. Op:=A_ST;
  502. else
  503. InternalError(2002122100);
  504. end;
  505. handle_load_store(list,true,op,reg,ref);
  506. end;
  507. procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;FromSize,ToSize:TCgSize;const ref:TReference;reg:tregister);
  508. var
  509. op:tasmop;
  510. begin
  511. case Fromsize of
  512. { signed integer registers }
  513. OS_S8:
  514. Op:=A_LDSB;{Load Signed Byte}
  515. OS_8:
  516. Op:=A_LDUB;{Load Unsigned Bye}
  517. OS_S16:
  518. Op:=A_LDSH;{Load Signed Halfword}
  519. OS_16:
  520. Op:=A_LDUH;{Load Unsigned Halfword}
  521. OS_S32,
  522. OS_32:
  523. Op:=A_LD;{Load Word}
  524. else
  525. InternalError(2002122101);
  526. end;
  527. handle_load_store(list,false,op,reg,ref);
  528. end;
  529. procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  530. begin
  531. if (reg1<>reg2) or
  532. (tcgsize2size[tosize]<tcgsize2size[fromsize]) or
  533. (
  534. (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  535. (tosize <> fromsize) and
  536. not(fromsize in [OS_32,OS_S32])
  537. ) then
  538. begin
  539. {$warning TODO Sign extension}
  540. case tosize of
  541. OS_8,OS_S8:
  542. a_op_const_reg_reg(list,OP_AND,tosize,$ff,reg1,reg2);
  543. OS_16,OS_S16:
  544. a_op_const_reg_reg(list,OP_AND,tosize,$ffff,reg1,reg2);
  545. OS_32,OS_S32:
  546. begin
  547. if reg1<>reg2 then
  548. list.Concat(taicpu.op_reg_reg(A_MOV,reg1,reg2));
  549. end;
  550. else
  551. internalerror(2002090901);
  552. end;
  553. end;
  554. end;
  555. procedure TCgSparc.a_loadaddr_ref_reg(list : TAasmOutput;const ref : TReference;r : tregister);
  556. var
  557. tmpref : treference;
  558. hreg : tregister;
  559. begin
  560. if (ref.base=NR_NO) and (ref.index<>NR_NO) then
  561. internalerror(200306171);
  562. { At least big offset (need SETHI), maybe base and maybe index }
  563. if assigned(ref.symbol) or
  564. (ref.offset<simm13lo) or
  565. (ref.offset>simm13hi) then
  566. begin
  567. if (ref.base<>r) and (ref.index<>r) then
  568. hreg:=r
  569. else
  570. hreg:=GetAddressRegister(list);
  571. reference_reset(tmpref);
  572. tmpref.symbol := ref.symbol;
  573. tmpref.offset := ref.offset;
  574. tmpref.symaddr := refs_hi;
  575. list.concat(taicpu.op_ref_reg(A_SETHI,tmpref,hreg));
  576. { Only the low part is left }
  577. tmpref.symaddr:=refs_lo;
  578. list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,tmpref,hreg));
  579. if ref.base<>NR_NO then
  580. begin
  581. if ref.index<>NR_NO then
  582. begin
  583. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,hreg));
  584. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,r));
  585. end
  586. else
  587. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.base,r));
  588. end
  589. else
  590. begin
  591. if hreg<>r then
  592. list.Concat(taicpu.op_reg_reg(A_MOV,hreg,r));
  593. end;
  594. if hreg<>r then
  595. UnGetRegister(list,hreg);
  596. end
  597. else
  598. { At least small offset, maybe base and maybe index }
  599. if ref.offset<>0 then
  600. begin
  601. if ref.base<>NR_NO then
  602. begin
  603. if ref.index<>NR_NO then
  604. begin
  605. if (ref.base<>r) and (ref.index<>r) then
  606. hreg:=r
  607. else
  608. hreg:=GetAddressRegister(list);
  609. list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),hreg));
  610. list.concat(taicpu.op_reg_reg_reg(A_ADD,hreg,ref.index,r));
  611. if hreg<>r then
  612. UnGetRegister(list,hreg);
  613. end
  614. else
  615. list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),r));
  616. end
  617. else
  618. list.concat(taicpu.op_reg_const_reg(A_ADD,NR_G0,aword(ref.offset),r));
  619. end
  620. else
  621. { Both base and index }
  622. if ref.index<>NR_NO then
  623. list.concat(taicpu.op_reg_reg_reg(A_ADD,ref.base,ref.index,r))
  624. else
  625. { Only base }
  626. if ref.base<>NR_NO then
  627. a_load_reg_reg(list,OS_INT,OS_INT,ref.base,r)
  628. else
  629. internalerror(200306172);
  630. end;
  631. procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;size:tcgsize;reg1, reg2:tregister);
  632. begin
  633. if reg1<>reg2 then
  634. begin
  635. list.concat(taicpu.op_reg_reg(A_FMOVs,reg1,reg2));
  636. if size=OS_F64 then
  637. begin
  638. setsupreg(reg1,getsupreg(reg1)+1);
  639. setsupreg(reg2,getsupreg(reg2)+1);
  640. list.concat(taicpu.op_reg_reg(A_FMOVs,reg1,reg2));
  641. end;
  642. end;
  643. end;
  644. procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);
  645. const
  646. FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
  647. (A_LDF,A_LDDF);
  648. begin
  649. { several functions call this procedure with OS_32 or OS_64 }
  650. { so this makes life easier (FK) }
  651. case size of
  652. OS_32,OS_F32:
  653. size:=OS_F32;
  654. OS_64,OS_F64,OS_C64:
  655. size:=OS_F64;
  656. else
  657. internalerror(200201121);
  658. end;
  659. handle_load_store(list,false,fpuloadinstr[size],reg,ref);
  660. end;
  661. procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);
  662. const
  663. FpuLoadInstr : Array[OS_F32..OS_F64] of TAsmOp =
  664. (A_STF,A_STDF);
  665. begin
  666. { several functions call this procedure with OS_32 or OS_64 }
  667. { so this makes life easier (FK) }
  668. case size of
  669. OS_32,OS_F32:
  670. size:=OS_F32;
  671. OS_64,OS_F64,OS_C64:
  672. size:=OS_F64;
  673. else
  674. internalerror(200201121);
  675. end;
  676. handle_load_store(list,true,fpuloadinstr[size],reg,ref);
  677. end;
  678. procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;size:tcgsize;a:AWord;reg:TRegister);
  679. begin
  680. if Op in [OP_NEG,OP_NOT] then
  681. internalerror(200306011);
  682. if (a=0) then
  683. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],reg,NR_G0,reg))
  684. else
  685. handle_reg_const_reg(list,TOpCG2AsmOp[op],reg,a,reg);
  686. end;
  687. procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  688. begin
  689. Case Op of
  690. OP_NEG,
  691. OP_NOT:
  692. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],src,dst));
  693. else
  694. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
  695. end;
  696. end;
  697. procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);
  698. var
  699. power : longInt;
  700. begin
  701. case op of
  702. OP_IMUL :
  703. begin
  704. if not(cs_check_overflow in aktlocalswitches) and
  705. ispowerof2(a,power) then
  706. begin
  707. { can be done with a shift }
  708. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  709. exit;
  710. end;
  711. end;
  712. OP_SUB,
  713. OP_ADD :
  714. begin
  715. if (a=0) then
  716. begin
  717. a_load_reg_reg(list,size,size,src,dst);
  718. exit;
  719. end;
  720. end;
  721. end;
  722. handle_reg_const_reg(list,TOpCG2AsmOp[op],src,a,dst);
  723. end;
  724. procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);
  725. begin
  726. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],src2,src1,dst));
  727. end;
  728. {*************** compare instructructions ****************}
  729. procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);
  730. begin
  731. if (a=0) then
  732. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg,NR_G0,NR_G0))
  733. else
  734. handle_reg_const_reg(list,A_SUBcc,reg,a,NR_G0);
  735. a_jmp_cond(list,cmp_op,l);
  736. end;
  737. procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);
  738. begin
  739. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,reg2,reg1,NR_G0));
  740. a_jmp_cond(list,cmp_op,l);
  741. end;
  742. procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
  743. begin
  744. List.Concat(TAiCpu.op_sym(A_BA,objectlibrary.newasmsymbol(l.name)));
  745. { Delay slot }
  746. list.Concat(TAiCpu.Op_none(A_NOP));
  747. end;
  748. procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel);
  749. var
  750. ai:TAiCpu;
  751. begin
  752. ai:=TAiCpu.Op_sym(A_Bxx,l);
  753. ai.SetCondition(TOpCmp2AsmCond[cond]);
  754. list.Concat(ai);
  755. { Delay slot }
  756. list.Concat(TAiCpu.Op_none(A_NOP));
  757. end;
  758. procedure TCgSparc.a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);
  759. var
  760. ai:taicpu;
  761. begin
  762. ai := Taicpu.op_sym(A_Bxx,l);
  763. ai.SetCondition(flags_to_cond(f));
  764. list.Concat(ai);
  765. { Delay slot }
  766. list.Concat(TAiCpu.Op_none(A_NOP));
  767. end;
  768. procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);
  769. var
  770. hl : tasmlabel;
  771. begin
  772. objectlibrary.getlabel(hl);
  773. a_load_const_reg(list,size,1,reg);
  774. a_jmp_flags(list,f,hl);
  775. a_load_const_reg(list,size,0,reg);
  776. a_label(list,hl);
  777. end;
  778. procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);
  779. var
  780. hl : tasmlabel;
  781. begin
  782. if not(cs_check_overflow in aktlocalswitches) then
  783. exit;
  784. objectlibrary.getlabel(hl);
  785. if not((def.deftype=pointerdef)or
  786. ((def.deftype=orddef)and
  787. (torddef(def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,bool8bit,bool16bit,bool32bit]))) then
  788. begin
  789. //r.enum:=R_CR7;
  790. //list.concat(taicpu.op_reg(A_MCRXR,r));
  791. //a_jmp_cond(list,A_Bxx,C_OV,hl)
  792. a_jmp_always(list,hl)
  793. end
  794. else
  795. a_jmp_cond(list,OC_AE,hl);
  796. a_call_name(list,'FPC_OVERFLOW');
  797. a_label(list,hl);
  798. end;
  799. { *********** entry/exit code and address loading ************ }
  800. procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
  801. begin
  802. { Althogh the SPARC architecture require only word alignment, software
  803. convention and the operating system require every stack frame to be double word
  804. aligned }
  805. LocalSize:=align(LocalSize,8);
  806. { Execute the SAVE instruction to get a new register window and create a new
  807. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  808. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  809. after execution of that instruction is the called function stack pointer}
  810. list.concat(Taicpu.Op_reg_const_reg(A_SAVE,NR_STACK_POINTER_REG,aword(-LocalSize),NR_STACK_POINTER_REG));
  811. end;
  812. procedure TCgSparc.g_restore_all_registers(list:TaasmOutput;accused,acchiused:boolean);
  813. begin
  814. { The sparc port uses the sparc standard calling convetions so this function has no used }
  815. end;
  816. procedure TCgSparc.g_restore_frame_pointer(list:TAasmOutput);
  817. begin
  818. { This function intontionally does nothing as frame pointer is restored in the
  819. delay slot of the return instrucion done in g_return_from_proc}
  820. end;
  821. procedure TCgSparc.g_restore_standard_registers(list:taasmoutput);
  822. begin
  823. { The sparc port uses the sparc standard calling convetions so this function has no used }
  824. end;
  825. procedure TCgSparc.g_return_from_proc(list:TAasmOutput;parasize:aword);
  826. begin
  827. { According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  828. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  829. real RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  830. delay slot, so an inversion is possible such as
  831. RET (=JMPL %i7+8,%g0)
  832. RESTORE (=RESTORE %g0,0,%g0)
  833. If no inversion we can use just
  834. RESTORE (=RESTORE %g0,0,%g0)
  835. RET (=JMPL %i7+8,%g0)
  836. NOP
  837. }
  838. list.concat(Taicpu.op_none(A_RET));
  839. { We use trivial restore in the delay slot of the JMPL instruction, as we
  840. already set result onto %i0 }
  841. list.concat(Taicpu.op_none(A_RESTORE));
  842. end;
  843. procedure TCgSparc.g_save_all_registers(list : taasmoutput);
  844. begin
  845. { The sparc port uses the sparc standard calling convetions so this function has no used }
  846. end;
  847. procedure TCgSparc.g_save_standard_registers(list : taasmoutput);
  848. begin
  849. { The sparc port uses the sparc standard calling convetions so this function has no used }
  850. end;
  851. { ************* concatcopy ************ }
  852. procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean);
  853. var
  854. hreg,
  855. countreg: TRegister;
  856. src, dst: TReference;
  857. lab: tasmlabel;
  858. count, count2: aword;
  859. orgsrc, orgdst: boolean;
  860. begin
  861. if len > high(longint) then
  862. internalerror(2002072704);
  863. { make sure short loads are handled as optimally as possible }
  864. if not loadref then
  865. begin
  866. if (len <= 8) and (byte(len) in [1,2,4,8]) then
  867. begin
  868. if len < 8 then
  869. begin
  870. a_load_ref_ref(list,int_cgsize(len),int_cgsize(len),source,dest);
  871. if delsource then
  872. reference_release(list,source);
  873. end
  874. else
  875. begin
  876. a_reg_alloc(list,NR_F0);
  877. a_loadfpu_ref_reg(list,OS_F64,source,NR_F0);
  878. if delsource then
  879. reference_release(list,source);
  880. a_loadfpu_reg_ref(list,OS_F64,NR_F0,dest);
  881. a_reg_dealloc(list,NR_F0);
  882. end;
  883. exit;
  884. end;
  885. end;
  886. reference_reset(src);
  887. reference_reset(dst);
  888. { load the address of source into src.base }
  889. if loadref then
  890. begin
  891. src.base:=GetAddressRegister(list);
  892. a_load_ref_reg(list,OS_32,OS_32,source,src.base);
  893. orgsrc := false;
  894. end
  895. else
  896. if not issimpleref(source) or
  897. (
  898. (source.index<>NR_NO) and
  899. (((source.offset+longint(len))>simm13hi) or
  900. ((source.offset+longint(len))<simm13lo))
  901. ) then
  902. begin
  903. src.base:=GetAddressRegister(list);
  904. a_loadaddr_ref_reg(list,source,src.base);
  905. orgsrc := false;
  906. end
  907. else
  908. begin
  909. src := source;
  910. orgsrc := true;
  911. end;
  912. if not orgsrc and delsource then
  913. reference_release(list,source);
  914. { load the address of dest into dst.base }
  915. if not issimpleref(dest) or
  916. (
  917. (dest.index<>NR_NO) and
  918. (((dest.offset + longint(len)) > simm13hi) or
  919. ((dest.offset + longint(len)) < simm13lo))
  920. ) then
  921. begin
  922. dst.base:=GetAddressRegister(list);
  923. a_loadaddr_ref_reg(list,dest,dst.base);
  924. orgdst := false;
  925. end
  926. else
  927. begin
  928. dst := dest;
  929. orgdst := true;
  930. end;
  931. { generate a loop }
  932. count:=len div 8;
  933. if count>4 then
  934. begin
  935. { the offsets are zero after the a_loadaddress_ref_reg and just }
  936. { have to be set to 8. I put an Inc there so debugging may be }
  937. { easier (should offset be different from zero here, it will be }
  938. { easy to notice in the generated assembler }
  939. inc(dst.offset,8);
  940. inc(src.offset,8);
  941. list.concat(taicpu.op_reg_const_reg(A_SUB,src.base,8,src.base));
  942. list.concat(taicpu.op_reg_const_reg(A_SUB,dst.base,8,dst.base));
  943. countreg:=GetIntRegister(list,OS_INT);
  944. a_load_const_reg(list,OS_INT,count,countreg);
  945. { explicitely allocate R_O0 since it can be used safely here }
  946. { (for holding date that's being copied) }
  947. a_reg_alloc(list,NR_F0);
  948. objectlibrary.getlabel(lab);
  949. a_label(list, lab);
  950. list.concat(taicpu.op_reg_const_reg(A_SUB,countreg,1,countreg));
  951. list.concat(taicpu.op_ref_reg(A_LDF,src,NR_F0));
  952. list.concat(taicpu.op_reg_ref(A_STD,NR_F0,dst));
  953. //a_jmp(list,A_BC,C_NE,0,lab);
  954. UnGetRegister(list,countreg);
  955. a_reg_dealloc(list,NR_F0);
  956. len := len mod 8;
  957. end;
  958. { unrolled loop }
  959. count:=len and 7;
  960. if count>0 then
  961. begin
  962. a_reg_alloc(list,NR_F0);
  963. for count2 := 1 to count do
  964. begin
  965. a_loadfpu_ref_reg(list,OS_F64,src,NR_F0);
  966. a_loadfpu_reg_ref(list,OS_F64,NR_F0,dst);
  967. inc(src.offset,8);
  968. inc(dst.offset,8);
  969. end;
  970. a_reg_dealloc(list,NR_F0);
  971. len := len mod 8;
  972. end;
  973. if (len and 4) <> 0 then
  974. begin
  975. hreg:=GetIntRegister(list,OS_INT);
  976. a_load_ref_reg(list,OS_32,OS_32,src,hreg);
  977. a_load_reg_ref(list,OS_32,OS_32,hreg,dst);
  978. inc(src.offset,4);
  979. inc(dst.offset,4);
  980. UnGetRegister(list,hreg);
  981. end;
  982. { copy the leftovers }
  983. if (len and 2) <> 0 then
  984. begin
  985. hreg:=GetIntRegister(list,OS_INT);
  986. a_load_ref_reg(list,OS_16,OS_16,src,hreg);
  987. a_load_reg_ref(list,OS_16,OS_16,hreg,dst);
  988. inc(src.offset,2);
  989. inc(dst.offset,2);
  990. UnGetRegister(list,hreg);
  991. end;
  992. if (len and 1) <> 0 then
  993. begin
  994. hreg:=GetIntRegister(list,OS_INT);
  995. a_load_ref_reg(list,OS_8,OS_8,src,hreg);
  996. a_load_reg_ref(list,OS_8,OS_8,hreg,dst);
  997. UnGetRegister(list,hreg);
  998. end;
  999. if orgsrc then
  1000. begin
  1001. if delsource then
  1002. reference_release(list,source);
  1003. end
  1004. else
  1005. UnGetRegister(list,src.base);
  1006. if not orgdst then
  1007. UnGetRegister(list,dst.base);
  1008. end;
  1009. {****************************************************************************
  1010. TCG64Sparc
  1011. ****************************************************************************}
  1012. procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  1013. begin
  1014. case op of
  1015. OP_ADD :
  1016. begin
  1017. op1:=A_ADD;
  1018. op2:=A_ADDX;
  1019. end;
  1020. OP_SUB :
  1021. begin
  1022. op1:=A_SUB;
  1023. op2:=A_SUBX;
  1024. end;
  1025. OP_XOR :
  1026. begin
  1027. op1:=A_XOR;
  1028. op2:=A_XOR;
  1029. end;
  1030. OP_OR :
  1031. begin
  1032. op1:=A_OR;
  1033. op2:=A_OR;
  1034. end;
  1035. OP_AND :
  1036. begin
  1037. op1:=A_AND;
  1038. op2:=A_AND;
  1039. end;
  1040. else
  1041. internalerror(200203241);
  1042. end;
  1043. end;
  1044. procedure TCg64Sparc.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  1045. var
  1046. op1,op2 : TAsmOp;
  1047. begin
  1048. case op of
  1049. OP_NEG :
  1050. begin
  1051. list.concat(taicpu.op_reg_reg_reg(A_XNOR,NR_G0,regsrc.reghi,regdst.reghi));
  1052. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,NR_G0,regsrc.reglo,regdst.reglo));
  1053. list.concat(taicpu.op_reg_const_reg(A_ADDX,regdst.reglo,aword(-1),regdst.reglo));
  1054. exit;
  1055. end;
  1056. OP_NOT :
  1057. begin
  1058. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reglo,NR_G0,regdst.reglo));
  1059. list.concat(taicpu.op_reg_reg_reg(A_XNOR,regsrc.reghi,NR_G0,regdst.reghi));
  1060. exit;
  1061. end;
  1062. end;
  1063. get_64bit_ops(op,op1,op2);
  1064. list.concat(taicpu.op_reg_reg_reg(op1,regdst.reglo,regsrc.reglo,regdst.reglo));
  1065. list.concat(taicpu.op_reg_reg_reg(op2,regdst.reghi,regsrc.reghi,regdst.reghi));
  1066. end;
  1067. procedure TCg64Sparc.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  1068. var
  1069. op1,op2:TAsmOp;
  1070. begin
  1071. case op of
  1072. OP_NEG,
  1073. OP_NOT :
  1074. internalerror(200306017);
  1075. end;
  1076. get_64bit_ops(op,op1,op2);
  1077. tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reglo,lo(value),regdst.reglo);
  1078. tcgsparc(cg).handle_reg_const_reg(list,op1,regdst.reghi,hi(value),regdst.reghi);
  1079. end;
  1080. begin
  1081. cg:=TCgSparc.Create;
  1082. cg64:=TCg64Sparc.Create;
  1083. end.
  1084. {
  1085. $Log$
  1086. Revision 1.72 2003-10-29 15:18:33 mazen
  1087. + added fake MM Registers support because of generic code need it.
  1088. Revision 1.71 2003/10/24 15:20:37 peter
  1089. * added more register functions
  1090. Revision 1.70 2003/10/24 11:14:46 mazen
  1091. * rg.[un]GetRegister* ==> [Un]Get[*]Register
  1092. Revision 1.69 2003/10/01 20:34:49 peter
  1093. * procinfo unit contains tprocinfo
  1094. * cginfo renamed to cgbase
  1095. * moved cgmessage to verbose
  1096. * fixed ppc and sparc compiles
  1097. Revision 1.68 2003/09/14 21:35:52 peter
  1098. * flags2reg fixed
  1099. * fixed 64bit not
  1100. Revision 1.67 2003/09/14 19:19:04 peter
  1101. * updates for new ra
  1102. Revision 1.66 2003/09/03 15:55:01 peter
  1103. * NEWRA branch merged
  1104. Revision 1.65.2.1 2003/09/01 21:02:55 peter
  1105. * sparc updates for new tregister
  1106. Revision 1.65 2003/07/08 21:24:59 peter
  1107. * sparc fixes
  1108. Revision 1.64 2003/07/06 22:10:13 peter
  1109. * operand order of cmp fixed
  1110. Revision 1.63 2003/07/06 17:58:22 peter
  1111. * framepointer fixes for sparc
  1112. * parent framepointer code more generic
  1113. Revision 1.62 2003/07/03 21:09:53 peter
  1114. * delay slot NOPs and comments added
  1115. * a_loadaddr_ref_reg fixed and optimized to reuse passed register
  1116. if it is not used by the ref
  1117. Revision 1.61 2003/07/02 22:18:04 peter
  1118. * paraloc splitted in callerparaloc,calleeparaloc
  1119. * sparc calling convention updates
  1120. Revision 1.60 2003/06/17 16:35:56 peter
  1121. * a_loadaddr_ref_reg fixed
  1122. Revision 1.59 2003/06/13 21:19:32 peter
  1123. * current_procdef removed, use current_procinfo.procdef instead
  1124. Revision 1.58 2003/06/12 16:43:07 peter
  1125. * newra compiles for sparc
  1126. Revision 1.57 2003/06/04 20:59:37 mazen
  1127. + added size of destination in code gen methods
  1128. + making g_overflowcheck declaration same as
  1129. ancestor's method declaration
  1130. Revision 1.56 2003/06/01 21:38:06 peter
  1131. * getregisterfpu size parameter added
  1132. * op_const_reg size parameter added
  1133. * sparc updates
  1134. Revision 1.55 2003/06/01 01:04:35 peter
  1135. * reference fixes
  1136. Revision 1.54 2003/05/31 01:00:51 peter
  1137. * register fixes
  1138. Revision 1.53 2003/05/30 23:57:08 peter
  1139. * more sparc cleanup
  1140. * accumulator removed, splitted in function_return_reg (called) and
  1141. function_result_reg (caller)
  1142. Revision 1.52 2003/05/28 23:18:31 florian
  1143. * started to fix and clean up the sparc port
  1144. Revision 1.51 2003/05/26 22:04:57 mazen
  1145. * added 64 bit value support to fix a problem in RTL
  1146. Revision 1.50 2003/05/23 22:33:48 florian
  1147. * fix some small flaws which prevent sparc linux system unit from compiling
  1148. * some reformatting done
  1149. Revision 1.49 2003/05/22 16:11:22 florian
  1150. * fixed sparc compilation partially
  1151. Revision 1.48 2003/05/07 15:04:30 mazen
  1152. * invalid genrated code for CASE statement fixed
  1153. Revision 1.47 2003/05/06 20:25:20 mazen
  1154. * Invalid genrated code : A_JMPL changed to A_BA
  1155. Revision 1.46 2003/05/06 15:02:40 mazen
  1156. * fixed a bug in a_load_const_reg related to max 13bit value limit
  1157. for immediat value ==> use of A_SETHI for greater values
  1158. Revision 1.45 2003/04/29 11:58:21 mazen
  1159. * fixed bug of output generated assembler for a_cmp_const_ref_label
  1160. Revision 1.44 2003/04/28 09:44:42 mazen
  1161. + NOP after conditional jump instruction to prevent delay slot execution
  1162. Revision 1.43 2003/04/27 11:21:36 peter
  1163. * aktprocdef renamed to current_procinfo.procdef
  1164. * procinfo renamed to current_procinfo
  1165. * procinfo will now be stored in current_module so it can be
  1166. cleaned up properly
  1167. * gen_main_procsym changed to create_main_proc and release_main_proc
  1168. to also generate a tprocinfo structure
  1169. * fixed unit implicit initfinal
  1170. Revision 1.42 2003/03/16 20:45:45 mazen
  1171. * fixing an LD operation without refernce in loading address parameters
  1172. Revision 1.41 2003/03/10 21:59:54 mazen
  1173. * fixing index overflow in handling new registers arrays.
  1174. Revision 1.40 2003/02/25 21:41:44 mazen
  1175. * code re-aligned 2 spaces
  1176. Revision 1.39 2003/02/19 22:00:16 daniel
  1177. * Code generator converted to new register notation
  1178. - Horribily outdated todo.txt removed
  1179. Revision 1.38 2003/02/18 22:00:20 mazen
  1180. * asm condition generation modified by TAiCpu.SetCondition
  1181. Revision 1.37 2003/02/05 21:48:34 mazen
  1182. * fixing run time errors related to unimplemented abstract methods in CG
  1183. + giving empty emplementations for some RTL functions
  1184. Revision 1.36 2003/01/22 22:30:03 mazen
  1185. - internal errors rmoved from a_loar_reg_reg when reg sizes differs from 32
  1186. Revision 1.35 2003/01/20 22:21:36 mazen
  1187. * many stuff related to RTL fixed
  1188. Revision 1.34 2003/01/08 18:43:58 daniel
  1189. * Tregister changed into a record
  1190. Revision 1.33 2003/01/07 22:03:40 mazen
  1191. * adding unequaln node support to sparc compiler
  1192. Revision 1.32 2003/01/06 22:51:47 mazen
  1193. * fixing bugs related to load_reg_ref
  1194. Revision 1.31 2003/01/05 21:32:35 mazen
  1195. * fixing several bugs compiling the RTL
  1196. Revision 1.30 2003/01/05 13:36:53 florian
  1197. * x86-64 compiles
  1198. + very basic support for float128 type (x86-64 only)
  1199. Revision 1.29 2002/12/25 20:59:49 mazen
  1200. - many emitXXX removed from cga.pas in order to remove that file.
  1201. Revision 1.28 2002/12/22 19:26:31 mazen
  1202. * many internal errors related to unimplemented nodes are fixed
  1203. Revision 1.27 2002/12/21 23:21:47 mazen
  1204. + added support for the shift nodes
  1205. + added debug output on screen with -an command line option
  1206. Revision 1.26 2002/11/25 19:21:49 mazen
  1207. * fixed support of nSparcInline
  1208. Revision 1.25 2002/11/25 17:43:28 peter
  1209. * splitted defbase in defutil,symutil,defcmp
  1210. * merged isconvertable and is_equal into compare_defs(_ext)
  1211. * made operator search faster by walking the list only once
  1212. Revision 1.24 2002/11/17 17:49:09 mazen
  1213. + 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
  1214. Revision 1.23 2002/11/10 19:07:46 mazen
  1215. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1216. Revision 1.22 2002/11/06 11:31:24 mazen
  1217. * op_reg_reg_reg don't need any more a TOpSize parameter
  1218. Revision 1.21 2002/11/05 16:15:00 mazen
  1219. *** empty log message ***
  1220. Revision 1.20 2002/11/03 20:22:40 mazen
  1221. * parameter handling updated
  1222. Revision 1.19 2002/10/28 20:59:17 mazen
  1223. * TOpSize values changed S_L --> S_SW
  1224. Revision 1.18 2002/10/22 13:43:01 mazen
  1225. - cga.pas redueced to an empty unit
  1226. Revision 1.17 2002/10/20 19:01:38 mazen
  1227. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1228. Revision 1.16 2002/10/13 21:46:07 mazen
  1229. * assembler output format fixed
  1230. Revision 1.15 2002/10/11 13:35:14 mazen
  1231. *** empty log message ***
  1232. Revision 1.14 2002/10/10 19:57:51 mazen
  1233. * Just to update repsitory
  1234. Revision 1.13 2002/10/10 15:10:39 mazen
  1235. * Internal error fixed, but usually i386 parameter model used
  1236. Revision 1.12 2002/10/08 17:17:03 mazen
  1237. *** empty log message ***
  1238. Revision 1.11 2002/10/07 20:33:04 mazen
  1239. word alignement modified in g_stack_frame
  1240. Revision 1.10 2002/10/04 21:57:42 mazen
  1241. * register allocation for parameters now done in cpupara
  1242. Revision 1.9 2002/10/02 22:20:28 mazen
  1243. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1244. Revision 1.8 2002/10/01 21:35:58 mazen
  1245. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1246. Revision 1.7 2002/10/01 21:06:29 mazen
  1247. attinst.inc --> strinst.inc
  1248. Revision 1.6 2002/10/01 17:41:50 florian
  1249. * fixed log and id
  1250. }