cgcpu.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612
  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;sz:tcgsize;r:tregister;const LocPara:TParaLocation);override;
  34. {passes a parameter which is a constant to a function}
  35. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);override;
  36. procedure a_param_ref(list:TAasmOutput;sz:tcgsize;CONST r:TReference;CONST LocPara:TParaLocation);override;
  37. procedure a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);override;
  38. procedure a_call_name(list:TAasmOutput;CONST s:string);override;
  39. procedure a_call_ref(list:TAasmOutput;CONST ref:TReference);override;
  40. procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override;
  41. {Branch Instruction}
  42. procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
  43. {General purpose instyructions}
  44. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override;
  45. procedure a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);override;
  46. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  47. procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);override;
  48. procedure a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);override;
  49. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  50. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  51. { move instructions }
  52. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  53. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);override;
  54. procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  55. procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  56. procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override;
  57. procedure a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);override;
  58. { fpu move instructions }
  59. procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  60. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);override;
  61. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;CONST ref:TReference);override;
  62. { vector register move instructions }
  63. procedure a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  64. procedure a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);override;
  65. procedure a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);override;
  66. procedure a_parammm_reg(list:TAasmOutput;reg:tregister);override;
  67. { comparison operations }
  68. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  69. procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;CONST ref:TReference;l:tasmlabel);override;
  70. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  71. procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);override;
  72. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  73. procedure a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);override;
  74. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);override;
  75. procedure g_overflowCheck(List:TAasmOutput;const p:TNode);override;
  76. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  77. procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override;
  78. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  79. procedure g_restore_standard_registers(list:taasmoutput;usedinproc:Tsupregset);override;
  80. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  81. procedure g_save_all_registers(list : taasmoutput);override;
  82. procedure g_save_standard_registers(list : taasmoutput; usedinproc : Tsupregset);override;
  83. procedure g_concatcopy(list:TAasmOutput;CONST source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  84. class function reg_cgsize(CONST reg:tregister):tcgsize;override;
  85. PRIVATE
  86. function IsSimpleRef(const ref:treference):boolean;
  87. procedure sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  88. procedure floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  89. procedure floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  90. procedure floatloadops(t:tcgsize;var op:tasmop;var s:topsize);
  91. procedure floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  92. END;
  93. TCg64Sparc=class(tcg64f32)
  94. procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);override;
  95. procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override;
  96. procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override;
  97. procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;CONST ref:TReference);override;
  98. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  99. END;
  100. CONST
  101. 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);
  102. 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);
  103. 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,S_NO);
  104. IMPLEMENTATION
  105. USES
  106. globtype,globals,verbose,systems,cutils,
  107. symdef,symsym,defutil,paramgr,
  108. rgobj,tgobj,rgcpu,cpupi;
  109. procedure TCgSparc.a_param_reg(list:TAasmOutput;sz:tcgsize;r:tregister;const LocPara:TParaLocation);
  110. var
  111. r2:Tregister;
  112. begin
  113. r2.enum:=R_G0;
  114. with list,LocPara do
  115. case Loc of
  116. LOC_REGISTER:
  117. case Sz of
  118. OS_8,OS_S8:
  119. Concat(taicpu.op_Reg_Const_Reg(A_AND,r,$FF,Register));
  120. OS_16,OS_S16:
  121. begin
  122. Concat(taicpu.op_Reg_Reg_Reg(A_AND,r,r2,Register));
  123. {This will put 00...00111 in the hiest 22 bits of the reg}
  124. Concat(taicpu.op_Reg_Const_Reg(A_SETHI,Register,$7,Register));
  125. end;
  126. OS_32,OS_S32:
  127. if r.enum<>Register.enum
  128. then
  129. Concat(taicpu.op_Reg_Reg_Reg(A_OR,r,r2,Register));
  130. else
  131. InternalError(2002032212);
  132. end;
  133. else
  134. InternalError(2002101002);
  135. end;
  136. end;
  137. procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;CONST LocPara:TParaLocation);
  138. var
  139. Ref:TReference;
  140. begin
  141. with List do
  142. case locpara.loc of
  143. LOC_REGISTER,LOC_CREGISTER:
  144. a_load_const_reg(list,size,a,locpara.register);
  145. LOC_REFERENCE:
  146. begin
  147. reference_reset(ref);
  148. ref.base:=locpara.reference.index;
  149. ref.offset:=locpara.reference.offset;
  150. a_load_const_ref(list,size,a,ref);
  151. end;
  152. else
  153. InternalError(2002122200);
  154. end;
  155. if locpara.sp_fixup<>0
  156. then
  157. InternalError(2002122201);
  158. end;
  159. procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation);
  160. var
  161. ref: treference;
  162. tmpreg:TRegister;
  163. begin
  164. with LocPara do
  165. case locpara.loc of
  166. LOC_REGISTER,LOC_CREGISTER:
  167. a_load_ref_reg(list,sz,r,Register);
  168. LOC_REFERENCE:
  169. begin
  170. {Code conventions need the parameters being allocated in %o6+92. See
  171. comment on g_stack_frame}
  172. if locpara.sp_fixup<92
  173. then
  174. InternalError(2002081104);
  175. reference_reset(ref);
  176. ref.base:=locpara.reference.index;
  177. ref.offset:=locpara.reference.offset;
  178. tmpreg := get_scratch_reg_int(list,sz);
  179. a_load_ref_reg(list,sz,r,tmpreg);
  180. a_load_reg_ref(list,sz,tmpreg,ref);
  181. free_scratch_reg(list,tmpreg);
  182. end;
  183. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  184. case sz of
  185. OS_32:
  186. a_loadfpu_ref_reg(list,OS_F32,r,locpara.register);
  187. OS_64:
  188. a_loadfpu_ref_reg(list,OS_F64,r,locpara.register);
  189. else
  190. internalerror(2002072801);
  191. end;
  192. else
  193. internalerror(2002081103);
  194. end;
  195. end;
  196. procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;CONST r:TReference;CONST LocPara:TParaLocation);
  197. var
  198. Ref:TReference;
  199. TmpReg:TRegister;
  200. begin
  201. case locpara.loc of
  202. LOC_REGISTER,LOC_CREGISTER:
  203. a_loadaddr_ref_reg(list,r,locpara.register);
  204. LOC_REFERENCE:
  205. begin
  206. reference_reset(ref);
  207. ref.base := locpara.reference.index;
  208. ref.offset := locpara.reference.offset;
  209. tmpreg := get_scratch_reg_address(list);
  210. a_loadaddr_ref_reg(list,r,tmpreg);
  211. a_load_reg_ref(list,OS_ADDR,tmpreg,ref);
  212. free_scratch_reg(list,tmpreg);
  213. end;
  214. else
  215. internalerror(2002080701);
  216. end;
  217. end;
  218. procedure TCgSparc.a_call_name(list:TAasmOutput;CONST s:string);
  219. BEGIN
  220. WITH List,objectlibrary DO
  221. BEGIN
  222. concat(taicpu.op_sym(A_CALL,S_SW,newasmsymbol(s)));
  223. concat(taicpu.op_none(A_NOP));
  224. END;
  225. END;
  226. procedure TCgSparc.a_call_ref(list:TAasmOutput;CONST ref:TReference);
  227. begin
  228. list.concat(taicpu.op_ref(A_CALL,ref));
  229. list.concat(taicpu.op_none(A_NOP));
  230. end;
  231. procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister);
  232. var
  233. RetAddrReg:TRegister;
  234. begin
  235. with RetAddrReg do
  236. begin
  237. enum:=R_INTREGISTER;
  238. Number:=NR_O7;
  239. end;
  240. list.concat(taicpu.op_reg_reg(A_JMPL,reg,RetAddrReg));
  241. if target_info.system=system_sparc_linux
  242. then
  243. list.concat(taicpu.op_none(A_NOP));
  244. include(current_procinfo.flags,pi_do_call);
  245. end;
  246. {********************** branch instructions ********************}
  247. procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
  248. begin
  249. List.Concat(TAiCpu.op_sym(A_BA,S_NO,objectlibrary.newasmsymbol(l.name)));
  250. end;
  251. {********************** load instructions ********************}
  252. procedure TCgSparc.a_load_const_reg(list:TAasmOutput;size:TCGSize;a:aword;reg:TRegister);
  253. var
  254. r:Tregister;
  255. begin
  256. r.enum:=R_G0;
  257. with List do
  258. if a=0
  259. then{R_G0 is usually set to zero, so we use it}
  260. Concat(taicpu.op_reg_reg_reg(A_OR,r,r,reg))
  261. else{There is no A_MOV in sparc, that's why we use A_OR with help of R_G0}
  262. begin
  263. Concat(taicpu.op_reg_const_reg(A_OR,r,a and $00001FFF,reg));
  264. a:=a and $FFFFE000;
  265. if a<>0
  266. then
  267. Concat(taicpu.op_const_reg(A_SETHI,a,reg));
  268. end;
  269. END;
  270. procedure TCgSparc.a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;CONST ref:TReference);
  271. var r:Tregister;
  272. BEGIN
  273. r.enum:=R_G0;
  274. WITH List DO
  275. IF a=0
  276. THEN
  277. Concat(taicpu.op_reg_ref(A_ST,r,Ref))
  278. ELSE
  279. BEGIN
  280. r.enum:=R_G1;
  281. a_load_const_reg(list,size,a,r);
  282. a_load_reg_ref(list,size,r,Ref);
  283. END;
  284. END;
  285. procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;const Ref:TReference);
  286. var
  287. op:tasmop;
  288. begin
  289. case size of
  290. { signed integer registers }
  291. OS_S8:
  292. Op:=A_STB;{Store Signed Byte}
  293. OS_S16:
  294. Op:=A_STH;{Store Signed Halfword}
  295. OS_S32:
  296. Op:=A_ST;{Store Word}
  297. OS_S64:
  298. Op:=A_STD;{Store Double Word}
  299. { unsigned integer registers }
  300. //A_STSTUB;{Store-Store Unsigned Byte}
  301. OS_8:
  302. Op:=A_STB;{Store Unsigned Bye}
  303. OS_16:
  304. Op:=A_STH;{Store Unsigned Halfword}
  305. OS_32:
  306. Op:=A_ST;{Store Word}
  307. OS_64:
  308. Op:=A_STD;{Store Double Word}
  309. { floating-point real registers }
  310. OS_F32:
  311. Op:=A_STF;{Store Floating-point word}
  312. //A_STFSR
  313. OS_F64:
  314. Op:=A_STDF;{Store Double Floating-point word}
  315. //A_STC;{Store Coprocessor}
  316. //A_STCSR;
  317. //A_STDC;{Store Double Coprocessor}
  318. else
  319. InternalError(2002122100);
  320. end;
  321. with list do
  322. concat(taicpu.op_reg_ref(op,reg,ref));
  323. end;
  324. procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;size:TCgSize;const ref:TReference;reg:tregister);
  325. var
  326. op:tasmop;
  327. begin
  328. case size of
  329. { signed integer registers }
  330. OS_S8:
  331. Op:=A_LDSB;{Load Signed Byte}
  332. OS_S16:
  333. Op:=A_LDSH;{Load Signed Halfword}
  334. OS_S32:
  335. Op:=A_LD;{Load Word}
  336. OS_S64:
  337. Op:=A_LDD;{Load Double Word}
  338. { unsigned integer registers }
  339. //A_LDSTUB;{Load-Store Unsigned Byte}
  340. OS_8:
  341. Op:=A_LDUB;{Load Unsigned Bye}
  342. OS_16:
  343. Op:=A_LDUH;{Load Unsigned Halfword}
  344. OS_32:
  345. Op:=A_LD;{Load Word}
  346. OS_64:
  347. Op:=A_LDD;{Load Double Word}
  348. { floating-point real registers }
  349. OS_F32:
  350. Op:=A_LDF;{Load Floating-point word}
  351. //A_LDFSR
  352. OS_F64:
  353. Op:=A_LDDF;{Load Double Floating-point word}
  354. //A_LDC;{Load Coprocessor}
  355. //A_LDCSR;
  356. //A_LDDC;{Load Double Coprocessor}
  357. else
  358. InternalError(2002122100);
  359. end;
  360. with list do
  361. concat(taicpu.op_ref_reg(op,ref,reg));
  362. end;
  363. procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  364. var
  365. op:tasmop;
  366. s:topsize;
  367. r:Tregister;
  368. begin
  369. r.enum:=R_G0;
  370. if(reg1.enum<>reg2.enum)or
  371. (tcgsize2size[tosize]<tcgsize2size[fromsize])or
  372. ((tcgsize2size[tosize] = tcgsize2size[fromsize])and
  373. (tosize <> fromsize)and
  374. not(fromsize in [OS_32,OS_S32]))
  375. then
  376. with list do
  377. case fromsize of
  378. OS_8,OS_S8,OS_16,OS_S16,OS_32,OS_S32:
  379. concat(taicpu.op_reg_reg_reg(A_OR,r,reg1,reg2));
  380. else internalerror(2002090901);
  381. end;
  382. end;
  383. { all fpu load routines expect that R_ST[0-7] means an fpu regvar and }
  384. { R_ST means "the current value at the top of the fpu stack" (JM) }
  385. procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  386. begin
  387. { if NOT (reg1 IN [R_F0..R_F31]) then
  388. begin
  389. list.concat(taicpu.op_reg(A_NONE,S_NO,
  390. trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset)));
  391. inc(trgcpu(rg).fpuvaroffset);
  392. end;
  393. if NOT (reg2 IN [R_F0..R_F31]) then
  394. begin
  395. list.concat(taicpu.op_reg(A_JMPL,S_NO,
  396. trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset)));
  397. dec(trgcpu(rg).fpuvaroffset);
  398. end;}
  399. end;
  400. procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;CONST ref:TReference;reg:tregister);
  401. begin
  402. floatload(list,size,ref);
  403. { if (reg <> R_ST) then
  404. a_loadfpu_reg_reg(list,R_ST,reg);}
  405. end;
  406. procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);
  407. const
  408. FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
  409. { indexed? updating?}
  410. (((A_STF,A_STF),(A_STF,A_STF)),
  411. ((A_STDF,A_STDF),(A_STDF,A_STDF)));
  412. var
  413. op: tasmop;
  414. ref2: treference;
  415. freereg: boolean;
  416. begin
  417. if not(size in [OS_F32,OS_F64])
  418. then
  419. internalerror(200201122);
  420. { ref2:=ref;
  421. freereg:=fixref(list,ref2);
  422. op:=fpustoreinstr[size,ref2.index.enum <> R_NO,false];
  423. a_load_store(list,op,reg,ref2);
  424. if freereg
  425. then
  426. cg.free_scratch_reg(list,ref2.base);}
  427. end;
  428. procedure TCgSparc.a_loadmm_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  429. begin
  430. // list.concat(taicpu.op_reg_reg(A_NONEQ,S_NO,reg1,reg2));
  431. end;
  432. procedure TCgSparc.a_loadmm_ref_reg(list:TAasmOutput;CONST ref:TReference;reg:tregister);
  433. begin
  434. // list.concat(taicpu.op_ref_reg(A_NONEQ,S_NO,ref,reg));
  435. end;
  436. procedure TCgSparc.a_loadmm_reg_ref(list:TAasmOutput;reg:tregister;CONST ref:TReference);
  437. begin
  438. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,ref));
  439. end;
  440. procedure TCgSparc.a_parammm_reg(list:TAasmOutput;reg:tregister);
  441. VAR
  442. href:TReference;
  443. BEGIN
  444. // list.concat(taicpu.op_const_reg(A_SUB,S_SW,8,R_RSP));
  445. // reference_reset_base(href,R_ESP,0);
  446. // list.concat(taicpu.op_reg_ref(A_NONEQ,S_NO,reg,href));
  447. END;
  448. procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);
  449. var
  450. opcode:tasmop;
  451. power:LongInt;
  452. begin
  453. (* Case Op of
  454. OP_DIV, OP_IDIV:
  455. Begin
  456. if ispowerof2(a,power) then
  457. begin
  458. case op of
  459. OP_DIV:
  460. opcode := A_SHR;
  461. OP_IDIV:
  462. opcode := A_SAR;
  463. end;
  464. list.concat(taicpu.op_const_reg(opcode,S_SW,power,
  465. reg));
  466. exit;
  467. end;
  468. { the rest should be handled specifically in the code }
  469. { generator because of the silly register usage restraints }
  470. internalerror(200109224);
  471. End;
  472. OP_MUL,OP_IMUL:
  473. begin
  474. if not(cs_check_overflow in aktlocalswitches) and
  475. ispowerof2(a,power) then
  476. begin
  477. list.concat(taicpu.op_const_reg(A_SHL,S_SW,power,
  478. reg));
  479. exit;
  480. end;
  481. if op = OP_IMUL then
  482. list.concat(taicpu.op_const_reg(A_IMUL,S_SW,
  483. a,reg))
  484. else
  485. { OP_MUL should be handled specifically in the code }
  486. { generator because of the silly register usage restraints }
  487. internalerror(200109225);
  488. end;
  489. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  490. if not(cs_check_overflow in aktlocalswitches) and
  491. (a = 1) and
  492. (op in [OP_ADD,OP_SUB]) then
  493. if op = OP_ADD then
  494. list.concat(taicpu.op_reg(A_INC,S_SW,reg))
  495. else
  496. list.concat(taicpu.op_reg(A_DEC,S_SW,reg))
  497. else if (a = 0) then
  498. if (op <> OP_AND) then
  499. exit
  500. else
  501. list.concat(taicpu.op_const_reg(A_NONE,S_SW,0,reg))
  502. else if (a = high(aword)) and
  503. (op in [OP_AND,OP_OR,OP_XOR]) then
  504. begin
  505. case op of
  506. OP_AND:
  507. exit;
  508. OP_OR:
  509. list.concat(taicpu.op_const_reg(A_NONE,S_SW,high(aword),reg));
  510. OP_XOR:
  511. list.concat(taicpu.op_reg(A_NOT,S_SW,reg));
  512. end
  513. end
  514. else
  515. list.concat(taicpu.op_const_reg(TOpCG2AsmOp[op],S_SW,
  516. a,reg));
  517. OP_SHL,OP_SHR,OP_SAR:
  518. begin
  519. if (a and 31) <> 0 Then
  520. list.concat(taicpu.op_const_reg(
  521. TOpCG2AsmOp[op],S_SW,a and 31,reg));
  522. if (a shr 5) <> 0 Then
  523. internalerror(68991);
  524. end
  525. else internalerror(68992);
  526. end;*)
  527. end;
  528. procedure TCgSparc.a_op_const_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;a:AWord;CONST ref:TReference);
  529. var
  530. opcode:tasmop;
  531. power:LongInt;
  532. begin
  533. (* Case Op of
  534. OP_DIV, OP_IDIV:
  535. Begin
  536. if ispowerof2(a,power) then
  537. begin
  538. case op of
  539. OP_DIV:
  540. opcode := A_SHR;
  541. OP_IDIV:
  542. opcode := A_SAR;
  543. end;
  544. list.concat(taicpu.op_const_ref(opcode,
  545. TCgSize2OpSize[size],power,ref));
  546. exit;
  547. end;
  548. { the rest should be handled specifically in the code }
  549. { generator because of the silly register usage restraints }
  550. internalerror(200109231);
  551. End;
  552. OP_MUL,OP_IMUL:
  553. begin
  554. if not(cs_check_overflow in aktlocalswitches) and
  555. ispowerof2(a,power) then
  556. begin
  557. list.concat(taicpu.op_const_ref(A_SHL,TCgSize2OpSize[size],
  558. power,ref));
  559. exit;
  560. end;
  561. { can't multiply a memory location directly with a CONSTant }
  562. if op = OP_IMUL then
  563. inherited a_op_const_ref(list,op,size,a,ref)
  564. else
  565. { OP_MUL should be handled specifically in the code }
  566. { generator because of the silly register usage restraints }
  567. internalerror(200109232);
  568. end;
  569. OP_ADD, OP_AND, OP_OR, OP_SUB, OP_XOR:
  570. if not(cs_check_overflow in aktlocalswitches) and
  571. (a = 1) and
  572. (op in [OP_ADD,OP_SUB]) then
  573. if op = OP_ADD then
  574. list.concat(taicpu.op_ref(A_INC,TCgSize2OpSize[size],ref))
  575. else
  576. list.concat(taicpu.op_ref(A_DEC,TCgSize2OpSize[size],ref))
  577. else if (a = 0) then
  578. if (op <> OP_AND) then
  579. exit
  580. else
  581. a_load_const_ref(list,size,0,ref)
  582. else if (a = high(aword)) and
  583. (op in [OP_AND,OP_OR,OP_XOR]) then
  584. begin
  585. case op of
  586. OP_AND:
  587. exit;
  588. OP_OR:
  589. list.concat(taicpu.op_const_ref(A_NONE,TCgSize2OpSize[size],high(aword),ref));
  590. OP_XOR:
  591. list.concat(taicpu.op_ref(A_NOT,TCgSize2OpSize[size],ref));
  592. end
  593. end
  594. else
  595. list.concat(taicpu.op_const_ref(TOpCG2AsmOp[op],
  596. TCgSize2OpSize[size],a,ref));
  597. OP_SHL,OP_SHR,OP_SAR:
  598. begin
  599. if (a and 31) <> 0 Then
  600. list.concat(taicpu.op_const_ref(
  601. TOpCG2AsmOp[op],TCgSize2OpSize[size],a and 31,ref));
  602. if (a shr 5) <> 0 Then
  603. internalerror(68991);
  604. end
  605. else internalerror(68992);
  606. end;*)
  607. end;
  608. procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  609. var
  610. regloadsize:tcgsize;
  611. dstsize:topsize;
  612. tmpreg:tregister;
  613. popecx:boolean;
  614. begin
  615. (* dstsize := S_Q{makeregsize(dst,size)};
  616. case op of
  617. OP_NEG,OP_NOT:
  618. begin
  619. if src <> R_NO then
  620. internalerror(200112291);
  621. list.concat(taicpu.op_reg(TOpCG2AsmOp[op],dstsize,dst));
  622. end;
  623. OP_MUL,OP_DIV,OP_IDIV:
  624. { special stuff, needs separate handling inside code }
  625. { generator }
  626. internalerror(200109233);
  627. OP_SHR,OP_SHL,OP_SAR:
  628. begin
  629. tmpreg := R_NO;
  630. { we need cl to hold the shift count, so if the destination }
  631. { is ecx, save it to a temp for now }
  632. if dst in [R_ECX,R_CX,R_CL] then
  633. begin
  634. case S_SW of
  635. S_B:regloadsize := OS_8;
  636. S_W:regloadsize := OS_16;
  637. else regloadsize := OS_32;
  638. end;
  639. tmpreg := get_scratch_reg(list);
  640. a_load_reg_reg(list,regloadsize,OS_32,src,tmpreg);
  641. end;
  642. if not(src in [R_ECX,R_CX,R_CL]) then
  643. begin
  644. { is ecx still free (it's also free if it was allocated }
  645. { to dst, since we've moved dst somewhere else already) }
  646. if not((dst = R_ECX) or
  647. ((R_ECX in rg.unusedregsint) and
  648. { this will always be true, it's just here to }
  649. { allocate ecx }
  650. (rg.getexplicitregisterint(list,R_ECX) = R_ECX))) then
  651. begin
  652. list.concat(taicpu.op_reg(A_NONE,S_SW,R_ECX));
  653. popecx := true;
  654. end;
  655. a_load_reg_reg(list,OS_8,OS_8,(src),R_CL);
  656. end
  657. else
  658. src := R_CL;
  659. { do the shift }
  660. if tmpreg = R_NO then
  661. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  662. R_CL,dst))
  663. else
  664. begin
  665. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],S_SW,
  666. R_CL,tmpreg));
  667. { move result back to the destination }
  668. a_load_reg_reg(list,OS_32,OS_32,tmpreg,R_ECX);
  669. free_scratch_reg(list,tmpreg);
  670. end;
  671. if popecx then
  672. list.concat(taicpu.op_reg(A_POP,S_SW,R_ECX))
  673. else if not (dst in [R_ECX,R_CX,R_CL]) then
  674. rg.ungetregisterint(list,R_ECX);
  675. end;
  676. else
  677. begin
  678. if S_SW <> dstsize then
  679. internalerror(200109226);
  680. list.concat(taicpu.op_reg_reg(TOpCG2AsmOp[op],dstsize,
  681. src,dst));
  682. end;
  683. end;*)
  684. end;
  685. procedure TCgSparc.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;CONST ref:TReference;reg:TRegister);
  686. var
  687. opsize:topsize;
  688. begin
  689. (* case op of
  690. OP_NEG,OP_NOT,OP_IMUL:
  691. begin
  692. inherited a_op_ref_reg(list,op,size,ref,reg);
  693. end;
  694. OP_MUL,OP_DIV,OP_IDIV:
  695. { special stuff, needs separate handling inside code }
  696. { generator }
  697. internalerror(200109239);
  698. else
  699. begin
  700. opsize := S_Q{makeregsize(reg,size)};
  701. list.concat(taicpu.op_ref_reg(TOpCG2AsmOp[op],opsize,ref,reg));
  702. end;
  703. end;*)
  704. end;
  705. procedure TCgSparc.a_op_reg_ref(list:TAasmOutput;Op:TOpCG;size:TCGSize;reg:TRegister;CONST ref:TReference);
  706. var
  707. opsize:topsize;
  708. begin
  709. (* case op of
  710. OP_NEG,OP_NOT:
  711. begin
  712. if reg <> R_NO then
  713. internalerror(200109237);
  714. list.concat(taicpu.op_ref(TOpCG2AsmOp[op],tcgsize2opsize[size],ref));
  715. end;
  716. OP_IMUL:
  717. begin
  718. { this one needs a load/imul/store, which is the default }
  719. inherited a_op_ref_reg(list,op,size,ref,reg);
  720. end;
  721. OP_MUL,OP_DIV,OP_IDIV:
  722. { special stuff, needs separate handling inside code }
  723. { generator }
  724. internalerror(200109238);
  725. else
  726. begin
  727. opsize := tcgsize2opsize[size];
  728. list.concat(taicpu.op_reg_ref(TOpCG2AsmOp[op],opsize,reg,ref));
  729. end;
  730. end;*)
  731. end;
  732. procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;
  733. size:tcgsize;a:aword;src, dst:tregister);
  734. var
  735. tmpref:TReference;
  736. power:LongInt;
  737. opsize:topsize;
  738. begin
  739. opsize := S_SW;
  740. if (opsize <> S_SW) or
  741. not (size in [OS_32,OS_S32]) then
  742. begin
  743. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  744. exit;
  745. end;
  746. { if we get here, we have to do a 32 bit calculation, guaranteed }
  747. Case Op of
  748. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  749. OP_SAR:
  750. { can't do anything special for these }
  751. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  752. OP_IMUL:
  753. begin
  754. if not(cs_check_overflow in aktlocalswitches) and
  755. ispowerof2(a,power) then
  756. { can be done with a shift }
  757. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  758. list.concat(taicpu.op_reg_const_reg(A_SMUL,src,a,dst));
  759. end;
  760. OP_ADD, OP_SUB:
  761. if (a = 0) then
  762. a_load_reg_reg(list,size,size,src,dst)
  763. else
  764. begin
  765. reference_reset(tmpref);
  766. tmpref.base := src;
  767. tmpref.offset := LongInt(a);
  768. if op = OP_SUB then
  769. tmpref.offset := -tmpref.offset;
  770. list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst));
  771. end
  772. else internalerror(200112302);
  773. end;
  774. end;
  775. procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;
  776. size:tcgsize;src1, src2, dst:tregister);
  777. var
  778. tmpref:TReference;
  779. opsize:topsize;
  780. begin
  781. opsize := S_SW;
  782. if (opsize <> S_SW) or
  783. (S_SW <> S_SW) or
  784. not (size in [OS_32,OS_S32]) then
  785. begin
  786. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  787. exit;
  788. end;
  789. { if we get here, we have to do a 32 bit calculation, guaranteed }
  790. Case Op of
  791. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  792. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  793. { can't do anything special for these }
  794. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  795. OP_IMUL:
  796. list.concat(taicpu.op_reg_reg_reg(A_SMUL,src1,src2,dst));
  797. OP_ADD:
  798. begin
  799. reference_reset(tmpref);
  800. tmpref.base := src1;
  801. tmpref.index := src2;
  802. tmpref.scalefactor := 1;
  803. list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst));
  804. end
  805. else internalerror(200112303);
  806. end;
  807. end;
  808. {*************** compare instructructions ****************}
  809. procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);
  810. begin
  811. if(a=0)
  812. then
  813. list.concat(taicpu.op_reg_reg(A_CMP,reg,reg))
  814. else
  815. list.concat(taicpu.op_reg_const(A_CMP,reg,a));
  816. a_jmp_cond(list,cmp_op,l);
  817. end;
  818. procedure TCgSparc.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel);
  819. var
  820. cReg,rReg:TRegister;
  821. begin
  822. with cg do
  823. begin
  824. cReg:=get_scratch_reg_int(List,size);
  825. rReg:=get_scratch_reg_int(List,size);
  826. a_load_const_reg(List,OS_32,a,cReg);
  827. a_load_ref_reg(List,OS_32,ref,rReg);
  828. List.Concat(taicpu.op_reg_reg(A_CMP,rReg,cReg));
  829. a_jmp_cond(list,cmp_op,l);
  830. free_scratch_reg(List,cReg);
  831. free_scratch_reg(List,rReg);
  832. end;
  833. end;
  834. procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;
  835. reg1,reg2:tregister;l:tasmlabel);
  836. begin
  837. { if regsize(reg1) <> S_SW then
  838. internalerror(200109226);
  839. list.concat(taicpu.op_reg_reg(A_CMP,regsize(reg1),reg1,reg2));
  840. a_jmp_cond(list,cmp_op,l);}
  841. end;
  842. procedure TCgSparc.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;CONST ref:TReference;reg:tregister;l:tasmlabel);
  843. var
  844. TempReg:TRegister;
  845. begin
  846. TempReg:=cg.get_scratch_reg_int(List,size);
  847. a_load_ref_reg(list,OS_32,Ref,TempReg);
  848. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,TempReg,Reg,CpuReg[R_G0]));
  849. a_jmp_cond(list,cmp_op,l);
  850. cg.free_scratch_reg(exprasmlist,TempReg);
  851. end;
  852. procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel);
  853. var
  854. ai:TAiCpu;
  855. begin
  856. ai:=TAiCpu.Op_sym(A_BA,S_NO,l);
  857. ai.SetCondition(TOpCmp2AsmCond[cond]);
  858. with List do
  859. begin
  860. Concat(ai);
  861. Concat(TAiCpu.Op_none(A_NOP));
  862. end;
  863. end;
  864. procedure TCgSparc.a_jmp_flags(list:TAasmOutput;CONST f:TResFlags;l:tasmlabel);
  865. var
  866. ai:taicpu;
  867. begin
  868. ai := Taicpu.op_sym(A_BA,S_NO,l);
  869. ai.SetCondition(flags_to_cond(f));
  870. with List do
  871. begin
  872. Concat(ai);
  873. Concat(TAiCpu.Op_none(A_NOP));
  874. end;
  875. end;
  876. procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;CONST f:tresflags;reg:TRegister);
  877. VAR
  878. ai:taicpu;
  879. r,hreg:tregister;
  880. BEGIN
  881. r.enum:=R_PSR;
  882. hreg := rg.makeregsize(reg,OS_8);
  883. ai:=Taicpu.Op_reg_reg(A_RDPSR,r,hreg);
  884. ai.SetCondition(flags_to_cond(f));
  885. with List do
  886. begin
  887. Concat(ai);
  888. Concat(TAiCpu.Op_none(A_NOP));
  889. end;
  890. IF hreg.enum<>reg.enum
  891. THEN
  892. a_load_reg_reg(list,OS_32,OS_32,hreg,reg);
  893. END;
  894. procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const p:TNode);
  895. var
  896. hl:TAsmLabel;
  897. r:Tregister;
  898. begin
  899. r.enum:=R_NONE;
  900. if not(cs_check_overflow in aktlocalswitches)
  901. then
  902. exit;
  903. objectlibrary.getlabel(hl);
  904. if not((p.resulttype.def.deftype=pointerdef) or
  905. ((p.resulttype.def.deftype=orddef) and
  906. (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  907. bool8bit,bool16bit,bool32bit])))
  908. then
  909. begin
  910. list.concat(taicpu.op_reg(A_NONE,r));
  911. a_jmp_always(list,hl)
  912. end
  913. else
  914. a_jmp_cond(list,OC_NONE,hl);
  915. a_call_name(list,'FPC_OVERFLOW');
  916. a_label(list,hl);
  917. end;
  918. { *********** entry/exit code and address loading ************ }
  919. procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
  920. var
  921. r : tregister;
  922. begin
  923. { Althogh the SPARC architecture require only word alignment, software
  924. convention and the operating system require every stack frame to be double word
  925. aligned }
  926. LocalSize:=align(LocalSize,8);
  927. { Execute the SAVE instruction to get a new register window and create a new
  928. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  929. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  930. after execution of that instruction is the called function stack pointer}
  931. r.enum:=R_INTREGISTER;
  932. r.number:=NR_STACK_POINTER_REG;
  933. list.concat(Taicpu.Op_reg_const_reg(A_SAVE,r,-LocalSize,r));
  934. end;
  935. procedure TCgSparc.g_restore_all_registers(list:TaasmOutput;accused,acchiused:boolean);
  936. begin
  937. { The sparc port uses the sparc standard calling convetions so this function has no used }
  938. end;
  939. procedure TCgSparc.g_restore_frame_pointer(list:TAasmOutput);
  940. begin
  941. { This function intontionally does nothing as frame pointer is restored in the
  942. delay slot of the return instrucion done in g_return_from_proc}
  943. end;
  944. procedure TCgSparc.g_restore_standard_registers(list:taasmoutput;usedinproc:Tsupregset);
  945. begin
  946. { The sparc port uses the sparc standard calling convetions so this function has no used }
  947. end;
  948. procedure TCgSparc.g_return_from_proc(list:TAasmOutput;parasize:aword);
  949. var
  950. r,r2:Tregister;
  951. begin
  952. { According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  953. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  954. RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  955. delay slot, so an inversion is possible such as
  956. JMPL %i7+8,%g0
  957. RESTORE %g0,0,%g0
  958. If no inversion we can use just
  959. RESTORE %g0,0,%g0
  960. JMPL %i7+8,%g0
  961. NOP
  962. }
  963. with list do
  964. begin
  965. { Return address is computed by adding 8 to the CALL address saved onto %i6}
  966. r.enum:=R_G0;
  967. r2.enum:=R_I7;
  968. concat(Taicpu.Op_caddr_reg(A_JMPL,r,8,r));
  969. { We use trivial restore in the delay slot of the JMPL instruction, as we
  970. already set result onto %i0 }
  971. concat(Taicpu.Op_reg_const_reg(A_RESTORE,r,0,r));
  972. end
  973. end;
  974. procedure TCgSparc.g_save_all_registers(list : taasmoutput);
  975. begin
  976. { The sparc port uses the sparc standard calling convetions so this function has no used }
  977. end;
  978. procedure TCgSparc.g_save_standard_registers(list : taasmoutput; usedinproc:Tsupregset);
  979. begin
  980. { The sparc port uses the sparc standard calling convetions so this function has no used }
  981. end;
  982. procedure TCgSparc.a_loadaddr_ref_reg(list:TAasmOutput;CONST ref:TReference;r:tregister);
  983. begin
  984. // list.concat(taicpu.op_ref_reg(A_LEA,S_SW,ref,r));
  985. end;
  986. { ************* 64bit operations ************ }
  987. procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  988. begin
  989. case op of
  990. OP_ADD :
  991. begin
  992. op1:=A_ADD;
  993. op2:=A_ADD;
  994. end;
  995. OP_SUB :
  996. begin
  997. op1:=A_SUB;
  998. op2:=A_SUB;
  999. end;
  1000. OP_XOR :
  1001. begin
  1002. op1:=A_XOR;
  1003. op2:=A_XOR;
  1004. end;
  1005. OP_OR :
  1006. begin
  1007. op1:=A_OR;
  1008. op2:=A_OR;
  1009. end;
  1010. OP_AND :
  1011. begin
  1012. op1:=A_AND;
  1013. op2:=A_AND;
  1014. end;
  1015. else
  1016. internalerror(200203241);
  1017. end;
  1018. end;
  1019. procedure TCg64Sparc.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;CONST ref:TReference;reg:TRegister64);
  1020. var
  1021. op1,op2:TAsmOp;
  1022. tempref:TReference;
  1023. begin
  1024. get_64bit_ops(op,op1,op2);
  1025. list.concat(taicpu.op_ref_reg(op1,ref,reg.reglo));
  1026. tempref:=ref;
  1027. inc(tempref.offset,4);
  1028. list.concat(taicpu.op_ref_reg(op2,tempref,reg.reghi));
  1029. end;
  1030. procedure TCg64Sparc.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  1031. var
  1032. op1,op2:TAsmOp;
  1033. begin
  1034. get_64bit_ops(op,op1,op2);
  1035. list.concat(taicpu.op_reg_reg(op1,regsrc.reglo,regdst.reglo));
  1036. list.concat(taicpu.op_reg_reg(op2,regsrc.reghi,regdst.reghi));
  1037. end;
  1038. procedure TCg64Sparc.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  1039. var
  1040. op1,op2:TAsmOp;
  1041. begin
  1042. case op of
  1043. OP_AND,OP_OR,OP_XOR:
  1044. WITH cg DO
  1045. begin
  1046. a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  1047. a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  1048. end;
  1049. OP_ADD, OP_SUB:
  1050. begin
  1051. {can't use a_op_const_ref because this may use dec/inc}
  1052. get_64bit_ops(op,op1,op2);
  1053. list.concat(taicpu.op_const_reg(op1,Lo(Value),regdst.reglo));
  1054. list.concat(taicpu.op_const_reg(op2,Hi(Value),regdst.reghi));
  1055. end;
  1056. else
  1057. internalerror(200204021);
  1058. end;
  1059. end;
  1060. procedure TCg64Sparc.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;const ref:TReference);
  1061. var
  1062. op1,op2:TAsmOp;
  1063. tempref:TReference;
  1064. begin
  1065. case op of
  1066. OP_AND,OP_OR,OP_XOR:
  1067. with cg do
  1068. begin
  1069. a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  1070. tempref:=ref;
  1071. inc(tempref.offset,4);
  1072. a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  1073. end;
  1074. OP_ADD, OP_SUB:
  1075. begin
  1076. get_64bit_ops(op,op1,op2);
  1077. { can't use a_op_const_ref because this may use dec/inc}
  1078. { list.concat(taicpu.op_const_ref(op1,Lo(Value),ref));
  1079. tempref:=ref;
  1080. inc(tempref.offset,4);
  1081. list.concat(taicpu.op_const_ref(op2,S_SW,Hi(Value),tempref));}
  1082. InternalError(2002102101);
  1083. end;
  1084. else
  1085. internalerror(200204022);
  1086. end;
  1087. end;
  1088. { ************* concatcopy ************ }
  1089. procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean);
  1090. var
  1091. countreg: TRegister;
  1092. src, dst: TReference;
  1093. lab: tasmlabel;
  1094. count, count2: aword;
  1095. orgsrc, orgdst: boolean;
  1096. r:Tregister;
  1097. begin
  1098. {$ifdef extdebug}
  1099. if len > high(longint)
  1100. then
  1101. internalerror(2002072704);
  1102. {$endif extdebug}
  1103. { make sure short loads are handled as optimally as possible }
  1104. if not loadref
  1105. then
  1106. if(len <= 8)and(byte(len) in [1,2,4,8])
  1107. then
  1108. begin
  1109. if len < 8
  1110. then
  1111. begin
  1112. a_load_ref_ref(list,int_cgsize(len),source,dest);
  1113. if delsource
  1114. then
  1115. reference_release(list,source);
  1116. end
  1117. else
  1118. begin
  1119. r.enum:=R_F0;
  1120. a_reg_alloc(list,r);
  1121. a_loadfpu_ref_reg(list,OS_F64,source,r);
  1122. if delsource
  1123. then
  1124. reference_release(list,source);
  1125. a_loadfpu_reg_ref(list,OS_F64,r,dest);
  1126. a_reg_dealloc(list,r);
  1127. end;
  1128. exit;
  1129. end;
  1130. reference_reset(src);
  1131. reference_reset(dst);
  1132. { load the address of source into src.base }
  1133. if loadref
  1134. then
  1135. begin
  1136. src.base := get_scratch_reg_address(list);
  1137. a_load_ref_reg(list,OS_32,source,src.base);
  1138. orgsrc := false;
  1139. end
  1140. else if not issimpleref(source) or
  1141. ((source.index.enum<>R_NO)and
  1142. ((source.offset+longint(len))>high(smallint)))
  1143. then
  1144. begin
  1145. src.base := get_scratch_reg_address(list);
  1146. a_loadaddr_ref_reg(list,source,src.base);
  1147. orgsrc := false;
  1148. end
  1149. else
  1150. begin
  1151. src := source;
  1152. orgsrc := true;
  1153. end;
  1154. if not orgsrc and delsource
  1155. then
  1156. reference_release(list,source);
  1157. { load the address of dest into dst.base }
  1158. if not issimpleref(dest) or
  1159. ((dest.index.enum <> R_NO) and
  1160. ((dest.offset + longint(len)) > high(smallint)))
  1161. then
  1162. begin
  1163. dst.base := get_scratch_reg_address(list);
  1164. a_loadaddr_ref_reg(list,dest,dst.base);
  1165. orgdst := false;
  1166. end
  1167. else
  1168. begin
  1169. dst := dest;
  1170. orgdst := true;
  1171. end;
  1172. count:=len and 7;{count:=len div 8}
  1173. if count>4
  1174. then
  1175. { generate a loop }
  1176. begin
  1177. { the offsets are zero after the a_loadaddress_ref_reg and just }
  1178. { have to be set to 8. I put an Inc there so debugging may be }
  1179. { easier (should offset be different from zero here, it will be }
  1180. { easy to notice in the generated assembler }
  1181. inc(dst.offset,8);
  1182. inc(src.offset,8);
  1183. list.concat(taicpu.op_reg_const_reg(A_SUB,src.base,8,src.base));
  1184. list.concat(taicpu.op_reg_const_reg(A_SUB,dst.base,8,dst.base));
  1185. countreg := get_scratch_reg_int(list,OS_32);
  1186. a_load_const_reg(list,OS_32,count,countreg);
  1187. { explicitely allocate R_O0 since it can be used safely here }
  1188. { (for holding date that's being copied) }
  1189. r.enum:=R_F0;
  1190. a_reg_alloc(list,r);
  1191. objectlibrary.getlabel(lab);
  1192. a_label(list, lab);
  1193. list.concat(taicpu.op_reg_const_reg(A_SUB,countreg,1,countreg));
  1194. list.concat(taicpu.op_ref_reg(A_LDF,src,r));
  1195. list.concat(taicpu.op_reg_ref(A_STD,r,dst));
  1196. //a_jmp(list,A_BC,C_NE,0,lab);
  1197. free_scratch_reg(list,countreg);
  1198. a_reg_dealloc(list,r);
  1199. len := len mod 8;
  1200. end;
  1201. count:=len and 7;
  1202. if count>0
  1203. then
  1204. { unrolled loop }
  1205. begin
  1206. r.enum:=R_F0;
  1207. a_reg_alloc(list,r);
  1208. for count2 := 1 to count do
  1209. begin
  1210. a_loadfpu_ref_reg(list,OS_F64,src,r);
  1211. a_loadfpu_reg_ref(list,OS_F64,r,dst);
  1212. inc(src.offset,8);
  1213. inc(dst.offset,8);
  1214. end;
  1215. a_reg_dealloc(list,r);
  1216. len := len mod 8;
  1217. end;
  1218. if (len and 4) <> 0 then
  1219. begin
  1220. r.enum:=R_O0;
  1221. a_reg_alloc(list,r);
  1222. a_load_ref_reg(list,OS_32,src,r);
  1223. a_load_reg_ref(list,OS_32,r,dst);
  1224. inc(src.offset,4);
  1225. inc(dst.offset,4);
  1226. a_reg_dealloc(list,r);
  1227. end;
  1228. { copy the leftovers }
  1229. if (len and 2) <> 0 then
  1230. begin
  1231. r.enum:=R_O0;
  1232. a_reg_alloc(list,r);
  1233. a_load_ref_reg(list,OS_16,src,r);
  1234. a_load_reg_ref(list,OS_16,r,dst);
  1235. inc(src.offset,2);
  1236. inc(dst.offset,2);
  1237. a_reg_dealloc(list,r);
  1238. end;
  1239. if (len and 1) <> 0 then
  1240. begin
  1241. r.enum:=R_O0;
  1242. a_reg_alloc(list,r);
  1243. a_load_ref_reg(list,OS_8,src,r);
  1244. a_load_reg_ref(list,OS_8,r,dst);
  1245. a_reg_dealloc(list,r);
  1246. end;
  1247. if orgsrc then
  1248. begin
  1249. if delsource then
  1250. reference_release(list,source);
  1251. end
  1252. else
  1253. free_scratch_reg(list,src.base);
  1254. if not orgdst then
  1255. free_scratch_reg(list,dst.base);
  1256. end;
  1257. function TCgSparc.reg_cgsize(CONST reg:tregister):tcgsize;
  1258. begin
  1259. result:=OS_32;
  1260. end;
  1261. {***************** This is private property, keep out! :) *****************}
  1262. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  1263. begin
  1264. if(ref.base.enum=R_NONE)and(ref.index.enum <> R_NO)
  1265. then
  1266. InternalError(2002100804);
  1267. result :=not(assigned(ref.symbol))and
  1268. (((ref.index.enum = R_NO) and
  1269. (ref.offset >= low(smallint)) and
  1270. (ref.offset <= high(smallint))) or
  1271. ((ref.index.enum <> R_NO) and
  1272. (ref.offset = 0)));
  1273. end;
  1274. procedure TCgSparc.sizes2load(s1:tcgsize;s2:topsize;var op:tasmop;var s3:topsize);
  1275. begin
  1276. case s2 of
  1277. S_B:
  1278. if S1 in [OS_8,OS_S8]
  1279. then
  1280. s3 := S_B
  1281. else
  1282. internalerror(200109221);
  1283. S_W:
  1284. case s1 of
  1285. OS_8,OS_S8:
  1286. s3 := S_B;
  1287. OS_16,OS_S16:
  1288. s3 := S_H;
  1289. else
  1290. internalerror(200109222);
  1291. end;
  1292. S_SW:
  1293. case s1 of
  1294. OS_8,OS_S8:
  1295. s3 := S_B;
  1296. OS_16,OS_S16:
  1297. s3 := S_H;
  1298. OS_32,OS_S32:
  1299. s3 := S_W;
  1300. else
  1301. internalerror(200109223);
  1302. end;
  1303. else internalerror(200109227);
  1304. end;
  1305. if s3 in [S_B,S_W,S_SW]
  1306. then
  1307. op := A_LD
  1308. { else if s3=S_DW
  1309. then
  1310. op:=A_LDD
  1311. else if s3 in [OS_8,OS_16,OS_32]
  1312. then
  1313. op := A_NONE}
  1314. else
  1315. op := A_NONE;
  1316. end;
  1317. procedure TCgSparc.floatloadops(t:tcgsize;VAR op:tasmop;VAR s:topsize);
  1318. BEGIN
  1319. (* case t of
  1320. OS_F32:begin
  1321. op:=A_FLD;
  1322. s:=S_FS;
  1323. end;
  1324. OS_F64:begin
  1325. op:=A_FLD;
  1326. { ???? }
  1327. s:=S_FL;
  1328. end;
  1329. OS_F80:begin
  1330. op:=A_FLD;
  1331. s:=S_FX;
  1332. end;
  1333. OS_C64:begin
  1334. op:=A_FILD;
  1335. s:=S_IQ;
  1336. end;
  1337. else internalerror(17);
  1338. end;*)
  1339. END;
  1340. procedure TCgSparc.floatload(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1341. VAR
  1342. op:tasmop;
  1343. s:topsize;
  1344. BEGIN
  1345. floatloadops(t,op,s);
  1346. list.concat(Taicpu.Op_ref(op,ref));
  1347. { inc(trgcpu(rg).fpuvaroffset);}
  1348. END;
  1349. procedure TCgSparc.floatstoreops(t:tcgsize;var op:tasmop;var s:topsize);
  1350. BEGIN
  1351. { case t of
  1352. OS_F32:begin
  1353. op:=A_FSTP;
  1354. s:=S_FS;
  1355. end;
  1356. OS_F64:begin
  1357. op:=A_FSTP;
  1358. s:=S_FL;
  1359. end;
  1360. OS_F80:begin
  1361. op:=A_FSTP;
  1362. s:=S_FX;
  1363. end;
  1364. OS_C64:begin
  1365. op:=A_FISTP;
  1366. s:=S_IQ;
  1367. end;
  1368. else
  1369. internalerror(17);
  1370. end;}
  1371. end;
  1372. procedure TCgSparc.floatstore(list:TAasmOutput;t:tcgsize;CONST ref:TReference);
  1373. VAR
  1374. op:tasmop;
  1375. s:topsize;
  1376. BEGIN
  1377. floatstoreops(t,op,s);
  1378. list.concat(Taicpu.Op_ref(op,ref));
  1379. { dec(trgcpu(rg).fpuvaroffset);}
  1380. END;
  1381. BEGIN
  1382. cg:=TCgSparc.Create;
  1383. cg64:=TCg64Sparc.Create;
  1384. END.
  1385. {
  1386. $Log$
  1387. Revision 1.50 2003-05-23 22:33:48 florian
  1388. * fix some small flaws which prevent sparc linux system unit from compiling
  1389. * some reformatting done
  1390. Revision 1.49 2003/05/22 16:11:22 florian
  1391. * fixed sparc compilation partially
  1392. Revision 1.48 2003/05/07 15:04:30 mazen
  1393. * invalid genrated code for CASE statement fixed
  1394. Revision 1.47 2003/05/06 20:25:20 mazen
  1395. * Invalid genrated code : A_JMPL changed to A_BA
  1396. Revision 1.46 2003/05/06 15:02:40 mazen
  1397. * fixed a bug in a_load_const_reg related to max 13bit value limit
  1398. for immediat value ==> use of A_SETHI for greater values
  1399. Revision 1.45 2003/04/29 11:58:21 mazen
  1400. * fixed bug of output generated assembler for a_cmp_const_ref_label
  1401. Revision 1.44 2003/04/28 09:44:42 mazen
  1402. + NOP after conditional jump instruction to prevent delay slot execution
  1403. Revision 1.43 2003/04/27 11:21:36 peter
  1404. * aktprocdef renamed to current_procdef
  1405. * procinfo renamed to current_procinfo
  1406. * procinfo will now be stored in current_module so it can be
  1407. cleaned up properly
  1408. * gen_main_procsym changed to create_main_proc and release_main_proc
  1409. to also generate a tprocinfo structure
  1410. * fixed unit implicit initfinal
  1411. Revision 1.42 2003/03/16 20:45:45 mazen
  1412. * fixing an LD operation without refernce in loading address parameters
  1413. Revision 1.41 2003/03/10 21:59:54 mazen
  1414. * fixing index overflow in handling new registers arrays.
  1415. Revision 1.40 2003/02/25 21:41:44 mazen
  1416. * code re-aligned 2 spaces
  1417. Revision 1.39 2003/02/19 22:00:16 daniel
  1418. * Code generator converted to new register notation
  1419. - Horribily outdated todo.txt removed
  1420. Revision 1.38 2003/02/18 22:00:20 mazen
  1421. * asm condition generation modified by TAiCpu.SetCondition
  1422. Revision 1.37 2003/02/05 21:48:34 mazen
  1423. * fixing run time errors related to unimplemented abstract methods in CG
  1424. + giving empty emplementations for some RTL functions
  1425. Revision 1.36 2003/01/22 22:30:03 mazen
  1426. - internal errors rmoved from a_loar_reg_reg when reg sizes differs from 32
  1427. Revision 1.35 2003/01/20 22:21:36 mazen
  1428. * many stuff related to RTL fixed
  1429. Revision 1.34 2003/01/08 18:43:58 daniel
  1430. * Tregister changed into a record
  1431. Revision 1.33 2003/01/07 22:03:40 mazen
  1432. * adding unequaln node support to sparc compiler
  1433. Revision 1.32 2003/01/06 22:51:47 mazen
  1434. * fixing bugs related to load_reg_ref
  1435. Revision 1.31 2003/01/05 21:32:35 mazen
  1436. * fixing several bugs compiling the RTL
  1437. Revision 1.30 2003/01/05 13:36:53 florian
  1438. * x86-64 compiles
  1439. + very basic support for float128 type (x86-64 only)
  1440. Revision 1.29 2002/12/25 20:59:49 mazen
  1441. - many emitXXX removed from cga.pas in order to remove that file.
  1442. Revision 1.28 2002/12/22 19:26:31 mazen
  1443. * many internal errors related to unimplemented nodes are fixed
  1444. Revision 1.27 2002/12/21 23:21:47 mazen
  1445. + added support for the shift nodes
  1446. + added debug output on screen with -an command line option
  1447. Revision 1.26 2002/11/25 19:21:49 mazen
  1448. * fixed support of nSparcInline
  1449. Revision 1.25 2002/11/25 17:43:28 peter
  1450. * splitted defbase in defutil,symutil,defcmp
  1451. * merged isconvertable and is_equal into compare_defs(_ext)
  1452. * made operator search faster by walking the list only once
  1453. Revision 1.24 2002/11/17 17:49:09 mazen
  1454. + 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
  1455. Revision 1.23 2002/11/10 19:07:46 mazen
  1456. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1457. Revision 1.22 2002/11/06 11:31:24 mazen
  1458. * op_reg_reg_reg don't need any more a TOpSize parameter
  1459. Revision 1.21 2002/11/05 16:15:00 mazen
  1460. *** empty log message ***
  1461. Revision 1.20 2002/11/03 20:22:40 mazen
  1462. * parameter handling updated
  1463. Revision 1.19 2002/10/28 20:59:17 mazen
  1464. * TOpSize values changed S_L --> S_SW
  1465. Revision 1.18 2002/10/22 13:43:01 mazen
  1466. - cga.pas redueced to an empty unit
  1467. Revision 1.17 2002/10/20 19:01:38 mazen
  1468. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1469. Revision 1.16 2002/10/13 21:46:07 mazen
  1470. * assembler output format fixed
  1471. Revision 1.15 2002/10/11 13:35:14 mazen
  1472. *** empty log message ***
  1473. Revision 1.14 2002/10/10 19:57:51 mazen
  1474. * Just to update repsitory
  1475. Revision 1.13 2002/10/10 15:10:39 mazen
  1476. * Internal error fixed, but usually i386 parameter model used
  1477. Revision 1.12 2002/10/08 17:17:03 mazen
  1478. *** empty log message ***
  1479. Revision 1.11 2002/10/07 20:33:04 mazen
  1480. word alignement modified in g_stack_frame
  1481. Revision 1.10 2002/10/04 21:57:42 mazen
  1482. * 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
  1483. Revision 1.9 2002/10/02 22:20:28 mazen
  1484. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1485. Revision 1.8 2002/10/01 21:35:58 mazen
  1486. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1487. Revision 1.7 2002/10/01 21:06:29 mazen
  1488. attinst.inc --> strinst.inc
  1489. Revision 1.6 2002/10/01 17:41:50 florian
  1490. * fixed log and id
  1491. }