cgcpu.pas 40 KB

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