n386mem.pas 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate i386 assembler for in memory related nodes
  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 n386mem;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nmem,ncgmem;
  23. type
  24. ti386addrnode = class(tcgaddrnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386derefnode = class(tcgderefnode)
  28. procedure pass_2;override;
  29. end;
  30. ti386vecnode = class(tcgvecnode)
  31. procedure pass_2;override;
  32. end;
  33. implementation
  34. uses
  35. {$ifdef delphi}
  36. sysutils,
  37. {$endif}
  38. globtype,systems,
  39. cutils,verbose,globals,
  40. symconst,symtype,symdef,symsym,symtable,defbase,paramgr,
  41. aasmbase,aasmtai,aasmcpu,
  42. cginfo,cgbase,pass_2,
  43. pass_1,nld,ncon,nadd,
  44. cpubase,
  45. cgobj,cga,tgobj,rgobj,ncgutil;
  46. {*****************************************************************************
  47. TI386ADDRNODE
  48. *****************************************************************************}
  49. procedure ti386addrnode.pass_2;
  50. begin
  51. inherited pass_2;
  52. { for use of other segments }
  53. if left.location.reference.segment<>R_NO then
  54. location.segment:=left.location.reference.segment;
  55. end;
  56. {*****************************************************************************
  57. TI386DEREFNODE
  58. *****************************************************************************}
  59. procedure ti386derefnode.pass_2;
  60. var
  61. oldglobalswitches : tglobalswitches;
  62. begin
  63. oldglobalswitches:=aktglobalswitches;
  64. exclude(aktglobalswitches,cs_checkpointer);
  65. inherited pass_2;
  66. aktglobalswitches:=oldglobalswitches;
  67. if tpointerdef(left.resulttype.def).is_far then
  68. location.reference.segment:=R_FS;
  69. if not tpointerdef(left.resulttype.def).is_far and
  70. (cs_gdb_heaptrc in aktglobalswitches) and
  71. (cs_checkpointer in aktglobalswitches) then
  72. begin
  73. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  74. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  75. end;
  76. end;
  77. {*****************************************************************************
  78. TI386VECNODE
  79. *****************************************************************************}
  80. procedure ti386vecnode.pass_2;
  81. procedure calc_emit_mul;
  82. var
  83. l1,l2 : longint;
  84. begin
  85. l1:=get_mul_size;
  86. case l1 of
  87. 1,2,4,8 : location.reference.scalefactor:=l1;
  88. else
  89. begin
  90. if ispowerof2(l1,l2) then
  91. emit_const_reg(A_SHL,S_L,l2,right.location.register)
  92. else
  93. emit_const_reg(A_IMUL,S_L,l1,right.location.register);
  94. end;
  95. end;
  96. end;
  97. var
  98. extraoffset : longint;
  99. { rl stores the resulttype.def of the left node, this is necessary }
  100. { to detect if it is an ansistring }
  101. { because in constant nodes which constant index }
  102. { the left tree is removed }
  103. t : tnode;
  104. href : treference;
  105. srsym : tsym;
  106. pushed : tpushedsaved;
  107. hightree : tnode;
  108. isjump : boolean;
  109. otl,ofl : tasmlabel;
  110. newsize : tcgsize;
  111. pushedregs : tmaybesave;
  112. begin
  113. newsize:=def_cgsize(resulttype.def);
  114. location_reset(location,LOC_REFERENCE,newsize);
  115. secondpass(left);
  116. { we load the array reference to location }
  117. { an ansistring needs to be dereferenced }
  118. if is_ansistring(left.resulttype.def) or
  119. is_widestring(left.resulttype.def) then
  120. begin
  121. if nf_callunique in flags then
  122. begin
  123. if left.location.loc<>LOC_REFERENCE then
  124. begin
  125. CGMessage(cg_e_illegal_expression);
  126. exit;
  127. end;
  128. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  129. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1));
  130. rg.saveregvars(exprasmlist,all_registers);
  131. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE');
  132. cg.g_maybe_loadself(exprasmlist);
  133. rg.restoreusedregisters(exprasmlist,pushed);
  134. end;
  135. case left.location.loc of
  136. LOC_REGISTER,
  137. LOC_CREGISTER :
  138. location.reference.base:=left.location.register;
  139. LOC_CREFERENCE,
  140. LOC_REFERENCE :
  141. begin
  142. location_release(exprasmlist,left.location);
  143. location.reference.base:=rg.getregisterint(exprasmlist);
  144. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.reference.base);
  145. end;
  146. else
  147. internalerror(2002032218);
  148. end;
  149. { check for a zero length string,
  150. we can use the ansistring routine here }
  151. if (cs_check_range in aktlocalswitches) then
  152. begin
  153. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  154. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  155. rg.saveregvars(exprasmlist,all_registers);
  156. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  157. cg.g_maybe_loadself(exprasmlist);
  158. rg.restoreusedregisters(exprasmlist,pushed);
  159. end;
  160. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  161. if is_ansistring(left.resulttype.def) then
  162. dec(location.reference.offset)
  163. else
  164. dec(location.reference.offset,2);
  165. { we've also to keep left up-to-date, because it is used }
  166. { if a constant array index occurs, subject to change (FK) }
  167. location_copy(left.location,location);
  168. end
  169. else if is_dynamic_array(left.resulttype.def) then
  170. { ... also a dynamic string }
  171. begin
  172. case left.location.loc of
  173. LOC_REGISTER,
  174. LOC_CREGISTER :
  175. location.reference.base:=left.location.register;
  176. LOC_REFERENCE,
  177. LOC_CREFERENCE :
  178. begin
  179. location_release(exprasmlist,left.location);
  180. location.reference.base:=rg.getregisterint(exprasmlist);
  181. emit_ref_reg(A_MOV,S_L,
  182. left.location.reference,location.reference.base);
  183. end;
  184. else
  185. internalerror(2002032219);
  186. end;
  187. {$warning FIXME}
  188. { check for a zero length string,
  189. we can use the ansistring routine here }
  190. if (cs_check_range in aktlocalswitches) then
  191. begin
  192. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  193. emit_reg(A_PUSH,S_L,location.reference.base);
  194. rg.saveregvars(exprasmlist,all_registers);
  195. cg.a_call_name(exprasmlist,'FPC_ANSISTR_CHECKZERO');
  196. cg.g_maybe_loadself(exprasmlist);
  197. rg.restoreusedregisters(exprasmlist,pushed);
  198. end;
  199. { we've also to keep left up-to-date, because it is used }
  200. { if a constant array index occurs, subject to change (FK) }
  201. location_copy(left.location,location);
  202. end
  203. else
  204. location_copy(location,left.location);
  205. { offset can only differ from 0 if arraydef }
  206. if (left.resulttype.def.deftype=arraydef) and
  207. not(is_dynamic_array(left.resulttype.def)) then
  208. dec(location.reference.offset,
  209. get_mul_size*tarraydef(left.resulttype.def).lowrange);
  210. if right.nodetype=ordconstn then
  211. begin
  212. { offset can only differ from 0 if arraydef }
  213. if (left.resulttype.def.deftype=arraydef) then
  214. begin
  215. if not(is_open_array(left.resulttype.def)) and
  216. not(is_array_of_const(left.resulttype.def)) and
  217. not(is_dynamic_array(left.resulttype.def)) then
  218. begin
  219. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  220. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  221. begin
  222. if (cs_check_range in aktlocalswitches) then
  223. CGMessage(parser_e_range_check_error)
  224. else
  225. CGMessage(parser_w_range_check_error);
  226. end;
  227. dec(left.location.reference.offset,
  228. get_mul_size*tarraydef(left.resulttype.def).lowrange);
  229. end
  230. else
  231. begin
  232. { range checking for open and dynamic arrays !!!! }
  233. {$warning FIXME}
  234. {!!!!!!!!!!!!!!!!!}
  235. end;
  236. end
  237. else if (left.resulttype.def.deftype=stringdef) then
  238. begin
  239. if (tordconstnode(right).value=0) and
  240. not(is_shortstring(left.resulttype.def)) then
  241. CGMessage(cg_e_can_access_element_zero);
  242. if (cs_check_range in aktlocalswitches) then
  243. begin
  244. case tstringdef(left.resulttype.def).string_typ of
  245. { it's the same for ansi- and wide strings }
  246. st_widestring,
  247. st_ansistring:
  248. begin
  249. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  250. cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paramanager.getintparaloc(2));
  251. href:=location.reference;
  252. dec(href.offset,7);
  253. cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
  254. rg.saveregvars(exprasmlist,all_registers);
  255. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  256. rg.restoreusedregisters(exprasmlist,pushed);
  257. cg.g_maybe_loadself(exprasmlist);
  258. end;
  259. st_shortstring:
  260. begin
  261. {!!!!!!!!!!!!!!!!!}
  262. end;
  263. st_longstring:
  264. begin
  265. {!!!!!!!!!!!!!!!!!}
  266. end;
  267. end;
  268. end;
  269. end;
  270. inc(left.location.reference.offset,
  271. get_mul_size*tordconstnode(right).value);
  272. if nf_memseg in flags then
  273. left.location.reference.segment:=R_FS;
  274. location_copy(location,left.location);
  275. end
  276. else
  277. { not nodetype=ordconstn }
  278. begin
  279. if (cs_regalloc in aktglobalswitches) and
  280. { if we do range checking, we don't }
  281. { need that fancy code (it would be }
  282. { buggy) }
  283. not(cs_check_range in aktlocalswitches) and
  284. (left.resulttype.def.deftype=arraydef) then
  285. begin
  286. extraoffset:=0;
  287. if (right.nodetype=addn) then
  288. begin
  289. if taddnode(right).right.nodetype=ordconstn then
  290. begin
  291. extraoffset:=tordconstnode(taddnode(right).right).value;
  292. t:=taddnode(right).left;
  293. { First pass processed this with the assumption }
  294. { that there was an add node which may require an }
  295. { extra register. Fake it or die with IE10 (JM) }
  296. t.registers32 := taddnode(right).registers32;
  297. taddnode(right).left:=nil;
  298. right.free;
  299. right:=t;
  300. end
  301. else if taddnode(right).left.nodetype=ordconstn then
  302. begin
  303. extraoffset:=tordconstnode(taddnode(right).left).value;
  304. t:=taddnode(right).right;
  305. t.registers32 := right.registers32;
  306. taddnode(right).right:=nil;
  307. right.free;
  308. right:=t;
  309. end;
  310. end
  311. else if (right.nodetype=subn) then
  312. begin
  313. if taddnode(right).right.nodetype=ordconstn then
  314. begin
  315. { this was "extraoffset:=right.right.value;" Looks a bit like
  316. copy-paste bug :) (JM) }
  317. extraoffset:=-tordconstnode(taddnode(right).right).value;
  318. t:=taddnode(right).left;
  319. t.registers32 := right.registers32;
  320. taddnode(right).left:=nil;
  321. right.free;
  322. right:=t;
  323. end
  324. { You also have to negate right.right in this case! I can't add an
  325. unaryminusn without causing a crash, so I've disabled it (JM)
  326. else if right.left.nodetype=ordconstn then
  327. begin
  328. extraoffset:=right.left.value;
  329. t:=right.right;
  330. t^.registers32 := right.registers32;
  331. putnode(right);
  332. putnode(right.left);
  333. right:=t;
  334. end;}
  335. end;
  336. inc(location.reference.offset,
  337. get_mul_size*extraoffset);
  338. end;
  339. { calculate from left to right }
  340. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  341. CGMessage(cg_e_illegal_expression);
  342. isjump:=(right.location.loc=LOC_JUMP);
  343. if isjump then
  344. begin
  345. otl:=truelabel;
  346. objectlibrary.getlabel(truelabel);
  347. ofl:=falselabel;
  348. objectlibrary.getlabel(falselabel);
  349. end;
  350. maybe_save(exprasmlist,right.registers32,location,pushedregs);
  351. secondpass(right);
  352. maybe_restore(exprasmlist,location,pushedregs);
  353. { here we change the location of right
  354. and the update was forgotten so it
  355. led to wrong code in emitrangecheck later PM
  356. so make range check before }
  357. if cs_check_range in aktlocalswitches then
  358. begin
  359. if left.resulttype.def.deftype=arraydef then
  360. begin
  361. if is_open_array(left.resulttype.def) or
  362. is_array_of_const(left.resulttype.def) then
  363. begin
  364. tarraydef(left.resulttype.def).genrangecheck;
  365. srsym:=searchsymonlyin(tloadnode(left).symtable,
  366. 'high'+tvarsym(tloadnode(left).symtableentry).name);
  367. hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
  368. firstpass(hightree);
  369. secondpass(hightree);
  370. location_release(exprasmlist,hightree.location);
  371. reference_reset_symbol(href,objectlibrary.newasmsymbol(tarraydef(left.resulttype.def).getrangecheckstring),4);
  372. cg.a_load_loc_ref(exprasmlist,hightree.location,href);
  373. hightree.free;
  374. hightree:=nil;
  375. end;
  376. cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
  377. end;
  378. end;
  379. location_force_reg(exprasmlist,right.location,OS_32,false);
  380. if isjump then
  381. begin
  382. truelabel:=otl;
  383. falselabel:=ofl;
  384. end;
  385. { produce possible range check code: }
  386. if cs_check_range in aktlocalswitches then
  387. begin
  388. if left.resulttype.def.deftype=arraydef then
  389. begin
  390. { done defore (PM) }
  391. end
  392. else if (left.resulttype.def.deftype=stringdef) then
  393. begin
  394. case tstringdef(left.resulttype.def).string_typ of
  395. { it's the same for ansi- and wide strings }
  396. st_widestring,
  397. st_ansistring:
  398. begin
  399. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  400. cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paramanager.getintparaloc(1));
  401. href:=location.reference;
  402. dec(href.offset,7);
  403. cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
  404. rg.saveregvars(exprasmlist,all_registers);
  405. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  406. rg.restoreusedregisters(exprasmlist,pushed);
  407. cg.g_maybe_loadself(exprasmlist);
  408. end;
  409. st_shortstring:
  410. begin
  411. {!!!!!!!!!!!!!!!!!}
  412. end;
  413. st_longstring:
  414. begin
  415. {!!!!!!!!!!!!!!!!!}
  416. end;
  417. end;
  418. end;
  419. end;
  420. if location.reference.index=R_NO then
  421. begin
  422. location.reference.index:=right.location.register;
  423. calc_emit_mul;
  424. end
  425. else
  426. begin
  427. if location.reference.base=R_NO then
  428. begin
  429. case location.reference.scalefactor of
  430. 2 : emit_const_reg(A_SHL,S_L,1,location.reference.index);
  431. 4 : emit_const_reg(A_SHL,S_L,2,location.reference.index);
  432. 8 : emit_const_reg(A_SHL,S_L,3,location.reference.index);
  433. end;
  434. calc_emit_mul;
  435. location.reference.base:=location.reference.index;
  436. location.reference.index:=right.location.register;
  437. end
  438. else
  439. begin
  440. emit_ref_reg(A_LEA,S_L,location.reference,location.reference.index);
  441. rg.ungetregisterint(exprasmlist,location.reference.base);
  442. { the symbol offset is loaded, }
  443. { so release the symbol name and set symbol }
  444. { to nil }
  445. location.reference.symbol:=nil;
  446. location.reference.offset:=0;
  447. calc_emit_mul;
  448. location.reference.base:=location.reference.index;
  449. location.reference.index:=right.location.register;
  450. end;
  451. end;
  452. if nf_memseg in flags then
  453. location.reference.segment:=R_FS;
  454. end;
  455. location.size:=newsize;
  456. end;
  457. begin
  458. caddrnode:=ti386addrnode;
  459. cderefnode:=ti386derefnode;
  460. cvecnode:=ti386vecnode;
  461. end.
  462. {
  463. $Log$
  464. Revision 1.41 2002-08-11 14:32:30 peter
  465. * renamed current_library to objectlibrary
  466. Revision 1.40 2002/08/11 13:24:17 peter
  467. * saving of asmsymbols in ppu supported
  468. * asmsymbollist global is removed and moved into a new class
  469. tasmlibrarydata that will hold the info of a .a file which
  470. corresponds with a single module. Added librarydata to tmodule
  471. to keep the library info stored for the module. In the future the
  472. objectfiles will also be stored to the tasmlibrarydata class
  473. * all getlabel/newasmsymbol and friends are moved to the new class
  474. Revision 1.39 2002/07/28 21:34:31 florian
  475. * more powerpc fixes
  476. + dummy tcgvecnode
  477. Revision 1.38 2002/07/20 11:58:04 florian
  478. * types.pas renamed to defbase.pas because D6 contains a types
  479. unit so this would conflicts if D6 programms are compiled
  480. + Willamette/SSE2 instructions to assembler added
  481. Revision 1.37 2002/07/11 14:41:33 florian
  482. * start of the new generic parameter handling
  483. Revision 1.36 2002/07/07 09:52:34 florian
  484. * powerpc target fixed, very simple units can be compiled
  485. * some basic stuff for better callparanode handling, far from being finished
  486. Revision 1.35 2002/07/01 18:46:33 peter
  487. * internal linker
  488. * reorganized aasm layer
  489. Revision 1.34 2002/06/24 12:43:01 jonas
  490. * fixed errors found with new -CR code from Peter when cycling with -O2p3r
  491. Revision 1.33 2002/05/18 13:34:25 peter
  492. * readded missing revisions
  493. Revision 1.32 2002/05/16 19:46:51 carl
  494. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  495. + try to fix temp allocation (still in ifdef)
  496. + generic constructor calls
  497. + start of tassembler / tmodulebase class cleanup
  498. Revision 1.30 2002/05/13 19:54:38 peter
  499. * removed n386ld and n386util units
  500. * maybe_save/maybe_restore added instead of the old maybe_push
  501. Revision 1.29 2002/05/12 16:53:17 peter
  502. * moved entry and exitcode to ncgutil and cgobj
  503. * foreach gets extra argument for passing local data to the
  504. iterator function
  505. * -CR checks also class typecasts at runtime by changing them
  506. into as
  507. * fixed compiler to cycle with the -CR option
  508. * fixed stabs with elf writer, finally the global variables can
  509. be watched
  510. * removed a lot of routines from cga unit and replaced them by
  511. calls to cgobj
  512. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  513. u32bit then the other is typecasted also to u32bit without giving
  514. a rangecheck warning/error.
  515. * fixed pascal calling method with reversing also the high tree in
  516. the parast, detected by tcalcst3 test
  517. Revision 1.28 2002/04/21 19:02:07 peter
  518. * removed newn and disposen nodes, the code is now directly
  519. inlined from pexpr
  520. * -an option that will write the secondpass nodes to the .s file, this
  521. requires EXTDEBUG define to actually write the info
  522. * fixed various internal errors and crashes due recent code changes
  523. Revision 1.27 2002/04/20 21:37:07 carl
  524. + generic FPC_CHECKPOINTER
  525. + first parameter offset in stack now portable
  526. * rename some constants
  527. + move some cpu stuff to other units
  528. - remove unused constents
  529. * fix stacksize for some targets
  530. * fix generic size problems which depend now on EXTEND_SIZE constant
  531. * removing frame pointer in routines is only available for : i386,m68k and vis targets
  532. Revision 1.26 2002/04/19 15:39:35 peter
  533. * removed some more routines from cga
  534. * moved location_force_reg/mem to ncgutil
  535. * moved arrayconstructnode secondpass to ncgld
  536. Revision 1.25 2002/04/15 19:12:09 carl
  537. + target_info.size_of_pointer -> pointer_size
  538. + some cleanup of unused types/variables
  539. * move several constants from cpubase to their specific units
  540. (where they are used)
  541. + att_Reg2str -> gas_reg2str
  542. + int_reg2str -> std_reg2str
  543. Revision 1.24 2002/04/04 19:06:12 peter
  544. * removed unused units
  545. * use tlocation.size in cg.a_*loc*() routines
  546. Revision 1.23 2002/04/02 17:11:36 peter
  547. * tlocation,treference update
  548. * LOC_CONSTANT added for better constant handling
  549. * secondadd splitted in multiple routines
  550. * location_force_reg added for loading a location to a register
  551. of a specified size
  552. * secondassignment parses now first the right and then the left node
  553. (this is compatible with Kylix). This saves a lot of push/pop especially
  554. with string operations
  555. * adapted some routines to use the new cg methods
  556. Revision 1.22 2002/04/01 09:44:04 jonas
  557. * better fix for new/dispose bug with init/final data
  558. Revision 1.21 2002/03/31 20:26:39 jonas
  559. + a_loadfpu_* and a_loadmm_* methods in tcg
  560. * register allocation is now handled by a class and is mostly processor
  561. independent (+rgobj.pas and i386/rgcpu.pas)
  562. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  563. * some small improvements and fixes to the optimizer
  564. * some register allocation fixes
  565. * some fpuvaroffset fixes in the unary minus node
  566. * push/popusedregisters is now called rg.save/restoreusedregisters and
  567. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  568. also better optimizable)
  569. * fixed and optimized register saving/restoring for new/dispose nodes
  570. * LOC_FPU locations now also require their "register" field to be set to
  571. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  572. - list field removed of the tnode class because it's not used currently
  573. and can cause hard-to-find bugs
  574. Revision 1.20 2002/03/04 19:10:14 peter
  575. * removed compiler warnings
  576. }