cgcpu.pas 45 KB

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