rgcpu.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the i386 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 rgcpu;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. cpubase,
  24. cpuinfo,
  25. aasmbase,aasmtai,aasmcpu,
  26. cclasses,globtype,cgbase,cginfo,rgobj;
  27. type
  28. trgcpu = class(trgobj)
  29. fpuvaroffset : byte;
  30. { to keep the same allocation order as with the old routines }
  31. {$ifndef newra}
  32. function getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;override;
  33. procedure ungetregisterint(list:Taasmoutput;r:Tregister); override;
  34. function getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;override;
  35. {$endif newra}
  36. function getregisterfpu(list: taasmoutput) : tregister; override;
  37. procedure ungetregisterfpu(list: taasmoutput; r : tregister); override;
  38. procedure ungetreference(list: taasmoutput; const ref : treference); override;
  39. {# Returns a subset register of the register r with the specified size.
  40. WARNING: There is no clearing of the upper parts of the register,
  41. if a 8-bit / 16-bit register is converted to a 32-bit register.
  42. It is up to the code generator to correctly zero fill the register
  43. }
  44. function makeregsize(reg: tregister; size: tcgsize): tregister; override;
  45. { pushes and restores registers }
  46. procedure pushusedintregisters(list:Taasmoutput;
  47. var pushed:Tpushedsavedint;
  48. const s:Tsupregset);
  49. procedure pushusedotherregisters(list:Taasmoutput;
  50. var pushed:Tpushedsaved;
  51. const s:Tregisterset);
  52. procedure popusedintregisters(list:Taasmoutput;
  53. const pushed:Tpushedsavedint);
  54. procedure popusedotherregisters(list:Taasmoutput;
  55. const pushed:Tpushedsaved);
  56. procedure saveusedintregisters(list:Taasmoutput;
  57. var saved:Tpushedsavedint;
  58. const s:Tsupregset);override;
  59. procedure saveusedotherregisters(list:Taasmoutput;
  60. var saved:Tpushedsaved;
  61. const s:Tregisterset);override;
  62. procedure restoreusedintregisters(list:Taasmoutput;
  63. const saved:Tpushedsavedint);override;
  64. procedure restoreusedotherregisters(list:Taasmoutput;
  65. const saved:Tpushedsaved);override;
  66. procedure resetusableregisters;override;
  67. { corrects the fpu stack register by ofs }
  68. function correct_fpuregister(r : tregister;ofs : byte) : tregister;
  69. end;
  70. implementation
  71. uses
  72. systems,
  73. globals,verbose,
  74. tgobj;
  75. {************************************************************************}
  76. { routine helpers }
  77. {************************************************************************}
  78. const
  79. reg2reg32 : array[firstreg..lastreg] of Toldregister = (R_NO,
  80. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  81. R_EAX,R_ECX,R_EDX,R_EBX,R_ESP,R_EBP,R_ESI,R_EDI,
  82. R_EAX,R_ECX,R_EDX,R_EBX,R_NO,R_NO,R_NO,R_NO,
  83. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  84. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  85. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  86. R_NO,R_NO,R_NO,R_NO,
  87. R_NO,R_NO,R_NO,R_NO,R_NO,
  88. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  89. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO
  90. );
  91. reg2reg16 : array[firstreg..lastreg] of Toldregister = (R_NO,
  92. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  93. R_AX,R_CX,R_DX,R_BX,R_SP,R_BP,R_SI,R_DI,
  94. R_AX,R_CX,R_DX,R_BX,R_NO,R_NO,R_NO,R_NO,
  95. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  96. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  97. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  98. R_NO,R_NO,R_NO,R_NO,
  99. R_NO,R_NO,R_NO,R_NO,R_NO,
  100. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  101. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO
  102. );
  103. reg2reg8 : array[firstreg..lastreg] of Toldregister = (R_NO,
  104. R_AL,R_CL,R_DL,R_BL,R_NO,R_NO,R_NO,R_NO,
  105. R_AL,R_CL,R_DL,R_BL,R_NO,R_NO,R_NO,R_NO,
  106. R_AL,R_CL,R_DL,R_BL,R_NO,R_NO,R_NO,R_NO,
  107. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  108. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  109. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  110. R_NO,R_NO,R_NO,R_NO,
  111. R_NO,R_NO,R_NO,R_NO,R_NO,
  112. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,
  113. R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO,R_NO
  114. );
  115. { convert a register to a specfied register size }
  116. function changeregsize(r:tregister;size:topsize):tregister;
  117. var
  118. reg : tregister;
  119. begin
  120. case size of
  121. S_B :
  122. reg.enum:=reg2reg8[r.enum];
  123. S_W :
  124. reg.enum:=reg2reg16[r.enum];
  125. S_L :
  126. reg.enum:=reg2reg32[r.enum];
  127. else
  128. internalerror(200204101);
  129. end;
  130. if reg.enum=R_NO then
  131. internalerror(200204102);
  132. changeregsize:=reg;
  133. end;
  134. {************************************************************************}
  135. { trgcpu }
  136. {************************************************************************}
  137. {$ifndef newra}
  138. function trgcpu.getregisterint(list:Taasmoutput;size:Tcgsize):Tregister;
  139. var subreg:Tsubregister;
  140. begin
  141. subreg:=cgsize2subreg(size);
  142. if countunusedregsint=0 then
  143. internalerror(10);
  144. getregisterint.enum:=R_INTREGISTER;
  145. {$ifdef TEMPREGDEBUG}
  146. if curptree^.usableregsint-countunusedregsint>curptree^.registers32 then
  147. internalerror(10);
  148. {$endif TEMPREGDEBUG}
  149. {$ifdef EXTTEMPREGDEBUG}
  150. if curptree^.usableregs-countunusedregistersint>curptree^^.reallyusedregs then
  151. curptree^.reallyusedregs:=curptree^^.usableregs-countunusedregistersint;
  152. {$endif EXTTEMPREGDEBUG}
  153. dec(countunusedregsint);
  154. if RS_EAX in unusedregsint then
  155. begin
  156. exclude(unusedregsint,RS_EAX);
  157. include(usedintinproc,RS_EAX);
  158. getregisterint.number:=RS_EAX shl 8 or subreg;
  159. {$ifdef TEMPREGDEBUG}
  160. reg_user[R_EAX]:=curptree^;
  161. {$endif TEMPREGDEBUG}
  162. exprasmlist.concat(tai_regalloc.alloc(getregisterint));
  163. end
  164. else if RS_EDX in unusedregsint then
  165. begin
  166. exclude(unusedregsint,RS_EDX);
  167. include(usedintinproc,RS_EDX);
  168. getregisterint.number:=RS_EDX shl 8 or subreg;
  169. {$ifdef TEMPREGDEBUG}
  170. reg_user[R_EDX]:=curptree^;
  171. {$endif TEMPREGDEBUG}
  172. exprasmlist.concat(tai_regalloc.alloc(getregisterint));
  173. end
  174. else if RS_EBX in unusedregsint then
  175. begin
  176. exclude(unusedregsint,RS_EBX);
  177. include(usedintinproc,RS_EBX);
  178. getregisterint.number:=RS_EBX shl 8 or subreg;
  179. {$ifdef TEMPREGDEBUG}
  180. reg_user[R_EBX]:=curptree^;
  181. {$endif TEMPREGDEBUG}
  182. exprasmlist.concat(tai_regalloc.alloc(getregisterint));
  183. end
  184. else if RS_ECX in unusedregsint then
  185. begin
  186. exclude(unusedregsint,RS_ECX);
  187. include(usedintinproc,RS_ECX);
  188. getregisterint.number:=RS_ECX shl 8 or subreg;
  189. {$ifdef TEMPREGDEBUG}
  190. reg_user[R_ECX]:=curptree^;
  191. {$endif TEMPREGDEBUG}
  192. exprasmlist.concat(tai_regalloc.alloc(getregisterint));
  193. end
  194. else internalerror(10);
  195. {$ifdef TEMPREGDEBUG}
  196. testregisters;
  197. {$endif TEMPREGDEBUG}
  198. end;
  199. procedure trgcpu.ungetregisterint(list: taasmoutput; r : tregister);
  200. var supreg:Tsuperregister;
  201. begin
  202. if r.enum=R_NO then
  203. exit;
  204. if r.enum<>R_INTREGISTER then
  205. internalerror(200301234);
  206. supreg:=r.number shr 8;
  207. if (supreg = RS_EDI) or
  208. ((not assigned(procinfo._class)) and (supreg = RS_ESI)) then
  209. begin
  210. list.concat(tai_regalloc.DeAlloc(r));
  211. exit;
  212. end;
  213. if not(supreg in [RS_EAX,RS_EBX,RS_ECX,RS_EDX]) then
  214. exit;
  215. inherited ungetregisterint(list,r);
  216. end;
  217. function trgcpu.getexplicitregisterint(list:Taasmoutput;r:Tnewregister):Tregister;
  218. var r2:Tregister;
  219. begin
  220. if (r shr 8) in [RS_ESI,RS_EDI] then
  221. begin
  222. r2.enum:=R_INTREGISTER;
  223. r2.number:=r;
  224. list.concat(Tai_regalloc.alloc(r2));
  225. getexplicitregisterint:=r2;
  226. exit;
  227. end;
  228. result:=inherited getexplicitregisterint(list,r);
  229. end;
  230. {$endif newra}
  231. function trgcpu.getregisterfpu(list: taasmoutput) : tregister;
  232. begin
  233. { note: don't return R_ST0, see comments above implementation of }
  234. { a_loadfpu_* methods in cgcpu (JM) }
  235. result.enum := R_ST;
  236. end;
  237. procedure trgcpu.ungetregisterfpu(list : taasmoutput; r : tregister);
  238. begin
  239. { nothing to do, fpu stack management is handled by the load/ }
  240. { store operations in cgcpu (JM) }
  241. end;
  242. procedure trgcpu.ungetreference(list: taasmoutput; const ref : treference);
  243. begin
  244. if ref.base.number<>NR_NO then
  245. ungetregisterint(list,ref.base);
  246. if ref.index.number<>NR_NO then
  247. ungetregisterint(list,ref.index);
  248. end;
  249. procedure trgcpu.pushusedintregisters(list:Taasmoutput;
  250. var pushed:Tpushedsavedint;
  251. const s:Tsupregset);
  252. var r:Tsuperregister;
  253. r2:Tregister;
  254. begin
  255. usedintinproc:=usedintinproc+s;
  256. for r:=RS_EAX to RS_EDX do
  257. begin
  258. r2.enum:=R_INTREGISTER;
  259. r2.number:=r shl 8 or R_SUBWHOLE;
  260. pushed[r].pushed:=false;
  261. { if the register is used by the calling subroutine }
  262. if not(r in is_reg_var_int) and (r in s) and
  263. { and is present in use }
  264. not(r in unusedregsint) then
  265. begin
  266. { then save it }
  267. list.concat(Taicpu.Op_reg(A_PUSH,S_L,r2));
  268. include(unusedregsint,r);
  269. inc(countunusedregsint);
  270. pushed[r].pushed:=true;
  271. end;
  272. end;
  273. {$ifdef TEMPREGDEBUG}
  274. testregisters;
  275. {$endif TEMPREGDEBUG}
  276. end;
  277. {$ifdef SUPPORT_MMX}
  278. procedure trgcpu.pushusedotherregisters(list:Taasmoutput;
  279. var pushed:Tpushedsaved;
  280. const s:Tregisterset);
  281. var r:Toldregister;
  282. r2:Tregister;
  283. hr:Treference;
  284. begin
  285. usedinproc:=usedinproc+s;
  286. for r:=R_MM0 to R_MM6 do
  287. begin
  288. pushed[r].pushed:=false;
  289. { if the register is used by the calling subroutine }
  290. if not is_reg_var[r] and
  291. (r in s) and
  292. { and is present in use }
  293. not(r in unusedregsmm) then
  294. begin
  295. r2.enum:=R_ESP;
  296. list.concat(Taicpu.Op_const_reg(A_SUB,S_L,8,r2));
  297. reference_reset_base(hr,r2,0);
  298. r2.enum:=r;
  299. list.concat(Taicpu.Op_reg_ref(A_MOVQ,S_NO,r2,hr));
  300. include(unusedregsmm,r);
  301. inc(countunusedregsmm);
  302. pushed[r].pushed:=true;
  303. end;
  304. end;
  305. {$ifdef TEMPREGDEBUG}
  306. testregisters;
  307. {$endif TEMPREGDEBUG}
  308. end;
  309. {$endif SUPPORT_MMX}
  310. procedure trgcpu.popusedintregisters(list:Taasmoutput;
  311. const pushed:Tpushedsavedint);
  312. var r:Tsuperregister;
  313. r2:Tregister;
  314. begin
  315. { restore in reverse order: }
  316. for r:=RS_EDX downto RS_EAX do
  317. if pushed[r].pushed then
  318. begin
  319. r2.enum:=R_INTREGISTER;
  320. r2.number:=r shl 8 or R_SUBWHOLE;
  321. list.concat(Taicpu.op_reg(A_POP,S_L,r2));
  322. if not (r in unusedregsint) then
  323. { internalerror(10)
  324. in cg386cal we always restore regs
  325. that appear as used
  326. due to a unused tmep storage PM }
  327. else
  328. dec(countunusedregsint);
  329. exclude(unusedregsint,r);
  330. end;
  331. {$ifdef TEMPREGDEBUG}
  332. testregisters;
  333. {$endif TEMPREGDEBUG}
  334. end;
  335. {$ifdef SUPPORT_MMX}
  336. procedure trgcpu.popusedotherregisters(list:Taasmoutput;
  337. const pushed:Tpushedsaved);
  338. var r:Toldregister;
  339. r2,r3:Tregister;
  340. hr:Treference;
  341. begin
  342. { restore in reverse order: }
  343. for r:=R_MM6 downto R_MM0 do
  344. if pushed[r].pushed then
  345. begin
  346. r2.enum:=R_ESP;
  347. reference_reset_base(hr,r2,0);
  348. r3.enum:=r;
  349. list.concat(Taicpu.op_ref_reg(A_MOVQ,S_NO,hr,r3));
  350. list.concat(Taicpu.op_const_reg(A_ADD,S_L,8,r2));
  351. if not (r in unusedregsmm) then
  352. { internalerror(10)
  353. in cg386cal we always restore regs
  354. that appear as used
  355. due to a unused tmep storage PM }
  356. else
  357. dec(countunusedregsmm);
  358. exclude(unusedregsmm,r);
  359. end;
  360. {$ifdef TEMPREGDEBUG}
  361. testregisters;
  362. {$endif TEMPREGDEBUG}
  363. end;
  364. {$endif SUPPORT_MMX}
  365. procedure trgcpu.saveusedintregisters(list:Taasmoutput;
  366. var saved:Tpushedsavedint;
  367. const s:Tsupregset);
  368. begin
  369. if (aktoptprocessor in [class386,classP5]) or
  370. (CS_LittleSize in aktglobalswitches) then
  371. pushusedintregisters(list,saved,s)
  372. else
  373. inherited saveusedintregisters(list,saved,s);
  374. end;
  375. procedure trgcpu.saveusedotherregisters(list:Taasmoutput;var saved:Tpushedsaved;
  376. const s:tregisterset);
  377. begin
  378. if (aktoptprocessor in [class386,classP5]) or
  379. (CS_LittleSize in aktglobalswitches) then
  380. pushusedotherregisters(list,saved,s)
  381. else
  382. inherited saveusedotherregisters(list,saved,s);
  383. end;
  384. procedure trgcpu.restoreusedintregisters(list:Taasmoutput;
  385. const saved:tpushedsavedint);
  386. begin
  387. if (aktoptprocessor in [class386,classP5]) or
  388. (CS_LittleSize in aktglobalswitches) then
  389. popusedintregisters(list,saved)
  390. else
  391. inherited restoreusedintregisters(list,saved);
  392. end;
  393. procedure trgcpu.restoreusedotherregisters(list:Taasmoutput;
  394. const saved:tpushedsaved);
  395. begin
  396. if (aktoptprocessor in [class386,classP5]) or
  397. (CS_LittleSize in aktglobalswitches) then
  398. popusedotherregisters(list,saved)
  399. else
  400. inherited restoreusedotherregisters(list,saved);
  401. end;
  402. procedure trgcpu.resetusableregisters;
  403. begin
  404. inherited resetusableregisters;
  405. fpuvaroffset := 0;
  406. end;
  407. function trgcpu.correct_fpuregister(r : tregister;ofs : byte) : tregister;
  408. begin
  409. correct_fpuregister.enum:=Toldregister(longint(r.enum)+ofs);
  410. end;
  411. function trgcpu.makeregsize(reg: tregister; size: tcgsize): tregister;
  412. var
  413. _result : topsize;
  414. begin
  415. case size of
  416. OS_32,OS_S32:
  417. begin
  418. _result := S_L;
  419. end;
  420. OS_8,OS_S8:
  421. begin
  422. _result := S_B;
  423. end;
  424. OS_16,OS_S16:
  425. begin
  426. _result := S_W;
  427. end;
  428. else
  429. internalerror(2001092312);
  430. end;
  431. makeregsize := changeregsize(reg,_result);
  432. end;
  433. initialization
  434. rg := trgcpu.create;
  435. end.
  436. {
  437. $Log$
  438. Revision 1.15 2003-03-08 13:59:17 daniel
  439. * Work to handle new register notation in ag386nsm
  440. + Added newra version of Ti386moddivnode
  441. Revision 1.14 2003/03/08 08:59:07 daniel
  442. + $define newra will enable new register allocator
  443. + getregisterint will return imaginary registers with $newra
  444. + -sr switch added, will skip register allocation so you can see
  445. the direct output of the code generator before register allocation
  446. Revision 1.13 2003/03/07 21:57:53 daniel
  447. * Improved getregisterint
  448. Revision 1.12 2003/02/19 22:00:16 daniel
  449. * Code generator converted to new register notation
  450. - Horribily outdated todo.txt removed
  451. Revision 1.11 2003/01/08 18:43:57 daniel
  452. * Tregister changed into a record
  453. Revision 1.10 2002/10/05 12:43:29 carl
  454. * fixes for Delphi 6 compilation
  455. (warning : Some features do not work under Delphi)
  456. Revision 1.9 2002/08/17 09:23:48 florian
  457. * first part of procinfo rewrite
  458. Revision 1.8 2002/07/01 18:46:34 peter
  459. * internal linker
  460. * reorganized aasm layer
  461. Revision 1.7 2002/05/16 19:46:52 carl
  462. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  463. + try to fix temp allocation (still in ifdef)
  464. + generic constructor calls
  465. + start of tassembler / tmodulebase class cleanup
  466. Revision 1.6 2002/05/12 16:53:18 peter
  467. * moved entry and exitcode to ncgutil and cgobj
  468. * foreach gets extra argument for passing local data to the
  469. iterator function
  470. * -CR checks also class typecasts at runtime by changing them
  471. into as
  472. * fixed compiler to cycle with the -CR option
  473. * fixed stabs with elf writer, finally the global variables can
  474. be watched
  475. * removed a lot of routines from cga unit and replaced them by
  476. calls to cgobj
  477. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  478. u32bit then the other is typecasted also to u32bit without giving
  479. a rangecheck warning/error.
  480. * fixed pascal calling method with reversing also the high tree in
  481. the parast, detected by tcalcst3 test
  482. Revision 1.5 2002/04/21 15:43:32 carl
  483. * changeregsize -> rg.makeregsize
  484. * changeregsize moved from cpubase to here
  485. Revision 1.4 2002/04/15 19:44:22 peter
  486. * fixed stackcheck that would be called recursively when a stack
  487. error was found
  488. * generic changeregsize(reg,size) for i386 register resizing
  489. * removed some more routines from cga unit
  490. * fixed returnvalue handling
  491. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  492. Revision 1.3 2002/04/04 19:06:13 peter
  493. * removed unused units
  494. * use tlocation.size in cg.a_*loc*() routines
  495. Revision 1.2 2002/04/02 17:11:39 peter
  496. * tlocation,treference update
  497. * LOC_CONSTANT added for better constant handling
  498. * secondadd splitted in multiple routines
  499. * location_force_reg added for loading a location to a register
  500. of a specified size
  501. * secondassignment parses now first the right and then the left node
  502. (this is compatible with Kylix). This saves a lot of push/pop especially
  503. with string operations
  504. * adapted some routines to use the new cg methods
  505. Revision 1.1 2002/03/31 20:26:40 jonas
  506. + a_loadfpu_* and a_loadmm_* methods in tcg
  507. * register allocation is now handled by a class and is mostly processor
  508. independent (+rgobj.pas and i386/rgcpu.pas)
  509. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  510. * some small improvements and fixes to the optimizer
  511. * some register allocation fixes
  512. * some fpuvaroffset fixes in the unary minus node
  513. * push/popusedregisters is now called rg.save/restoreusedregisters and
  514. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  515. also better optimizable)
  516. * fixed and optimized register saving/restoring for new/dispose nodes
  517. * LOC_FPU locations now also require their "register" field to be set to
  518. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  519. - list field removed of the tnode class because it's not used currently
  520. and can cause hard-to-find bugs
  521. }