rgx86.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the x86 specific class for the register
  5. allocator
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit rgx86;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cpubase,
  24. cpuinfo,
  25. aasmbase,aasmtai,aasmcpu,
  26. cclasses,globtype,cgbase,rgobj;
  27. type
  28. trgx86 = class(trgobj)
  29. function instr_spill_register(list:Taasmoutput;
  30. instr:taicpu;
  31. const r:Tsuperregisterset;
  32. const spilltemplist:Tspill_temp_list): boolean;override;
  33. end;
  34. tpushedsavedloc = record
  35. case byte of
  36. 0: (pushed: boolean);
  37. 1: (ofs: longint);
  38. end;
  39. tpushedsavedfpu = array[tsuperregister] of tpushedsavedloc;
  40. trgx86fpu = class
  41. { The "usableregsxxx" contain all registers of type "xxx" that }
  42. { aren't currently allocated to a regvar. The "unusedregsxxx" }
  43. { contain all registers of type "xxx" that aren't currently }
  44. { allocated }
  45. unusedregsfpu,usableregsfpu : Tsuperregisterset;
  46. { these counters contain the number of elements in the }
  47. { unusedregsxxx/usableregsxxx sets }
  48. countunusedregsfpu : byte;
  49. { Contains the registers which are really used by the proc itself.
  50. It doesn't take care of registers used by called procedures
  51. }
  52. used_in_proc : tcpuregisterset;
  53. {reg_pushes_other : regvarother_longintarray;
  54. is_reg_var_other : regvarother_booleanarray;
  55. regvar_loaded_other : regvarother_booleanarray;}
  56. { tries to hold the amount of times which the current tree is processed }
  57. t_times: longint;
  58. fpuvaroffset : byte;
  59. constructor create;
  60. function getregisterfpu(list: taasmoutput) : tregister;
  61. procedure ungetregisterfpu(list: taasmoutput; r : tregister);
  62. { pushes and restores registers }
  63. procedure saveusedfpuregisters(list:Taasmoutput;
  64. var saved:Tpushedsavedfpu;
  65. const s:Tcpuregisterset);
  66. procedure restoreusedfpuregisters(list:Taasmoutput;
  67. const saved:Tpushedsavedfpu);
  68. { corrects the fpu stack register by ofs }
  69. function correct_fpuregister(r : tregister;ofs : byte) : tregister;
  70. end;
  71. implementation
  72. uses
  73. systems,
  74. verbose;
  75. const
  76. { This value is used in tsaved. If the array value is equal
  77. to this, then this means that this register is not used.}
  78. reg_not_saved = $7fffffff;
  79. {******************************************************************************
  80. Trgcpu
  81. ******************************************************************************}
  82. function trgx86.instr_spill_register(list:Taasmoutput;
  83. instr:taicpu;
  84. const r:Tsuperregisterset;
  85. const spilltemplist:Tspill_temp_list): boolean;
  86. {
  87. Spill the registers in r in this instruction. Returns true if any help
  88. registers are used. This procedure has become one big hack party, because
  89. of the huge amount of situations you can have. The irregularity of the i386
  90. instruction set doesn't help either. (DM)
  91. }
  92. var i:byte;
  93. supreg:Tsuperregister;
  94. subreg:Tsubregister;
  95. helpreg:Tregister;
  96. helpins:Taicpu;
  97. op:Tasmop;
  98. hopsize:Topsize;
  99. pos:Tai;
  100. begin
  101. {Situation examples are in intel notation, so operand order:
  102. mov eax , ebx
  103. ^^^ ^^^
  104. oper[1] oper[0]
  105. (DM)}
  106. result:=false;
  107. with taicpu(instr) do
  108. begin
  109. case ops of
  110. 1:
  111. begin
  112. if (oper[0]^.typ=top_reg) and
  113. (getregtype(oper[0]^.reg)=regtype) then
  114. begin
  115. supreg:=getsupreg(oper[0]^.reg);
  116. if supregset_in(r,supreg) then
  117. begin
  118. {Situation example:
  119. push r20d ; r20d must be spilled into [ebp-12]
  120. Change into:
  121. push [ebp-12] ; Replace register by reference }
  122. { hopsize:=reg2opsize(oper[0].reg);}
  123. oper[0]^.typ:=top_ref;
  124. new(oper[0]^.ref);
  125. oper[0]^.ref^:=spilltemplist[supreg];
  126. { oper[0]^.ref^.size:=hopsize;}
  127. end;
  128. end;
  129. if oper[0]^.typ=top_ref then
  130. begin
  131. supreg:=getsupreg(oper[0]^.ref^.base);
  132. if supregset_in(r,supreg) then
  133. begin
  134. {Situation example:
  135. push [r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  136. Change into:
  137. mov r23d,[ebp-12] ; Use a help register
  138. push [r23d+4*r22d] ; Replace register by helpregister }
  139. subreg:=getsubreg(oper[0]^.ref^.base);
  140. if oper[0]^.ref^.index=NR_NO then
  141. pos:=Tai(previous)
  142. else
  143. pos:=get_insert_pos(Tai(previous),getsupreg(oper[0]^.ref^.index),RS_INVALID,RS_INVALID);
  144. getregisterinline(list,pos,subreg,helpreg);
  145. result:=true;
  146. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.base),spilltemplist[supreg],helpreg);
  147. if pos=nil then
  148. list.insertafter(helpins,list.first)
  149. else
  150. list.insertafter(helpins,pos.next);
  151. ungetregisterinline(list,helpins,helpreg);
  152. forward_allocation(Tai(helpins.next),instr);
  153. oper[0]^.ref^.base:=helpreg;
  154. end;
  155. supreg:=getsupreg(oper[0]^.ref^.index);
  156. if supregset_in(r,supreg) then
  157. begin
  158. {Situation example:
  159. push [r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  160. Change into:
  161. mov r23d,[ebp-12] ; Use a help register
  162. push [r21d+4*r23d] ; Replace register by helpregister }
  163. subreg:=getsubreg(oper[0]^.ref^.index);
  164. if oper[0]^.ref^.base=NR_NO then
  165. pos:=Tai(instr.previous)
  166. else
  167. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),RS_INVALID,RS_INVALID);
  168. getregisterinline(list,pos,subreg,helpreg);
  169. result:=true;
  170. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.ref^.index),spilltemplist[supreg],helpreg);
  171. if pos=nil then
  172. list.insertafter(helpins,list.first)
  173. else
  174. list.insertafter(helpins,pos.next);
  175. ungetregisterinline(list,helpins,helpreg);
  176. forward_allocation(Tai(helpins.next),instr);
  177. oper[0]^.ref^.index:=helpreg;
  178. end;
  179. end;
  180. end;
  181. 2:
  182. begin
  183. { First spill the registers from the references. This is
  184. required because the reference can be moved from this instruction
  185. to a MOV instruction when spilling of the register operand is done }
  186. for i:=0 to 1 do
  187. if oper[i]^.typ=top_ref then
  188. begin
  189. supreg:=getsupreg(oper[i]^.ref^.base);
  190. if supregset_in(r,supreg) then
  191. begin
  192. {Situation example:
  193. add r20d,[r21d+4*r22d] ; r21d must be spilled into [ebp-12]
  194. Change into:
  195. mov r23d,[ebp-12] ; Use a help register
  196. add r20d,[r23d+4*r22d] ; Replace register by helpregister }
  197. subreg:=getsubreg(oper[i]^.ref^.base);
  198. if i=1 then
  199. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),getsupreg(oper[0]^.reg),RS_INVALID)
  200. else
  201. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.index),RS_INVALID,RS_INVALID);
  202. getregisterinline(list,pos,subreg,helpreg);
  203. result:=true;
  204. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.base),spilltemplist[supreg],helpreg);
  205. if pos=nil then
  206. list.insertafter(helpins,list.first)
  207. else
  208. list.insertafter(helpins,pos.next);
  209. oper[i]^.ref^.base:=helpreg;
  210. ungetregisterinline(list,helpins,helpreg);
  211. forward_allocation(Tai(helpins.next),instr);
  212. end;
  213. supreg:=getsupreg(oper[i]^.ref^.index);
  214. if supregset_in(r,supreg) then
  215. begin
  216. {Situation example:
  217. add r20d,[r21d+4*r22d] ; r22d must be spilled into [ebp-12]
  218. Change into:
  219. mov r23d,[ebp-12] ; Use a help register
  220. add r20d,[r21d+4*r23d] ; Replace register by helpregister }
  221. subreg:=getsubreg(oper[i]^.ref^.index);
  222. if i=1 then
  223. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),
  224. getsupreg(oper[0]^.reg),RS_INVALID)
  225. else
  226. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[i]^.ref^.base),RS_INVALID,RS_INVALID);
  227. getregisterinline(list,pos,subreg,helpreg);
  228. result:=true;
  229. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[i]^.ref^.index),spilltemplist[supreg],helpreg);
  230. if pos=nil then
  231. list.insertafter(helpins,list.first)
  232. else
  233. list.insertafter(helpins,pos.next);
  234. oper[i]^.ref^.index:=helpreg;
  235. ungetregisterinline(list,helpins,helpreg);
  236. forward_allocation(Tai(helpins.next),instr);
  237. end;
  238. end;
  239. if (oper[0]^.typ=top_reg) and
  240. (getregtype(oper[0]^.reg)=regtype) then
  241. begin
  242. supreg:=getsupreg(oper[0]^.reg);
  243. subreg:=getsubreg(oper[0]^.reg);
  244. if supregset_in(r,supreg) then
  245. if oper[1]^.typ=top_ref then
  246. begin
  247. {Situation example:
  248. add [r20d],r21d ; r21d must be spilled into [ebp-12]
  249. Change into:
  250. mov r22d,[ebp-12] ; Use a help register
  251. add [r20d],r22d ; Replace register by helpregister }
  252. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),
  253. getsupreg(oper[1]^.ref^.base),getsupreg(oper[1]^.ref^.index));
  254. getregisterinline(list,pos,subreg,helpreg);
  255. result:=true;
  256. helpins:=Taicpu.op_ref_reg(A_MOV,reg2opsize(oper[0]^.reg),spilltemplist[supreg],helpreg);
  257. if pos=nil then
  258. list.insertafter(helpins,list.first)
  259. else
  260. list.insertafter(helpins,pos.next);
  261. oper[0]^.reg:=helpreg;
  262. ungetregisterinline(list,helpins,helpreg);
  263. forward_allocation(Tai(helpins.next),instr);
  264. end
  265. else
  266. begin
  267. {Situation example:
  268. add r20d,r21d ; r21d must be spilled into [ebp-12]
  269. Change into:
  270. add r20d,[ebp-12] ; Replace register by reference }
  271. oper[0]^.typ:=top_ref;
  272. new(oper[0]^.ref);
  273. oper[0]^.ref^:=spilltemplist[supreg];
  274. end;
  275. end;
  276. if (oper[1]^.typ=top_reg) and
  277. (getregtype(oper[1]^.reg)=regtype) then
  278. begin
  279. supreg:=getsupreg(oper[1]^.reg);
  280. subreg:=getsubreg(oper[1]^.reg);
  281. if supregset_in(r,supreg) then
  282. begin
  283. if oper[0]^.typ=top_ref then
  284. begin
  285. {Situation example:
  286. add r20d,[r21d] ; r20d must be spilled into [ebp-12]
  287. Change into:
  288. mov r22d,[r21d] ; Use a help register
  289. add [ebp-12],r22d ; Replace register by helpregister }
  290. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.ref^.base),
  291. getsupreg(oper[0]^.ref^.index),RS_INVALID);
  292. getregisterinline(list,pos,subreg,helpreg);
  293. result:=true;
  294. op:=A_MOV;
  295. hopsize:=opsize; {Save old value...}
  296. if (opcode=A_MOVZX) or (opcode=A_MOVSX) or (opcode=A_LEA) then
  297. begin
  298. {Because 'movzx memory,register' does not exist...}
  299. op:=opcode;
  300. opcode:=A_MOV;
  301. opsize:=reg2opsize(oper[1]^.reg);
  302. end;
  303. helpins:=Taicpu.op_ref_reg(op,hopsize,oper[0]^.ref^,helpreg);
  304. if pos=nil then
  305. list.insertafter(helpins,list.first)
  306. else
  307. list.insertafter(helpins,pos.next);
  308. dispose(oper[0]^.ref);
  309. oper[0]^.typ:=top_reg;
  310. oper[0]^.reg:=helpreg;
  311. oper[1]^.typ:=top_ref;
  312. new(oper[1]^.ref);
  313. oper[1]^.ref^:=spilltemplist[supreg];
  314. ungetregisterinline(list,helpins,helpreg);
  315. forward_allocation(Tai(helpins.next),instr);
  316. end
  317. else
  318. begin
  319. {Situation example:
  320. add r20d,r21d ; r20d must be spilled into [ebp-12]
  321. Change into:
  322. add [ebp-12],r21d ; Replace register by reference }
  323. if (opcode=A_MOVZX) or (opcode=A_MOVSX) then
  324. begin
  325. {Because 'movzx memory,register' does not exist...}
  326. result:=true;
  327. op:=opcode;
  328. hopsize:=opsize;
  329. opcode:=A_MOV;
  330. opsize:=reg2opsize(oper[1]^.reg);
  331. pos:=get_insert_pos(Tai(instr.previous),getsupreg(oper[0]^.reg),RS_INVALID,RS_INVALID);
  332. getregisterinline(list,pos,subreg,helpreg);
  333. helpins:=Taicpu.op_reg_reg(op,hopsize,oper[0]^.reg,helpreg);
  334. if pos=nil then
  335. list.insertafter(helpins,list.first)
  336. else
  337. list.insertafter(helpins,pos.next);
  338. oper[0]^.reg:=helpreg;
  339. ungetregisterinline(list,helpins,helpreg);
  340. forward_allocation(Tai(helpins.next),instr);
  341. end;
  342. oper[1]^.typ:=top_ref;
  343. new(oper[1]^.ref);
  344. oper[1]^.ref^:=spilltemplist[supreg];
  345. end;
  346. end;
  347. end;
  348. { The i386 instruction set never gets boring...
  349. some opcodes do not support a memory location as destination }
  350. if (oper[1]^.typ=top_ref) and
  351. (
  352. (oper[0]^.typ=top_const) or
  353. ((oper[0]^.typ=top_reg) and
  354. (getregtype(oper[0]^.reg)=regtype))
  355. ) then
  356. begin
  357. case opcode of
  358. A_IMUL :
  359. begin
  360. {Yikes! We just changed the destination register into
  361. a memory location above here.
  362. Situation examples:
  363. imul [ebp-12],r21d ; We need a help register
  364. imul [ebp-12],<const> ; We need a help register
  365. Change into:
  366. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  367. imul r22d,r21d ; Replace reference by helpregister
  368. mov [ebp-12],r22d ; Use another help instruction}
  369. getregisterinline(list,Tai(previous),subreg,helpreg);
  370. result:=true;
  371. {First help instruction.}
  372. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[1]^.ref^,helpreg);
  373. if previous=nil then
  374. list.insert(helpins)
  375. else
  376. list.insertafter(helpins,previous);
  377. {Second help instruction.}
  378. helpins:=Taicpu.op_reg_ref(A_MOV,opsize,helpreg,oper[1]^.ref^);
  379. dispose(oper[1]^.ref);
  380. oper[1]^.typ:=top_reg;
  381. oper[1]^.reg:=helpreg;
  382. list.insertafter(helpins,instr);
  383. ungetregisterinline(list,instr,helpreg);
  384. end;
  385. end;
  386. end;
  387. { The i386 instruction set never gets boring...
  388. some opcodes do not support a memory location as source }
  389. if (oper[0]^.typ=top_ref) and
  390. (oper[1]^.typ=top_reg) and
  391. (getregtype(oper[1]^.reg)=regtype) then
  392. begin
  393. case opcode of
  394. A_BT,A_BTS,
  395. A_BTC,A_BTR :
  396. begin
  397. {Yikes! We just changed the source register into
  398. a memory location above here.
  399. Situation example:
  400. bt r21d,[ebp-12] ; We need a help register
  401. Change into:
  402. mov r22d,[ebp-12] ; Use a help instruction (only for IMUL)
  403. bt r21d,r22d ; Replace reference by helpregister}
  404. getregisterinline(list,Tai(previous),subreg,helpreg);
  405. result:=true;
  406. {First help instruction.}
  407. helpins:=Taicpu.op_ref_reg(A_MOV,opsize,oper[0]^.ref^,helpreg);
  408. if previous=nil then
  409. list.insert(helpins)
  410. else
  411. list.insertafter(helpins,previous);
  412. dispose(oper[0]^.ref);
  413. oper[0]^.typ:=top_reg;
  414. oper[0]^.reg:=helpreg;
  415. ungetregisterinline(list,helpins,helpreg);
  416. end;
  417. end;
  418. end;
  419. end;
  420. 3:
  421. begin
  422. {$warning todo!!}
  423. end;
  424. end;
  425. end;
  426. end;
  427. {******************************************************************************
  428. Trgx86fpu
  429. ******************************************************************************}
  430. constructor Trgx86fpu.create;
  431. var i:Tsuperregister;
  432. begin
  433. used_in_proc:=[];
  434. t_times := 0;
  435. unusedregsfpu:=usableregsfpu;
  436. end;
  437. function trgx86fpu.getregisterfpu(list: taasmoutput) : tregister;
  438. begin
  439. { note: don't return R_ST0, see comments above implementation of }
  440. { a_loadfpu_* methods in cgcpu (JM) }
  441. result:=NR_ST;
  442. end;
  443. procedure trgx86fpu.ungetregisterfpu(list : taasmoutput; r : tregister);
  444. begin
  445. { nothing to do, fpu stack management is handled by the load/ }
  446. { store operations in cgcpu (JM) }
  447. end;
  448. function trgx86fpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
  449. begin
  450. correct_fpuregister:=r;
  451. setsupreg(correct_fpuregister,ofs);
  452. end;
  453. procedure trgx86fpu.saveusedfpuregisters(list: taasmoutput;
  454. var saved : tpushedsavedfpu;
  455. const s: tcpuregisterset);
  456. var
  457. r : tregister;
  458. hr : treference;
  459. begin
  460. used_in_proc:=used_in_proc+s;
  461. {$warning TODO firstsavefpureg}
  462. (*
  463. { don't try to save the fpu registers if not desired (e.g. for }
  464. { the 80x86) }
  465. if firstsavefpureg <> R_NO then
  466. for r.enum:=firstsavefpureg to lastsavefpureg do
  467. begin
  468. saved[r.enum].ofs:=reg_not_saved;
  469. { if the register is used by the calling subroutine and if }
  470. { it's not a regvar (those are handled separately) }
  471. if not is_reg_var_other[r.enum] and
  472. (r.enum in s) and
  473. { and is present in use }
  474. not(r.enum in unusedregsfpu) then
  475. begin
  476. { then save it }
  477. tg.GetTemp(list,extended_size,tt_persistent,hr);
  478. saved[r.enum].ofs:=hr.offset;
  479. cg.a_loadfpu_reg_ref(list,OS_FLOAT,r,hr);
  480. cg.a_reg_dealloc(list,r);
  481. include(unusedregsfpu,r.enum);
  482. inc(countunusedregsfpu);
  483. end;
  484. end;
  485. *)
  486. end;
  487. procedure trgx86fpu.restoreusedfpuregisters(list : taasmoutput;
  488. const saved : tpushedsavedfpu);
  489. var
  490. r,r2 : tregister;
  491. hr : treference;
  492. begin
  493. {$warning TODO firstsavefpureg}
  494. (*
  495. if firstsavefpureg <> R_NO then
  496. for r.enum:=lastsavefpureg downto firstsavefpureg do
  497. begin
  498. if saved[r.enum].ofs <> reg_not_saved then
  499. begin
  500. r2.enum:=R_INTREGISTER;
  501. r2.number:=NR_FRAME_POINTER_REG;
  502. reference_reset_base(hr,r2,saved[r.enum].ofs);
  503. cg.a_reg_alloc(list,r);
  504. cg.a_loadfpu_ref_reg(list,OS_FLOAT,hr,r);
  505. if not (r.enum in unusedregsfpu) then
  506. { internalerror(10)
  507. in n386cal we always save/restore the reg *state*
  508. using save/restoreunusedstate -> the current state
  509. may not be real (JM) }
  510. else
  511. begin
  512. dec(countunusedregsfpu);
  513. exclude(unusedregsfpu,r.enum);
  514. end;
  515. tg.UnGetTemp(list,hr);
  516. end;
  517. end;
  518. *)
  519. end;
  520. (*
  521. procedure Trgx86fpu.saveotherregvars(list: taasmoutput; const s: totherregisterset);
  522. var
  523. r: Tregister;
  524. begin
  525. if not(cs_regvars in aktglobalswitches) then
  526. exit;
  527. if firstsavefpureg <> NR_NO then
  528. for r.enum := firstsavefpureg to lastsavefpureg do
  529. if is_reg_var_other[r.enum] and
  530. (r.enum in s) then
  531. store_regvar(list,r);
  532. end;
  533. *)
  534. end.
  535. {
  536. $Log$
  537. Revision 1.4 2004-06-20 08:55:32 florian
  538. * logs truncated
  539. Revision 1.3 2004/06/16 20:07:11 florian
  540. * dwarf branch merged
  541. Revision 1.2.2.1 2004/04/10 12:36:42 peter
  542. * fixed alignment issues
  543. Revision 1.2 2004/01/12 16:37:59 peter
  544. * moved spilling code from taicpu to rg
  545. }