cgcpu.pas 45 KB

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