ncgcnv.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. Generate assembler for nodes that handle type conversions which are
  5. the same for all (most) processors
  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 ncgcnv;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,ncnv,defbase;
  24. type
  25. tcgtypeconvnode = class(ttypeconvnode)
  26. procedure second_int_to_int;override;
  27. procedure second_cstring_to_pchar;override;
  28. procedure second_string_to_chararray;override;
  29. procedure second_array_to_pointer;override;
  30. procedure second_pointer_to_array;override;
  31. procedure second_char_to_string;override;
  32. procedure second_real_to_real;override;
  33. procedure second_cord_to_pointer;override;
  34. procedure second_proc_to_procvar;override;
  35. procedure second_bool_to_int;override;
  36. procedure second_bool_to_bool;override;
  37. procedure second_ansistring_to_pchar;override;
  38. procedure second_class_to_intf;override;
  39. procedure second_char_to_char;override;
  40. procedure second_nothing;override;
  41. {$ifdef TESTOBJEXT2}
  42. procedure checkobject;virtual;
  43. {$endif TESTOBJEXT2}
  44. procedure second_call_helper(c : tconverttype);virtual;abstract;
  45. procedure pass_2;override;
  46. end;
  47. tcgasnode = class(tasnode)
  48. procedure pass_2;override;
  49. end;
  50. implementation
  51. uses
  52. cutils,verbose,
  53. aasmbase,aasmtai,aasmcpu,symconst,symdef,paramgr,
  54. ncon,ncal,
  55. cpubase,cpuinfo,cpupara,
  56. pass_2,
  57. cginfo,cgbase,
  58. cgobj,cgcpu,
  59. ncgutil,
  60. tgobj,rgobj
  61. ;
  62. procedure tcgtypeconvnode.second_int_to_int;
  63. var
  64. newsize : tcgsize;
  65. begin
  66. newsize:=def_cgsize(resulttype.def);
  67. { insert range check if not explicit conversion }
  68. if not(nf_explizit in flags) then
  69. cg.g_rangecheck(exprasmlist,left,resulttype.def);
  70. { is the result size smaller ? }
  71. if resulttype.def.size<>left.resulttype.def.size then
  72. begin
  73. location_copy(location,left.location);
  74. { reuse a loc_reference when the newsize is smaller than
  75. than the original, else load it to a register }
  76. if (location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  77. (resulttype.def.size<left.resulttype.def.size) then
  78. location.size:=newsize
  79. else
  80. location_force_reg(exprasmlist,location,newsize,false);
  81. end
  82. else
  83. begin
  84. { no special loading is required, reuse current location }
  85. location_copy(location,left.location);
  86. location.size:=newsize;
  87. end;
  88. end;
  89. procedure tcgtypeconvnode.second_cstring_to_pchar;
  90. var
  91. hr : treference;
  92. begin
  93. location_release(exprasmlist,left.location);
  94. location_reset(location,LOC_REGISTER,OS_ADDR);
  95. case tstringdef(left.resulttype.def).string_typ of
  96. st_shortstring :
  97. begin
  98. inc(left.location.reference.offset);
  99. location.register:=rg.getaddressregister(exprasmlist);
  100. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
  101. end;
  102. st_ansistring :
  103. begin
  104. if (left.nodetype=stringconstn) and
  105. (str_length(left)=0) then
  106. begin
  107. reference_reset(hr);
  108. hr.symbol:=objectlibrary.newasmsymbol('FPC_EMPTYCHAR');
  109. location.register:=rg.getaddressregister(exprasmlist);
  110. cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
  111. end
  112. else
  113. begin
  114. location.register:=rg.getaddressregister(exprasmlist);
  115. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.register);
  116. end;
  117. end;
  118. st_longstring:
  119. begin
  120. {!!!!!!!}
  121. internalerror(8888);
  122. end;
  123. st_widestring:
  124. begin
  125. if (left.nodetype=stringconstn) and
  126. (str_length(left)=0) then
  127. begin
  128. reference_reset(hr);
  129. hr.symbol:=objectlibrary.newasmsymbol('FPC_EMPTYCHAR');
  130. location.register:=rg.getaddressregister(exprasmlist);
  131. cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
  132. end
  133. else
  134. begin
  135. location.register:=rg.getregisterint(exprasmlist);
  136. {$warning Todo: convert widestrings to ascii when typecasting them to pchars}
  137. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
  138. location.register);
  139. end;
  140. end;
  141. end;
  142. end;
  143. procedure tcgtypeconvnode.second_string_to_chararray;
  144. var
  145. arrsize: longint;
  146. begin
  147. with tarraydef(resulttype.def) do
  148. arrsize := highrange-lowrange+1;
  149. if (left.nodetype = stringconstn) and
  150. { left.length+1 since there's always a terminating #0 character (JM) }
  151. (tstringconstnode(left).len+1 >= arrsize) and
  152. (tstringdef(left.resulttype.def).string_typ=st_shortstring) then
  153. begin
  154. location_copy(location,left.location);
  155. inc(location.reference.offset);
  156. exit;
  157. end
  158. else
  159. { should be handled already in resulttype pass (JM) }
  160. internalerror(200108292);
  161. end;
  162. procedure tcgtypeconvnode.second_array_to_pointer;
  163. begin
  164. location_release(exprasmlist,left.location);
  165. location_reset(location,LOC_REGISTER,OS_ADDR);
  166. location.register:=rg.getaddressregister(exprasmlist);
  167. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
  168. end;
  169. procedure tcgtypeconvnode.second_pointer_to_array;
  170. begin
  171. location_reset(location,LOC_REFERENCE,OS_NO);
  172. case left.location.loc of
  173. LOC_REGISTER :
  174. begin
  175. if not rg.isaddressregister(left.location.register) then
  176. begin
  177. location_release(exprasmlist,left.location);
  178. location.reference.base:=rg.getaddressregister(exprasmlist);
  179. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  180. left.location.register,location.reference.base);
  181. end
  182. else
  183. location.reference.base := left.location.register;
  184. end;
  185. LOC_CREGISTER :
  186. begin
  187. location.reference.base:=rg.getregisterint(exprasmlist);
  188. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
  189. location.reference.base);
  190. end;
  191. LOC_REFERENCE,
  192. LOC_CREFERENCE :
  193. begin
  194. location_release(exprasmlist,left.location);
  195. location.reference.base:=rg.getaddressregister(exprasmlist);
  196. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
  197. location.reference.base);
  198. location_freetemp(exprasmlist,left.location);
  199. end;
  200. else
  201. internalerror(2002032216);
  202. end;
  203. end;
  204. procedure tcgtypeconvnode.second_char_to_string;
  205. begin
  206. location_reset(location,LOC_REFERENCE,OS_NO);
  207. case tstringdef(resulttype.def).string_typ of
  208. st_shortstring :
  209. begin
  210. tg.GetTemp(exprasmlist,256,tt_normal,location.reference);
  211. cg.a_load_loc_ref(exprasmlist,left.location,
  212. location.reference);
  213. location_release(exprasmlist,left.location);
  214. location_freetemp(exprasmlist,left.location);
  215. end;
  216. { the rest is removed in the resulttype pass and converted to compilerprocs }
  217. else
  218. internalerror(4179);
  219. end;
  220. end;
  221. procedure tcgtypeconvnode.second_real_to_real;
  222. begin
  223. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  224. case left.location.loc of
  225. LOC_FPUREGISTER,
  226. LOC_CFPUREGISTER:
  227. begin
  228. location_copy(location,left.location);
  229. location.size:=def_cgsize(resulttype.def);
  230. exit;
  231. end;
  232. LOC_CREFERENCE,
  233. LOC_REFERENCE:
  234. begin
  235. location_release(exprasmlist,left.location);
  236. location.register:=rg.getregisterfpu(exprasmlist);
  237. cg.a_loadfpu_loc_reg(exprasmlist,left.location,location.register);
  238. location_freetemp(exprasmlist,left.location);
  239. end;
  240. else
  241. internalerror(2002032215);
  242. end;
  243. end;
  244. procedure tcgtypeconvnode.second_cord_to_pointer;
  245. begin
  246. { this can't happen because constants are already processed in
  247. pass 1 }
  248. internalerror(47423985);
  249. end;
  250. procedure tcgtypeconvnode.second_proc_to_procvar;
  251. begin
  252. { method pointer ? }
  253. if assigned(tunarynode(left).left) then
  254. begin
  255. location_copy(location,left.location);
  256. end
  257. else
  258. begin
  259. location_release(exprasmlist,left.location);
  260. location_reset(location,LOC_REGISTER,OS_ADDR);
  261. location.register:=rg.getaddressregister(exprasmlist);
  262. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
  263. end;
  264. end;
  265. procedure tcgtypeconvnode.second_bool_to_int;
  266. var
  267. oldtruelabel,oldfalselabel : tasmlabel;
  268. begin
  269. oldtruelabel:=truelabel;
  270. oldfalselabel:=falselabel;
  271. objectlibrary.getlabel(truelabel);
  272. objectlibrary.getlabel(falselabel);
  273. secondpass(left);
  274. location_copy(location,left.location);
  275. { byte(boolean) or word(wordbool) or longint(longbool) must }
  276. { be accepted for var parameters }
  277. if not((nf_explizit in flags) and
  278. (left.resulttype.def.size=resulttype.def.size) and
  279. (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE,LOC_CREGISTER])) then
  280. location_force_reg(exprasmlist,location,def_cgsize(resulttype.def),false);
  281. truelabel:=oldtruelabel;
  282. falselabel:=oldfalselabel;
  283. end;
  284. procedure tcgtypeconvnode.second_bool_to_bool;
  285. begin
  286. { we can reuse the conversion already available
  287. in bool_to_int to resize the value. But when the
  288. size of the new boolean is smaller we need to calculate
  289. the value as is done in int_to_bool. This is needed because
  290. the bits that define the true status can be outside the limits
  291. of the new size and truncating the register can result in a 0
  292. value }
  293. if resulttype.def.size<left.resulttype.def.size then
  294. second_int_to_bool
  295. else
  296. second_bool_to_int;
  297. end;
  298. procedure tcgtypeconvnode.second_ansistring_to_pchar;
  299. var
  300. l1 : tasmlabel;
  301. hr : treference;
  302. begin
  303. location_reset(location,LOC_REGISTER,OS_ADDR);
  304. objectlibrary.getlabel(l1);
  305. case left.location.loc of
  306. LOC_CREGISTER,LOC_REGISTER:
  307. begin
  308. if not rg.isaddressregister(left.location.register) then
  309. begin
  310. location_release(exprasmlist,left.location);
  311. location.register:=rg.getaddressregister(exprasmlist);
  312. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  313. left.location.register,location.register);
  314. end
  315. else
  316. location.register := left.location.register;
  317. end;
  318. LOC_CREFERENCE,LOC_REFERENCE:
  319. begin
  320. location_release(exprasmlist,left.location);
  321. location.register:=rg.getaddressregister(exprasmlist);
  322. cg.a_load_ref_reg(exprasmlist,OS_32,left.location.reference,location.register);
  323. location_freetemp(exprasmlist,left.location);
  324. end;
  325. else
  326. internalerror(2002032214);
  327. end;
  328. cg.a_cmp_const_reg_label(exprasmlist,OS_32,OC_NE,0,location.register,l1);
  329. reference_reset(hr);
  330. hr.symbol:=objectlibrary.newasmsymbol('FPC_EMPTYCHAR');
  331. cg.a_loadaddr_ref_reg(exprasmlist,hr,location.register);
  332. cg.a_label(exprasmlist,l1);
  333. end;
  334. procedure tcgtypeconvnode.second_class_to_intf;
  335. var
  336. l1 : tasmlabel;
  337. hd : tobjectdef;
  338. begin
  339. location_reset(location,LOC_REGISTER,OS_ADDR);
  340. case left.location.loc of
  341. LOC_CREFERENCE,
  342. LOC_REFERENCE:
  343. begin
  344. location_release(exprasmlist,left.location);
  345. location.register:=rg.getregisterint(exprasmlist);
  346. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.register);
  347. location_freetemp(exprasmlist,left.location);
  348. end;
  349. LOC_CREGISTER:
  350. begin
  351. location.register:=rg.getregisterint(exprasmlist);
  352. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,location.register);
  353. end;
  354. LOC_REGISTER:
  355. location.register:=left.location.register;
  356. else
  357. internalerror(121120001);
  358. end;
  359. objectlibrary.getlabel(l1);
  360. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,location.register,l1);
  361. hd:=tobjectdef(left.resulttype.def);
  362. while assigned(hd) do
  363. begin
  364. if hd.implementedinterfaces.searchintf(resulttype.def)<>-1 then
  365. begin
  366. cg.a_op_const_reg(exprasmlist,OP_ADD,aword(
  367. hd.implementedinterfaces.ioffsets(
  368. hd.implementedinterfaces.searchintf(
  369. resulttype.def))^),location.register);
  370. break;
  371. end;
  372. hd:=hd.childof;
  373. end;
  374. if hd=nil then
  375. internalerror(2002081301);
  376. cg.a_label(exprasmlist,l1);
  377. end;
  378. procedure tcgtypeconvnode.second_char_to_char;
  379. begin
  380. {$warning todo: add RTL routine for widechar-char conversion }
  381. { Quick hack to atleast generate 'working' code (PFV) }
  382. second_int_to_int;
  383. end;
  384. procedure tcgtypeconvnode.second_nothing;
  385. begin
  386. { we reuse the old value }
  387. location_copy(location,left.location);
  388. { Floats should never be returned as LOC_CONSTANT, do the
  389. moving to memory before the new size is set }
  390. if (resulttype.def.deftype=floatdef) and
  391. (location.loc=LOC_CONSTANT) then
  392. location_force_mem(exprasmlist,location);
  393. { but use the new size, but we don't know the size of all arrays }
  394. location.size:=def_cgsize(resulttype.def);
  395. end;
  396. {$ifdef TESTOBJEXT2}
  397. procedure tcgtypeconvnode.checkobject;
  398. begin
  399. { no checking by default }
  400. end;
  401. {$endif TESTOBJEXT2}
  402. procedure tcgtypeconvnode.pass_2;
  403. begin
  404. { the boolean routines can be called with LOC_JUMP and
  405. call secondpass themselves in the helper }
  406. if not(convtype in [tc_bool_2_int,tc_bool_2_bool,tc_int_2_bool]) then
  407. begin
  408. secondpass(left);
  409. if codegenerror then
  410. exit;
  411. end;
  412. second_call_helper(convtype);
  413. {$ifdef TESTOBJEXT2}
  414. { Check explicit conversions to objects pointers !! }
  415. if p^.explizit and
  416. (p^.resulttype.def.deftype=pointerdef) and
  417. (tpointerdef(p^.resulttype.def).definition.deftype=objectdef) and not
  418. (tobjectdef(tpointerdef(p^.resulttype.def).definition).isclass) and
  419. ((tobjectdef(tpointerdef(p^.resulttype.def).definition).options and oo_hasvmt)<>0) and
  420. (cs_check_range in aktlocalswitches) then
  421. checkobject;
  422. {$endif TESTOBJEXT2}
  423. end;
  424. procedure tcgasnode.pass_2;
  425. begin
  426. secondpass(call);
  427. location_copy(location,call.location);
  428. end;
  429. begin
  430. ctypeconvnode := tcgtypeconvnode;
  431. casnode := tcgasnode;
  432. end.
  433. {
  434. $Log$
  435. Revision 1.29 2002-09-02 18:46:00 peter
  436. * reuse a reference when resizing ordinal values to smaller sizes,
  437. this is required for constructions like byte(w):=1 that are
  438. allowed in tp mode only
  439. Revision 1.28 2002/08/25 09:06:58 peter
  440. * add calls to release temps
  441. Revision 1.27 2002/08/23 16:14:48 peter
  442. * tempgen cleanup
  443. * tt_noreuse temp type added that will be used in genentrycode
  444. Revision 1.26 2002/08/20 18:23:32 jonas
  445. * the as node again uses a compilerproc
  446. + (untested) support for interface "as" statements
  447. Revision 1.25 2002/08/13 18:01:52 carl
  448. * rename swatoperands to swapoperands
  449. + m68k first compilable version (still needs a lot of testing):
  450. assembler generator, system information , inline
  451. assembler reader.
  452. Revision 1.24 2002/08/12 20:39:17 florian
  453. * casting of classes to interface fixed when the interface was
  454. implemented by a parent class
  455. Revision 1.23 2002/08/11 14:32:26 peter
  456. * renamed current_library to objectlibrary
  457. Revision 1.22 2002/08/11 13:24:11 peter
  458. * saving of asmsymbols in ppu supported
  459. * asmsymbollist global is removed and moved into a new class
  460. tasmlibrarydata that will hold the info of a .a file which
  461. corresponds with a single module. Added librarydata to tmodule
  462. to keep the library info stored for the module. In the future the
  463. objectfiles will also be stored to the tasmlibrarydata class
  464. * all getlabel/newasmsymbol and friends are moved to the new class
  465. Revision 1.21 2002/07/20 11:57:53 florian
  466. * types.pas renamed to defbase.pas because D6 contains a types
  467. unit so this would conflicts if D6 programms are compiled
  468. + Willamette/SSE2 instructions to assembler added
  469. Revision 1.20 2002/07/11 14:41:28 florian
  470. * start of the new generic parameter handling
  471. Revision 1.19 2002/07/07 09:52:32 florian
  472. * powerpc target fixed, very simple units can be compiled
  473. * some basic stuff for better callparanode handling, far from being finished
  474. Revision 1.18 2002/07/04 20:43:01 florian
  475. * first x86-64 patches
  476. Revision 1.17 2002/07/01 18:46:22 peter
  477. * internal linker
  478. * reorganized aasm layer
  479. Revision 1.16 2002/07/01 16:23:53 peter
  480. * cg64 patch
  481. * basics for currency
  482. * asnode updates for class and interface (not finished)
  483. Revision 1.15 2002/05/18 13:34:09 peter
  484. * readded missing revisions
  485. Revision 1.14 2002/05/16 19:46:37 carl
  486. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  487. + try to fix temp allocation (still in ifdef)
  488. + generic constructor calls
  489. + start of tassembler / tmodulebase class cleanup
  490. Revision 1.12 2002/05/12 16:53:07 peter
  491. * moved entry and exitcode to ncgutil and cgobj
  492. * foreach gets extra argument for passing local data to the
  493. iterator function
  494. * -CR checks also class typecasts at runtime by changing them
  495. into as
  496. * fixed compiler to cycle with the -CR option
  497. * fixed stabs with elf writer, finally the global variables can
  498. be watched
  499. * removed a lot of routines from cga unit and replaced them by
  500. calls to cgobj
  501. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  502. u32bit then the other is typecasted also to u32bit without giving
  503. a rangecheck warning/error.
  504. * fixed pascal calling method with reversing also the high tree in
  505. the parast, detected by tcalcst3 test
  506. Revision 1.11 2002/04/21 19:02:03 peter
  507. * removed newn and disposen nodes, the code is now directly
  508. inlined from pexpr
  509. * -an option that will write the secondpass nodes to the .s file, this
  510. requires EXTDEBUG define to actually write the info
  511. * fixed various internal errors and crashes due recent code changes
  512. Revision 1.10 2002/04/19 15:39:34 peter
  513. * removed some more routines from cga
  514. * moved location_force_reg/mem to ncgutil
  515. * moved arrayconstructnode secondpass to ncgld
  516. Revision 1.9 2002/04/15 19:44:19 peter
  517. * fixed stackcheck that would be called recursively when a stack
  518. error was found
  519. * generic changeregsize(reg,size) for i386 register resizing
  520. * removed some more routines from cga unit
  521. * fixed returnvalue handling
  522. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  523. Revision 1.8 2002/04/06 18:10:42 jonas
  524. * several powerpc-related additions and fixes
  525. Revision 1.7 2002/04/04 19:05:57 peter
  526. * removed unused units
  527. * use tlocation.size in cg.a_*loc*() routines
  528. Revision 1.6 2002/04/02 17:11:28 peter
  529. * tlocation,treference update
  530. * LOC_CONSTANT added for better constant handling
  531. * secondadd splitted in multiple routines
  532. * location_force_reg added for loading a location to a register
  533. of a specified size
  534. * secondassignment parses now first the right and then the left node
  535. (this is compatible with Kylix). This saves a lot of push/pop especially
  536. with string operations
  537. * adapted some routines to use the new cg methods
  538. Revision 1.5 2002/03/31 20:26:34 jonas
  539. + a_loadfpu_* and a_loadmm_* methods in tcg
  540. * register allocation is now handled by a class and is mostly processor
  541. independent (+rgobj.pas and i386/rgcpu.pas)
  542. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  543. * some small improvements and fixes to the optimizer
  544. * some register allocation fixes
  545. * some fpuvaroffset fixes in the unary minus node
  546. * push/popusedregisters is now called rg.save/restoreusedregisters and
  547. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  548. also better optimizable)
  549. * fixed and optimized register saving/restoring for new/dispose nodes
  550. * LOC_FPU locations now also require their "register" field to be set to
  551. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  552. - list field removed of the tnode class because it's not used currently
  553. and can cause hard-to-find bugs
  554. }