cgcpu.pas 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185
  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. cginfo,cgbase,cgobj,cg64f32,
  23. aasmbase,aasmtai,aasmcpu,
  24. cpubase,cpuinfo,
  25. node,symconst;
  26. type
  27. TCgSparc=class(tcg)
  28. private
  29. function IsSimpleRef(const ref:treference):boolean;
  30. public
  31. procedure a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);override;
  32. procedure a_param_ref(list:TAasmOutput;sz:tcgsize;const r:TReference;const LocPara:TParaLocation);override;
  33. procedure a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation);override;
  34. procedure a_call_name(list:TAasmOutput;const s:string);override;
  35. procedure a_call_ref(list:TAasmOutput;const ref:TReference);override;
  36. procedure a_call_reg(list:TAasmOutput;Reg:TRegister);override;
  37. { General purpose instructions }
  38. procedure a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);override;
  39. procedure a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);override;
  40. procedure a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;const ref:TReference;reg:TRegister);override;
  41. procedure a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);override;
  42. procedure a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;src1, src2, dst:tregister);override;
  43. { move instructions }
  44. procedure a_load_const_reg(list:TAasmOutput;size:tcgsize;a:aword;reg:tregister);override;
  45. procedure a_load_const_ref(list:TAasmOutput;size:tcgsize;a:aword;const ref:TReference);override;
  46. procedure a_load_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override;
  47. procedure a_load_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override;
  48. procedure a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);override;
  49. procedure a_loadaddr_ref_reg(list:TAasmOutput;const ref:TReference;r:tregister);override;
  50. { fpu move instructions }
  51. procedure a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);override;
  52. procedure a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);override;
  53. procedure a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);override;
  54. { comparison operations }
  55. procedure a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);override;
  56. procedure a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel);override;
  57. procedure a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);override;
  58. procedure a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;const ref:TReference;reg:tregister;l:tasmlabel);override;
  59. procedure a_jmp_always(List:TAasmOutput;l:TAsmLabel);override;
  60. procedure a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:tasmlabel);{ override;}
  61. procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override;
  62. procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override;
  63. procedure g_overflowCheck(List:TAasmOutput;const p:TNode);override;
  64. procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override;
  65. procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override;
  66. procedure g_restore_frame_pointer(list:TAasmOutput);override;
  67. procedure g_restore_standard_registers(list:taasmoutput;usedinproc:Tsupregset);override;
  68. procedure g_return_from_proc(list:TAasmOutput;parasize:aword);override;
  69. procedure g_save_all_registers(list : taasmoutput);override;
  70. procedure g_save_standard_registers(list : taasmoutput; usedinproc : Tsupregset);override;
  71. procedure g_concatcopy(list:TAasmOutput;const source,dest:TReference;len:aword;delsource,loadref:boolean);override;
  72. class function reg_cgsize(const reg:tregister):tcgsize;override;
  73. end;
  74. TCg64Sparc=class(tcg64f32)
  75. procedure a_op64_ref_reg(list:TAasmOutput;op:TOpCG;const ref:TReference;reg:TRegister64);override;
  76. procedure a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);override;
  77. procedure a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);override;
  78. procedure a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;const ref:TReference);override;
  79. procedure get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  80. end;
  81. const
  82. TOpCG2AsmOp : array[topcg] of TAsmOp=(
  83. 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
  84. );
  85. TOpCmp2AsmCond : array[topcmp] of TAsmCond=(
  86. C_NONE,C_E,C_G,C_L,C_GE,C_LE,C_NE,C_BE,C_B,C_AE,C_A
  87. );
  88. implementation
  89. uses
  90. globtype,globals,verbose,systems,cutils,
  91. symdef,symsym,defutil,paramgr,
  92. rgobj,tgobj,rgcpu,cpupi;
  93. {****************************************************************************
  94. This is private property, keep out! :)
  95. ****************************************************************************}
  96. function TCgSparc.IsSimpleRef(const ref:treference):boolean;
  97. begin
  98. if (ref.base.number=NR_NO) and (ref.index.number<>NR_NO) then
  99. InternalError(2002100804);
  100. result :=not(assigned(ref.symbol))and
  101. (((ref.index.number = NR_NO) and
  102. (ref.offset >= low(smallint)) and
  103. (ref.offset <= high(smallint))) or
  104. ((ref.index.number <> NR_NO) and
  105. (ref.offset = 0)));
  106. end;
  107. {****************************************************************************
  108. Assembler code
  109. ****************************************************************************}
  110. function TCgSparc.reg_cgsize(const reg:tregister):tcgsize;
  111. begin
  112. result:=OS_32;
  113. end;
  114. procedure TCgSparc.a_param_const(list:TAasmOutput;size:tcgsize;a:aword;const LocPara:TParaLocation);
  115. var
  116. Ref:TReference;
  117. begin
  118. case locpara.loc of
  119. LOC_REGISTER,LOC_CREGISTER:
  120. a_load_const_reg(list,size,a,locpara.register);
  121. LOC_REFERENCE:
  122. begin
  123. reference_reset(ref);
  124. ref.base:=locpara.reference.index;
  125. ref.offset:=locpara.reference.offset;
  126. a_load_const_ref(list,size,a,ref);
  127. end;
  128. else
  129. InternalError(2002122200);
  130. end;
  131. if locpara.sp_fixup<>0 then
  132. InternalError(2002122201);
  133. end;
  134. procedure TCgSparc.a_param_ref(list:TAasmOutput;sz:TCgSize;const r:TReference;const LocPara:TParaLocation);
  135. var
  136. ref: treference;
  137. tmpreg:TRegister;
  138. begin
  139. with LocPara do
  140. case loc of
  141. LOC_REGISTER,LOC_CREGISTER:
  142. a_load_ref_reg(list,sz,r,Register);
  143. LOC_REFERENCE:
  144. begin
  145. { Code conventions need the parameters being allocated in %o6+92. See
  146. comment on g_stack_frame }
  147. if locpara.sp_fixup<92 then
  148. InternalError(2002081104);
  149. reference_reset(ref);
  150. ref.base:=locpara.reference.index;
  151. ref.offset:=locpara.reference.offset;
  152. tmpreg := get_scratch_reg_int(list,sz);
  153. a_load_ref_reg(list,sz,r,tmpreg);
  154. a_load_reg_ref(list,sz,tmpreg,ref);
  155. free_scratch_reg(list,tmpreg);
  156. end;
  157. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  158. case sz of
  159. OS_32:
  160. a_loadfpu_ref_reg(list,OS_F32,r,locpara.register);
  161. OS_64:
  162. a_loadfpu_ref_reg(list,OS_F64,r,locpara.register);
  163. else
  164. internalerror(2002072801);
  165. end;
  166. else
  167. internalerror(2002081103);
  168. end;
  169. end;
  170. procedure TCgSparc.a_paramaddr_ref(list:TAasmOutput;const r:TReference;const LocPara:TParaLocation);
  171. var
  172. Ref:TReference;
  173. TmpReg:TRegister;
  174. begin
  175. case locpara.loc of
  176. LOC_REGISTER,LOC_CREGISTER:
  177. a_loadaddr_ref_reg(list,r,locpara.register);
  178. LOC_REFERENCE:
  179. begin
  180. reference_reset(ref);
  181. ref.base := locpara.reference.index;
  182. ref.offset := locpara.reference.offset;
  183. tmpreg := get_scratch_reg_address(list);
  184. a_loadaddr_ref_reg(list,r,tmpreg);
  185. a_load_reg_ref(list,OS_ADDR,tmpreg,ref);
  186. free_scratch_reg(list,tmpreg);
  187. end;
  188. else
  189. internalerror(2002080701);
  190. end;
  191. end;
  192. procedure TCgSparc.a_call_name(list:TAasmOutput;const s:string);
  193. begin
  194. list.concat(taicpu.op_sym(A_CALL,objectlibrary.newasmsymbol(s)));
  195. list.concat(taicpu.op_none(A_NOP));
  196. include(current_procinfo.flags,pi_do_call);
  197. end;
  198. procedure TCgSparc.a_call_ref(list:TAasmOutput;const ref:TReference);
  199. begin
  200. list.concat(taicpu.op_ref(A_CALL,ref));
  201. list.concat(taicpu.op_none(A_NOP));
  202. include(current_procinfo.flags,pi_do_call);
  203. end;
  204. procedure TCgSparc.a_call_reg(list:TAasmOutput;Reg:TRegister);
  205. var
  206. RetAddrReg:TRegister;
  207. begin
  208. retaddrreg.enum:=R_INTREGISTER;
  209. retaddrreg.Number:=NR_O7;
  210. list.concat(taicpu.op_reg_reg(A_JMPL,reg,RetAddrReg));
  211. { why only on Sparc/Linux? Doesn't use other implementations use the delay slot? (FK) }
  212. if target_info.system=system_sparc_linux then
  213. list.concat(taicpu.op_none(A_NOP));
  214. include(current_procinfo.flags,pi_do_call);
  215. end;
  216. {********************** load instructions ********************}
  217. procedure TCgSparc.a_load_const_reg(list : TAasmOutput;size : TCGSize;a : aword;reg : TRegister);
  218. var
  219. r:Tregister;
  220. begin
  221. r.enum:=R_INTREGISTER;
  222. r.number:=NR_G0;
  223. { we don't use the set instruction here because it could be evalutated to two
  224. instructions which would cause problems with the delay slot (FK) }
  225. { sethi allows to set the upper 22 bit, so we'll take full advantage of it }
  226. if (a and aword($3ff))=0 then
  227. list.concat(taicpu.op_const_reg(A_SETHI,(a and aword($fffffc00)) shr 10,reg))
  228. else if (a and aword($ffffe000))=0 then
  229. list.concat(taicpu.op_reg_const_reg(A_OR,r,a,reg))
  230. else
  231. begin
  232. list.concat(taicpu.op_const_reg(A_SETHI,(a and aword($ffffe000)) shr 13,reg));
  233. list.concat(taicpu.op_reg_const_reg(A_OR,r,a and $1fff,reg));
  234. end;
  235. end;
  236. procedure TCgSparc.a_load_const_ref(list : TAasmOutput;size : tcgsize;a : aword;const ref : TReference);
  237. var
  238. r:Tregister;
  239. begin
  240. inherited a_load_const_ref(list,size,a,ref);
  241. r.enum:=R_INTREGISTER;
  242. r.number:=NR_G0;
  243. if a=0 then
  244. a_load_reg_ref(list,size,r,ref)
  245. else
  246. inherited a_load_const_ref(list,size,a,ref);
  247. end;
  248. procedure TCgSparc.a_load_reg_ref(list:TAasmOutput;size:TCGSize;reg:tregister;const Ref:TReference);
  249. var
  250. op:tasmop;
  251. begin
  252. case size of
  253. { signed integer registers }
  254. OS_8,
  255. OS_S8:
  256. Op:=A_STB;
  257. OS_16,
  258. OS_S16:
  259. Op:=A_STH;
  260. OS_32,
  261. OS_S32:
  262. Op:=A_ST;
  263. else
  264. InternalError(2002122100);
  265. end;
  266. list.concat(taicpu.op_reg_ref(op,reg,ref));
  267. end;
  268. procedure TCgSparc.a_load_ref_reg(list:TAasmOutput;size:TCgSize;const ref:TReference;reg:tregister);
  269. var
  270. op:tasmop;
  271. begin
  272. case size of
  273. { signed integer registers }
  274. OS_S8:
  275. Op:=A_LDSB;{Load Signed Byte}
  276. OS_S16:
  277. Op:=A_LDSH;{Load Signed Halfword}
  278. OS_8:
  279. Op:=A_LDUB;{Load Unsigned Bye}
  280. OS_16:
  281. Op:=A_LDUH;{Load Unsigned Halfword}
  282. OS_S32,
  283. OS_32:
  284. Op:=A_LD;{Load Word}
  285. else
  286. InternalError(2002122100);
  287. end;
  288. list.concat(taicpu.op_ref_reg(op,ref,reg));
  289. end;
  290. procedure TCgSparc.a_load_reg_reg(list:TAasmOutput;fromsize,tosize:tcgsize;reg1,reg2:tregister);
  291. var
  292. zeroreg : Tregister;
  293. begin
  294. if(reg1.enum<>R_INTREGISTER)or(reg1.number=NR_NO) then
  295. InternalError(200303101);
  296. if(reg2.enum<>R_INTREGISTER)or(reg2.number=NR_NO) then
  297. InternalError(200303102);
  298. zeroreg.enum:=R_INTREGISTER;
  299. zeroreg.Number:=NR_G0;
  300. if (reg1.Number<>reg2.Number) or
  301. (tcgsize2size[tosize]<tcgsize2size[fromsize]) or
  302. (
  303. (tcgsize2size[tosize] = tcgsize2size[fromsize]) and
  304. (tosize <> fromsize) and
  305. not(fromsize in [OS_32,OS_S32])
  306. ) then
  307. begin
  308. case tosize of
  309. OS_8,OS_S8:
  310. list.Concat(taicpu.op_Reg_Const_Reg(A_AND,reg1,$FF,reg2));
  311. OS_16,OS_S16:
  312. begin
  313. list.Concat(taicpu.op_Reg_Reg_Reg(A_AND,reg1,zeroreg,reg2));
  314. { This will put 00...00111 in the highest 22 bits of the reg }
  315. list.Concat(taicpu.op_Reg_Const_Reg(A_SETHI,reg2,$7,reg2));
  316. end;
  317. OS_32,OS_S32:
  318. begin
  319. if reg1.number<>reg2.number then
  320. list.Concat(taicpu.op_Reg_Reg_Reg(A_OR,zeroreg,reg1,reg2));
  321. end;
  322. else
  323. internalerror(2002090901);
  324. end;
  325. end;
  326. end;
  327. procedure TCgSparc.a_loadfpu_reg_reg(list:TAasmOutput;reg1, reg2:tregister);
  328. begin
  329. { if NOT (reg1 IN [R_F0..R_F31]) then
  330. begin
  331. list.concat(taicpu.op_reg(A_NONE,S_NO,
  332. trgcpu(rg).correct_fpuregister(reg1,trgcpu(rg).fpuvaroffset)));
  333. inc(trgcpu(rg).fpuvaroffset);
  334. end;
  335. if NOT (reg2 IN [R_F0..R_F31]) then
  336. begin
  337. list.concat(taicpu.op_reg(A_JMPL,S_NO,
  338. trgcpu(rg).correct_fpuregister(reg2,trgcpu(rg).fpuvaroffset)));
  339. dec(trgcpu(rg).fpuvaroffset);
  340. end;}
  341. end;
  342. procedure TCgSparc.a_loadfpu_ref_reg(list:TAasmOutput;size:tcgsize;const ref:TReference;reg:tregister);
  343. begin
  344. // floatload(list,size,ref);
  345. { if (reg <> R_ST) then
  346. a_loadfpu_reg_reg(list,R_ST,reg);}
  347. end;
  348. procedure TCgSparc.a_loadfpu_reg_ref(list:TAasmOutput;size:tcgsize;reg:tregister;const ref:TReference);
  349. const
  350. FpuStoreInstr: Array[OS_F32..OS_F64,boolean, boolean] of TAsmOp =
  351. { indexed? updating?}
  352. (((A_STF,A_STF),(A_STF,A_STF)),
  353. ((A_STDF,A_STDF),(A_STDF,A_STDF)));
  354. var
  355. ref2: treference;
  356. freereg: boolean;
  357. begin
  358. if not(size in [OS_F32,OS_F64])
  359. then
  360. internalerror(200201122);
  361. { ref2:=ref;
  362. freereg:=fixref(list,ref2);
  363. op:=fpustoreinstr[size,ref2.index.enum <> R_NO,false];
  364. a_load_store(list,op,reg,ref2);
  365. if freereg
  366. then
  367. cg.free_scratch_reg(list,ref2.base);}
  368. end;
  369. procedure TCgSparc.a_op_const_reg(list:TAasmOutput;Op:TOpCG;a:AWord;reg:TRegister);
  370. begin
  371. list.concat(taicpu.op_reg_const_reg(TOpCG2AsmOp[op],reg,a,reg));
  372. end;
  373. procedure TCgSparc.a_op_reg_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;src, dst:TRegister);
  374. begin
  375. list.concat(taicpu.op_reg_reg_reg(TOpCG2AsmOp[op],dst,src,dst));
  376. end;
  377. procedure TCgSparc.a_op_ref_reg(list:TAasmOutput;Op:TOpCG;size:TCGSize;const ref:TReference;reg:TRegister);
  378. begin
  379. list.concat(taicpu.op_reg_ref_reg(TOpCG2AsmOp[op],reg,ref,reg));
  380. end;
  381. procedure TCgSparc.a_op_const_reg_reg(list:TAasmOutput;op:TOpCg;size:tcgsize;a:aword;src, dst:tregister);
  382. var
  383. tmpref:TReference;
  384. power:LongInt;
  385. begin
  386. if not (size in [OS_32,OS_S32]) then
  387. begin
  388. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  389. exit;
  390. end;
  391. { if we get here, we have to do a 32 bit calculation, guaranteed }
  392. Case Op of
  393. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  394. OP_SAR:
  395. { can't do anything special for these }
  396. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  397. OP_IMUL:
  398. begin
  399. if not(cs_check_overflow in aktlocalswitches) and
  400. ispowerof2(a,power) then
  401. { can be done with a shift }
  402. inherited a_op_const_reg_reg(list,op,size,a,src,dst);
  403. list.concat(taicpu.op_reg_const_reg(A_SMUL,src,a,dst));
  404. end;
  405. OP_ADD, OP_SUB:
  406. if (a = 0) then
  407. a_load_reg_reg(list,size,size,src,dst)
  408. else
  409. begin
  410. reference_reset(tmpref);
  411. tmpref.base := src;
  412. tmpref.offset := LongInt(a);
  413. if op = OP_SUB then
  414. tmpref.offset := -tmpref.offset;
  415. list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst));
  416. end
  417. else
  418. internalerror(200112302);
  419. end;
  420. end;
  421. procedure TCgSparc.a_op_reg_reg_reg(list:TAasmOutput;op:TOpCg;
  422. size:tcgsize;src1, src2, dst:tregister);
  423. var
  424. tmpref:TReference;
  425. begin
  426. if not (size in [OS_32,OS_S32]) then
  427. begin
  428. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  429. exit;
  430. end;
  431. { if we get here, we have to do a 32 bit calculation, guaranteed }
  432. Case Op of
  433. OP_DIV, OP_IDIV, OP_MUL, OP_AND, OP_OR, OP_XOR, OP_SHL, OP_SHR,
  434. OP_SAR,OP_SUB,OP_NOT,OP_NEG:
  435. { can't do anything special for these }
  436. inherited a_op_reg_reg_reg(list,op,size,src1,src2,dst);
  437. OP_IMUL:
  438. list.concat(taicpu.op_reg_reg_reg(A_SMUL,src1,src2,dst));
  439. OP_ADD:
  440. begin
  441. reference_reset(tmpref);
  442. tmpref.base := src1;
  443. tmpref.index := src2;
  444. list.concat(taicpu.op_ref_reg(A_NONE,tmpref,dst));
  445. end
  446. else internalerror(200112303);
  447. end;
  448. end;
  449. {*************** compare instructructions ****************}
  450. procedure TCgSparc.a_cmp_const_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;reg:tregister;l:tasmlabel);
  451. begin
  452. if(a=0)
  453. then
  454. list.concat(taicpu.op_reg_reg(A_CMP,reg,reg))
  455. else
  456. list.concat(taicpu.op_reg_const(A_CMP,reg,a));
  457. a_jmp_cond(list,cmp_op,l);
  458. end;
  459. procedure TCgSparc.a_cmp_const_ref_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;a:aword;const ref:TReference;l:tasmlabel);
  460. var
  461. cReg,rReg:TRegister;
  462. begin
  463. cReg:=get_scratch_reg_int(List,size);
  464. rReg:=get_scratch_reg_int(List,size);
  465. a_load_const_reg(List,OS_32,a,cReg);
  466. a_load_ref_reg(List,OS_32,ref,rReg);
  467. a_cmp_reg_reg_label(list,OS_32,cmp_op,rReg,cReg,l);
  468. free_scratch_reg(List,cReg);
  469. free_scratch_reg(List,rReg);
  470. end;
  471. procedure TCgSparc.a_cmp_reg_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;reg1,reg2:tregister;l:tasmlabel);
  472. begin
  473. List.Concat(taicpu.op_reg_reg(A_CMP,reg1,reg2));
  474. a_jmp_cond(list,cmp_op,l);
  475. end;
  476. procedure TCgSparc.a_cmp_ref_reg_label(list:TAasmOutput;size:tcgsize;cmp_op:topcmp;const ref:TReference;reg:tregister;l:tasmlabel);
  477. var
  478. zeroreg,TempReg:TRegister;
  479. begin
  480. TempReg:=cg.get_scratch_reg_int(List,size);
  481. a_load_ref_reg(list,OS_32,Ref,TempReg);
  482. zeroreg.enum:=R_INTREGISTER;
  483. zeroreg.number:=NR_G0;
  484. list.concat(taicpu.op_reg_reg_reg(A_SUBcc,TempReg,Reg,zeroreg));
  485. a_jmp_cond(list,cmp_op,l);
  486. cg.free_scratch_reg(exprasmlist,TempReg);
  487. end;
  488. procedure TCgSparc.a_jmp_always(List:TAasmOutput;l:TAsmLabel);
  489. begin
  490. List.Concat(TAiCpu.op_sym(A_BA,objectlibrary.newasmsymbol(l.name)));
  491. end;
  492. procedure TCgSparc.a_jmp_cond(list:TAasmOutput;cond:TOpCmp;l:TAsmLabel);
  493. var
  494. ai:TAiCpu;
  495. begin
  496. ai:=TAiCpu.Op_sym(A_BA,l);
  497. ai.SetCondition(TOpCmp2AsmCond[cond]);
  498. list.Concat(ai);
  499. list.Concat(TAiCpu.Op_none(A_NOP));
  500. end;
  501. procedure TCgSparc.a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);
  502. var
  503. ai:taicpu;
  504. begin
  505. ai := Taicpu.op_sym(A_BA,l);
  506. ai.SetCondition(flags_to_cond(f));
  507. list.Concat(ai);
  508. list.Concat(TAiCpu.Op_none(A_NOP));
  509. end;
  510. procedure TCgSparc.g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);
  511. var
  512. ai : taicpu;
  513. r : tregister;
  514. begin
  515. r.enum:=R_PSR;
  516. ai:=Taicpu.Op_reg_reg(A_RDPSR,r,reg);
  517. ai.SetCondition(flags_to_cond(f));
  518. list.Concat(ai);
  519. list.Concat(TAiCpu.Op_none(A_NOP));
  520. end;
  521. procedure TCgSparc.g_overflowCheck(List:TAasmOutput;const p:TNode);
  522. var
  523. hl:TAsmLabel;
  524. begin
  525. if not(cs_check_overflow in aktlocalswitches) then
  526. exit;
  527. objectlibrary.getlabel(hl);
  528. if not((p.resulttype.def.deftype=pointerdef) or
  529. ((p.resulttype.def.deftype=orddef) and
  530. (torddef(p.resulttype.def).typ in [u64bit,u16bit,u32bit,u8bit,uchar,
  531. bool8bit,bool16bit,bool32bit]))) then
  532. begin
  533. {$warning TODO Overflow check}
  534. a_jmp_always(list,hl)
  535. end
  536. else
  537. a_jmp_cond(list,OC_NONE,hl);
  538. a_call_name(list,'FPC_OVERFLOW');
  539. a_label(list,hl);
  540. end;
  541. { *********** entry/exit code and address loading ************ }
  542. procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt);
  543. var
  544. r : tregister;
  545. begin
  546. { Althogh the SPARC architecture require only word alignment, software
  547. convention and the operating system require every stack frame to be double word
  548. aligned }
  549. LocalSize:=align(LocalSize,8);
  550. { Execute the SAVE instruction to get a new register window and create a new
  551. stack frame. In the "SAVE %i6,size,%i6" the first %i6 is related to the state
  552. before execution of the SAVE instrucion so it is the caller %i6, when the %i6
  553. after execution of that instruction is the called function stack pointer}
  554. r.enum:=R_INTREGISTER;
  555. r.number:=NR_STACK_POINTER_REG;
  556. list.concat(Taicpu.Op_reg_const_reg(A_SAVE,r,aword(-LocalSize),r));
  557. end;
  558. procedure TCgSparc.g_restore_all_registers(list:TaasmOutput;accused,acchiused:boolean);
  559. begin
  560. { The sparc port uses the sparc standard calling convetions so this function has no used }
  561. end;
  562. procedure TCgSparc.g_restore_frame_pointer(list:TAasmOutput);
  563. begin
  564. { This function intontionally does nothing as frame pointer is restored in the
  565. delay slot of the return instrucion done in g_return_from_proc}
  566. end;
  567. procedure TCgSparc.g_restore_standard_registers(list:taasmoutput;usedinproc:Tsupregset);
  568. begin
  569. { The sparc port uses the sparc standard calling convetions so this function has no used }
  570. end;
  571. procedure TCgSparc.g_return_from_proc(list:TAasmOutput;parasize:aword);
  572. var
  573. r : tregister;
  574. href : treference;
  575. begin
  576. { According to the SPARC ABI, the stack is cleared using the RESTORE instruction
  577. which is genereted in the g_restore_frame_pointer. Notice that SPARC has no
  578. RETURN instruction and that JMPL is used instead. The JMPL instrucion have one
  579. delay slot, so an inversion is possible such as
  580. JMPL %i7+8,%g0
  581. RESTORE %g0,0,%g0
  582. If no inversion we can use just
  583. RESTORE %g0,0,%g0
  584. JMPL %i7+8,%g0
  585. NOP
  586. }
  587. { Return address is computed by adding 8 to the CALL address saved onto %i6}
  588. r.enum:=R_INTREGISTER;
  589. r.number:=NR_I7;
  590. reference_reset_base(href,r,8);
  591. r.enum:=R_INTREGISTER;
  592. r.number:=NR_G0;
  593. list.concat(Taicpu.op_ref_reg(A_JMPL,href,r));
  594. { We use trivial restore in the delay slot of the JMPL instruction, as we
  595. already set result onto %i0 }
  596. list.concat(Taicpu.Op_reg_const_reg(A_RESTORE,r,0,r));
  597. end;
  598. procedure TCgSparc.g_save_all_registers(list : taasmoutput);
  599. begin
  600. { The sparc port uses the sparc standard calling convetions so this function has no used }
  601. end;
  602. procedure TCgSparc.g_save_standard_registers(list : taasmoutput; usedinproc:Tsupregset);
  603. begin
  604. { The sparc port uses the sparc standard calling convetions so this function has no used }
  605. end;
  606. procedure TCgSparc.a_loadaddr_ref_reg(list : TAasmOutput;const ref : TReference;r : tregister);
  607. var
  608. href : treference;
  609. hreg : tregister;
  610. begin
  611. if (r.number=ref.index.number) or (r.number=ref.base.number) then
  612. begin
  613. {$ifdef newra}
  614. hreg:=rg.getaddressregister(list);
  615. {$else}
  616. hreg := get_scratch_reg_address(list);
  617. {$endif}
  618. end
  619. else
  620. hreg:=r;
  621. if assigned(ref.symbol) then
  622. begin
  623. reference_reset_symbol(href,ref.symbol,ref.offset);
  624. href.symaddr:=refs_hi;
  625. list.concat(taicpu.op_ref_reg(A_SETHI,href,hreg));
  626. href.symaddr:=refs_hi;
  627. list.concat(taicpu.op_reg_ref_reg(A_OR,hreg,href,hreg));
  628. // if (ref.index<>R_NO)
  629. end;
  630. if hreg.number<>r.number then
  631. begin
  632. a_load_reg_reg(list,OS_ADDR,OS_ADDR,hreg,r);
  633. {$ifdef newra}
  634. rg.ungetregisterint(list,hreg);
  635. {$else}
  636. free_scratch_reg(list,hreg);
  637. {$endif}
  638. end;
  639. end;
  640. { ************* 64bit operations ************ }
  641. procedure TCg64Sparc.get_64bit_ops(op:TOpCG;var op1,op2:TAsmOp);
  642. begin
  643. case op of
  644. OP_ADD :
  645. begin
  646. op1:=A_ADD;
  647. op2:=A_ADD;
  648. end;
  649. OP_SUB :
  650. begin
  651. op1:=A_SUB;
  652. op2:=A_SUB;
  653. end;
  654. OP_XOR :
  655. begin
  656. op1:=A_XOR;
  657. op2:=A_XOR;
  658. end;
  659. OP_OR :
  660. begin
  661. op1:=A_OR;
  662. op2:=A_OR;
  663. end;
  664. OP_AND :
  665. begin
  666. op1:=A_AND;
  667. op2:=A_AND;
  668. end;
  669. else
  670. internalerror(200203241);
  671. end;
  672. end;
  673. procedure TCg64Sparc.a_op64_ref_reg(list:TAasmOutput;op:TOpCG;const ref:TReference;reg:TRegister64);
  674. var
  675. op1,op2:TAsmOp;
  676. tempref:TReference;
  677. begin
  678. get_64bit_ops(op,op1,op2);
  679. list.concat(taicpu.op_ref_reg(op1,ref,reg.reglo));
  680. tempref:=ref;
  681. inc(tempref.offset,4);
  682. list.concat(taicpu.op_ref_reg(op2,tempref,reg.reghi));
  683. end;
  684. procedure TCg64Sparc.a_op64_reg_reg(list:TAasmOutput;op:TOpCG;regsrc,regdst:TRegister64);
  685. var
  686. op1,op2:TAsmOp;
  687. begin
  688. get_64bit_ops(op,op1,op2);
  689. list.concat(taicpu.op_reg_reg(op1,regsrc.reglo,regdst.reglo));
  690. list.concat(taicpu.op_reg_reg(op2,regsrc.reghi,regdst.reghi));
  691. end;
  692. procedure TCg64Sparc.a_op64_const_reg(list:TAasmOutput;op:TOpCG;value:qWord;regdst:TRegister64);
  693. var
  694. op1,op2:TAsmOp;
  695. begin
  696. case op of
  697. OP_AND,OP_OR,OP_XOR:
  698. begin
  699. cg.a_op_const_reg(list,op,Lo(Value),regdst.reglo);
  700. cg.a_op_const_reg(list,op,Hi(Value),regdst.reghi);
  701. end;
  702. OP_ADD, OP_SUB:
  703. begin
  704. {can't use a_op_const_ref because this may use dec/inc}
  705. get_64bit_ops(op,op1,op2);
  706. list.concat(taicpu.op_const_reg(op1,Lo(Value),regdst.reglo));
  707. list.concat(taicpu.op_const_reg(op2,Hi(Value),regdst.reghi));
  708. end;
  709. else
  710. internalerror(200204021);
  711. end;
  712. end;
  713. procedure TCg64Sparc.a_op64_const_ref(list:TAasmOutput;op:TOpCG;value:qWord;const ref:TReference);
  714. var
  715. op1,op2:TAsmOp;
  716. tempref:TReference;
  717. begin
  718. case op of
  719. OP_AND,OP_OR,OP_XOR:
  720. begin
  721. cg.a_op_const_ref(list,op,OS_32,Lo(Value),ref);
  722. tempref:=ref;
  723. inc(tempref.offset,4);
  724. cg.a_op_const_ref(list,op,OS_32,Hi(Value),tempref);
  725. end;
  726. OP_ADD, OP_SUB:
  727. begin
  728. get_64bit_ops(op,op1,op2);
  729. { can't use a_op_const_ref because this may use dec/inc}
  730. { list.concat(taicpu.op_const_ref(op1,Lo(Value),ref));
  731. tempref:=ref;
  732. inc(tempref.offset,4);
  733. list.concat(taicpu.op_const_ref(op2,S_SW,Hi(Value),tempref));}
  734. InternalError(2002102101);
  735. end;
  736. else
  737. internalerror(200204022);
  738. end;
  739. end;
  740. { ************* concatcopy ************ }
  741. procedure TCgSparc.g_concatcopy(list:taasmoutput;const source,dest:treference;len:aword;delsource,loadref:boolean);
  742. var
  743. countreg: TRegister;
  744. src, dst: TReference;
  745. lab: tasmlabel;
  746. count, count2: aword;
  747. orgsrc, orgdst: boolean;
  748. r:Tregister;
  749. begin
  750. if len > high(longint) then
  751. internalerror(2002072704);
  752. { make sure short loads are handled as optimally as possible }
  753. if not loadref then
  754. begin
  755. if (len <= 8) and (byte(len) in [1,2,4,8]) then
  756. begin
  757. if len < 8 then
  758. begin
  759. a_load_ref_ref(list,int_cgsize(len),source,dest);
  760. if delsource then
  761. reference_release(list,source);
  762. end
  763. else
  764. begin
  765. r.enum:=R_F0;
  766. a_reg_alloc(list,r);
  767. a_loadfpu_ref_reg(list,OS_F64,source,r);
  768. if delsource then
  769. reference_release(list,source);
  770. a_loadfpu_reg_ref(list,OS_F64,r,dest);
  771. a_reg_dealloc(list,r);
  772. end;
  773. exit;
  774. end;
  775. end;
  776. reference_reset(src);
  777. reference_reset(dst);
  778. { load the address of source into src.base }
  779. if loadref then
  780. begin
  781. src.base := get_scratch_reg_address(list);
  782. a_load_ref_reg(list,OS_32,source,src.base);
  783. orgsrc := false;
  784. end
  785. else
  786. if not issimpleref(source) or
  787. (
  788. (source.index.number<>NR_NO) and
  789. ((source.offset+longint(len))>high(smallint))
  790. ) then
  791. begin
  792. src.base := get_scratch_reg_address(list);
  793. a_loadaddr_ref_reg(list,source,src.base);
  794. orgsrc := false;
  795. end
  796. else
  797. begin
  798. src := source;
  799. orgsrc := true;
  800. end;
  801. if not orgsrc and delsource then
  802. reference_release(list,source);
  803. { load the address of dest into dst.base }
  804. if not issimpleref(dest) or
  805. (
  806. (dest.index.number<>NR_NO) and
  807. ((dest.offset + longint(len)) > high(smallint))
  808. ) then
  809. begin
  810. dst.base := get_scratch_reg_address(list);
  811. a_loadaddr_ref_reg(list,dest,dst.base);
  812. orgdst := false;
  813. end
  814. else
  815. begin
  816. dst := dest;
  817. orgdst := true;
  818. end;
  819. { generate a loop }
  820. count:=len div 8;
  821. if count>4 then
  822. begin
  823. { the offsets are zero after the a_loadaddress_ref_reg and just }
  824. { have to be set to 8. I put an Inc there so debugging may be }
  825. { easier (should offset be different from zero here, it will be }
  826. { easy to notice in the generated assembler }
  827. inc(dst.offset,8);
  828. inc(src.offset,8);
  829. list.concat(taicpu.op_reg_const_reg(A_SUB,src.base,8,src.base));
  830. list.concat(taicpu.op_reg_const_reg(A_SUB,dst.base,8,dst.base));
  831. countreg := get_scratch_reg_int(list,OS_32);
  832. a_load_const_reg(list,OS_32,count,countreg);
  833. { explicitely allocate R_O0 since it can be used safely here }
  834. { (for holding date that's being copied) }
  835. r.enum:=R_F0;
  836. a_reg_alloc(list,r);
  837. objectlibrary.getlabel(lab);
  838. a_label(list, lab);
  839. list.concat(taicpu.op_reg_const_reg(A_SUB,countreg,1,countreg));
  840. list.concat(taicpu.op_ref_reg(A_LDF,src,r));
  841. list.concat(taicpu.op_reg_ref(A_STD,r,dst));
  842. //a_jmp(list,A_BC,C_NE,0,lab);
  843. free_scratch_reg(list,countreg);
  844. a_reg_dealloc(list,r);
  845. len := len mod 8;
  846. end;
  847. { unrolled loop }
  848. count:=len and 7;
  849. if count>0 then
  850. begin
  851. r.enum:=R_F0;
  852. a_reg_alloc(list,r);
  853. for count2 := 1 to count do
  854. begin
  855. a_loadfpu_ref_reg(list,OS_F64,src,r);
  856. a_loadfpu_reg_ref(list,OS_F64,r,dst);
  857. inc(src.offset,8);
  858. inc(dst.offset,8);
  859. end;
  860. a_reg_dealloc(list,r);
  861. len := len mod 8;
  862. end;
  863. if (len and 4) <> 0 then
  864. begin
  865. r.enum:=R_INTREGISTER;
  866. r.number:=NR_O0;
  867. a_reg_alloc(list,r);
  868. a_load_ref_reg(list,OS_32,src,r);
  869. a_load_reg_ref(list,OS_32,r,dst);
  870. inc(src.offset,4);
  871. inc(dst.offset,4);
  872. a_reg_dealloc(list,r);
  873. end;
  874. { copy the leftovers }
  875. if (len and 2) <> 0 then
  876. begin
  877. r.enum:=R_INTREGISTER;
  878. r.number:=NR_O0;
  879. a_reg_alloc(list,r);
  880. a_load_ref_reg(list,OS_16,src,r);
  881. a_load_reg_ref(list,OS_16,r,dst);
  882. inc(src.offset,2);
  883. inc(dst.offset,2);
  884. a_reg_dealloc(list,r);
  885. end;
  886. if (len and 1) <> 0 then
  887. begin
  888. r.enum:=R_INTREGISTER;
  889. r.number:=NR_O0;
  890. a_reg_alloc(list,r);
  891. a_load_ref_reg(list,OS_8,src,r);
  892. a_load_reg_ref(list,OS_8,r,dst);
  893. a_reg_dealloc(list,r);
  894. end;
  895. if orgsrc then
  896. begin
  897. if delsource then
  898. reference_release(list,source);
  899. end
  900. else
  901. free_scratch_reg(list,src.base);
  902. if not orgdst then
  903. free_scratch_reg(list,dst.base);
  904. end;
  905. begin
  906. cg:=TCgSparc.Create;
  907. cg64:=TCg64Sparc.Create;
  908. end.
  909. {
  910. $Log$
  911. Revision 1.54 2003-05-31 01:00:51 peter
  912. * register fixes
  913. Revision 1.53 2003/05/30 23:57:08 peter
  914. * more sparc cleanup
  915. * accumulator removed, splitted in function_return_reg (called) and
  916. function_result_reg (caller)
  917. Revision 1.52 2003/05/28 23:18:31 florian
  918. * started to fix and clean up the sparc port
  919. Revision 1.51 2003/05/26 22:04:57 mazen
  920. * added 64 bit value support to fix a problem in RTL
  921. Revision 1.50 2003/05/23 22:33:48 florian
  922. * fix some small flaws which prevent sparc linux system unit from compiling
  923. * some reformatting done
  924. Revision 1.49 2003/05/22 16:11:22 florian
  925. * fixed sparc compilation partially
  926. Revision 1.48 2003/05/07 15:04:30 mazen
  927. * invalid genrated code for CASE statement fixed
  928. Revision 1.47 2003/05/06 20:25:20 mazen
  929. * Invalid genrated code : A_JMPL changed to A_BA
  930. Revision 1.46 2003/05/06 15:02:40 mazen
  931. * fixed a bug in a_load_const_reg related to max 13bit value limit
  932. for immediat value ==> use of A_SETHI for greater values
  933. Revision 1.45 2003/04/29 11:58:21 mazen
  934. * fixed bug of output generated assembler for a_cmp_const_ref_label
  935. Revision 1.44 2003/04/28 09:44:42 mazen
  936. + NOP after conditional jump instruction to prevent delay slot execution
  937. Revision 1.43 2003/04/27 11:21:36 peter
  938. * aktprocdef renamed to current_procdef
  939. * procinfo renamed to current_procinfo
  940. * procinfo will now be stored in current_module so it can be
  941. cleaned up properly
  942. * gen_main_procsym changed to create_main_proc and release_main_proc
  943. to also generate a tprocinfo structure
  944. * fixed unit implicit initfinal
  945. Revision 1.42 2003/03/16 20:45:45 mazen
  946. * fixing an LD operation without refernce in loading address parameters
  947. Revision 1.41 2003/03/10 21:59:54 mazen
  948. * fixing index overflow in handling new registers arrays.
  949. Revision 1.40 2003/02/25 21:41:44 mazen
  950. * code re-aligned 2 spaces
  951. Revision 1.39 2003/02/19 22:00:16 daniel
  952. * Code generator converted to new register notation
  953. - Horribily outdated todo.txt removed
  954. Revision 1.38 2003/02/18 22:00:20 mazen
  955. * asm condition generation modified by TAiCpu.SetCondition
  956. Revision 1.37 2003/02/05 21:48:34 mazen
  957. * fixing run time errors related to unimplemented abstract methods in CG
  958. + giving empty emplementations for some RTL functions
  959. Revision 1.36 2003/01/22 22:30:03 mazen
  960. - internal errors rmoved from a_loar_reg_reg when reg sizes differs from 32
  961. Revision 1.35 2003/01/20 22:21:36 mazen
  962. * many stuff related to RTL fixed
  963. Revision 1.34 2003/01/08 18:43:58 daniel
  964. * Tregister changed into a record
  965. Revision 1.33 2003/01/07 22:03:40 mazen
  966. * adding unequaln node support to sparc compiler
  967. Revision 1.32 2003/01/06 22:51:47 mazen
  968. * fixing bugs related to load_reg_ref
  969. Revision 1.31 2003/01/05 21:32:35 mazen
  970. * fixing several bugs compiling the RTL
  971. Revision 1.30 2003/01/05 13:36:53 florian
  972. * x86-64 compiles
  973. + very basic support for float128 type (x86-64 only)
  974. Revision 1.29 2002/12/25 20:59:49 mazen
  975. - many emitXXX removed from cga.pas in order to remove that file.
  976. Revision 1.28 2002/12/22 19:26:31 mazen
  977. * many internal errors related to unimplemented nodes are fixed
  978. Revision 1.27 2002/12/21 23:21:47 mazen
  979. + added support for the shift nodes
  980. + added debug output on screen with -an command line option
  981. Revision 1.26 2002/11/25 19:21:49 mazen
  982. * fixed support of nSparcInline
  983. Revision 1.25 2002/11/25 17:43:28 peter
  984. * splitted defbase in defutil,symutil,defcmp
  985. * merged isconvertable and is_equal into compare_defs(_ext)
  986. * made operator search faster by walking the list only once
  987. Revision 1.24 2002/11/17 17:49:09 mazen
  988. + 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
  989. Revision 1.23 2002/11/10 19:07:46 mazen
  990. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  991. Revision 1.22 2002/11/06 11:31:24 mazen
  992. * op_reg_reg_reg don't need any more a TOpSize parameter
  993. Revision 1.21 2002/11/05 16:15:00 mazen
  994. *** empty log message ***
  995. Revision 1.20 2002/11/03 20:22:40 mazen
  996. * parameter handling updated
  997. Revision 1.19 2002/10/28 20:59:17 mazen
  998. * TOpSize values changed S_L --> S_SW
  999. Revision 1.18 2002/10/22 13:43:01 mazen
  1000. - cga.pas redueced to an empty unit
  1001. Revision 1.17 2002/10/20 19:01:38 mazen
  1002. + op_raddr_reg and op_caddr_reg added to fix functions prologue
  1003. Revision 1.16 2002/10/13 21:46:07 mazen
  1004. * assembler output format fixed
  1005. Revision 1.15 2002/10/11 13:35:14 mazen
  1006. *** empty log message ***
  1007. Revision 1.14 2002/10/10 19:57:51 mazen
  1008. * Just to update repsitory
  1009. Revision 1.13 2002/10/10 15:10:39 mazen
  1010. * Internal error fixed, but usually i386 parameter model used
  1011. Revision 1.12 2002/10/08 17:17:03 mazen
  1012. *** empty log message ***
  1013. Revision 1.11 2002/10/07 20:33:04 mazen
  1014. word alignement modified in g_stack_frame
  1015. Revision 1.10 2002/10/04 21:57:42 mazen
  1016. * 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
  1017. Revision 1.9 2002/10/02 22:20:28 mazen
  1018. + out registers allocator for the first 6 scalar parameters which must be passed into %o0..%o5
  1019. Revision 1.8 2002/10/01 21:35:58 mazen
  1020. + procedures exiting prologue added and stack frame now restored in the delay slot of the return (JMPL) instruction
  1021. Revision 1.7 2002/10/01 21:06:29 mazen
  1022. attinst.inc --> strinst.inc
  1023. Revision 1.6 2002/10/01 17:41:50 florian
  1024. * fixed log and id
  1025. }