ncgflw.pas 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for nodes that influence the flow 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 ncgflw;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,nflw;
  24. type
  25. tcgwhilerepeatnode = class(twhilerepeatnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgifnode = class(tifnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgfornode = class(tfornode)
  32. procedure pass_2;override;
  33. end;
  34. tcgexitnode = class(texitnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgbreaknode = class(tbreaknode)
  38. procedure pass_2;override;
  39. end;
  40. tcgcontinuenode = class(tcontinuenode)
  41. procedure pass_2;override;
  42. end;
  43. tcggotonode = class(tgotonode)
  44. procedure pass_2;override;
  45. end;
  46. tcglabelnode = class(tlabelnode)
  47. procedure pass_2;override;
  48. end;
  49. tcgfailnode = class(tfailnode)
  50. procedure pass_2;override;
  51. end;
  52. implementation
  53. uses
  54. verbose,globals,systems,globtype,
  55. symconst,symsym,aasmbase,aasmtai,aasmcpu,types,
  56. cginfo,cgbase,pass_2,
  57. cpubase,cpuinfo,
  58. nld,ncon,
  59. ncgutil,
  60. cga,
  61. tgobj,rgobj,
  62. regvars,cgobj,cgcpu,cg64f32;
  63. {*****************************************************************************
  64. Second_While_RepeatN
  65. *****************************************************************************}
  66. procedure tcgwhilerepeatnode.pass_2;
  67. var
  68. lcont,lbreak,lloop,
  69. oldclabel,oldblabel : tasmlabel;
  70. otlabel,oflabel : tasmlabel;
  71. begin
  72. getlabel(lloop);
  73. getlabel(lcont);
  74. getlabel(lbreak);
  75. { arrange continue and breaklabels: }
  76. oldclabel:=aktcontinuelabel;
  77. oldblabel:=aktbreaklabel;
  78. load_all_regvars(exprasmlist);
  79. { handling code at the end as it is much more efficient, and makes
  80. while equal to repeat loop, only the end true/false is swapped (PFV) }
  81. if nodetype=whilen then
  82. cg.a_jmp_always(exprasmlist,lcont);
  83. { align loop target }
  84. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  85. cg.a_label(exprasmlist,lloop);
  86. aktcontinuelabel:=lcont;
  87. aktbreaklabel:=lbreak;
  88. rg.cleartempgen;
  89. if assigned(right) then
  90. secondpass(right);
  91. load_all_regvars(exprasmlist);
  92. cg.a_label(exprasmlist,lcont);
  93. otlabel:=truelabel;
  94. oflabel:=falselabel;
  95. if nodetype=whilen then
  96. begin
  97. truelabel:=lloop;
  98. falselabel:=lbreak;
  99. end
  100. { repeatn }
  101. else
  102. begin
  103. truelabel:=lbreak;
  104. falselabel:=lloop;
  105. end;
  106. rg.cleartempgen;
  107. secondpass(left);
  108. maketojumpbool(exprasmlist,left,lr_load_regvars);
  109. cg.a_label(exprasmlist,lbreak);
  110. truelabel:=otlabel;
  111. falselabel:=oflabel;
  112. aktcontinuelabel:=oldclabel;
  113. aktbreaklabel:=oldblabel;
  114. { a break/continue in a while/repeat block can't be seen outside }
  115. flowcontrol:=flowcontrol-[fc_break,fc_continue];
  116. end;
  117. {*****************************************************************************
  118. tcgIFNODE
  119. *****************************************************************************}
  120. procedure tcgifnode.pass_2;
  121. var
  122. hl,otlabel,oflabel : tasmlabel;
  123. org_regvar_loaded,
  124. then_regvar_loaded,
  125. else_regvar_loaded : regvar_booleanarray;
  126. org_list,
  127. then_list,
  128. else_list : taasmoutput;
  129. begin
  130. otlabel:=truelabel;
  131. oflabel:=falselabel;
  132. getlabel(truelabel);
  133. getlabel(falselabel);
  134. rg.cleartempgen;
  135. secondpass(left);
  136. { save regvars loaded in the beginning so that we can restore them }
  137. { when processing the else-block }
  138. if cs_regalloc in aktglobalswitches then
  139. begin
  140. org_list := exprasmlist;
  141. exprasmlist := taasmoutput.create;
  142. end;
  143. maketojumpbool(exprasmlist,left,lr_dont_load_regvars);
  144. if cs_regalloc in aktglobalswitches then
  145. org_regvar_loaded := rg.regvar_loaded;
  146. if assigned(right) then
  147. begin
  148. cg.a_label(exprasmlist,truelabel);
  149. rg.cleartempgen;
  150. secondpass(right);
  151. end;
  152. { save current asmlist (previous instructions + then-block) and }
  153. { loaded regvar state and create new clean ones }
  154. if cs_regalloc in aktglobalswitches then
  155. begin
  156. then_regvar_loaded := rg.regvar_loaded;
  157. rg.regvar_loaded := org_regvar_loaded;
  158. then_list := exprasmlist;
  159. exprasmlist := taasmoutput.create;
  160. end;
  161. if assigned(t1) then
  162. begin
  163. if assigned(right) then
  164. begin
  165. getlabel(hl);
  166. { do go back to if line !! }
  167. if not(cs_regalloc in aktglobalswitches) then
  168. aktfilepos:=exprasmList.getlasttaifilepos^
  169. else
  170. aktfilepos:=then_list.getlasttaifilepos^;
  171. cg.a_jmp_always(exprasmlist,hl);
  172. end;
  173. cg.a_label(exprasmlist,falselabel);
  174. rg.cleartempgen;
  175. secondpass(t1);
  176. { save current asmlist (previous instructions + else-block) }
  177. { and loaded regvar state and create a new clean list }
  178. if cs_regalloc in aktglobalswitches then
  179. begin
  180. else_regvar_loaded := rg.regvar_loaded;
  181. else_list := exprasmlist;
  182. exprasmlist := taasmoutput.create;
  183. end;
  184. if assigned(right) then
  185. cg.a_label(exprasmlist,hl);
  186. end
  187. else
  188. begin
  189. if cs_regalloc in aktglobalswitches then
  190. begin
  191. else_regvar_loaded := rg.regvar_loaded;
  192. else_list := exprasmlist;
  193. exprasmlist := taasmoutput.create;
  194. end;
  195. cg.a_label(exprasmlist,falselabel);
  196. end;
  197. if not(assigned(right)) then
  198. begin
  199. cg.a_label(exprasmlist,truelabel);
  200. end;
  201. if cs_regalloc in aktglobalswitches then
  202. begin
  203. { add loads of regvars at the end of the then- and else-blocks }
  204. { so that at the end of both blocks the same regvars are loaded }
  205. { no else block? }
  206. if not assigned(t1) then
  207. sync_regvars(org_list,then_list,org_regvar_loaded,
  208. then_regvar_loaded)
  209. { no then block? }
  210. else if not assigned(right) then
  211. sync_regvars(org_list,else_list,org_regvar_loaded,
  212. else_regvar_loaded)
  213. { both else and then blocks }
  214. else
  215. sync_regvars(then_list,else_list,then_regvar_loaded,
  216. else_regvar_loaded);
  217. { add all lists together }
  218. org_list.concatlist(then_list);
  219. then_list.free;
  220. org_list.concatlist(else_list);
  221. else_list.free;
  222. org_list.concatlist(exprasmlist);
  223. exprasmlist.free;
  224. exprasmlist := org_list;
  225. end;
  226. truelabel:=otlabel;
  227. falselabel:=oflabel;
  228. end;
  229. {*****************************************************************************
  230. SecondFor
  231. *****************************************************************************}
  232. procedure tcgfornode.pass_2;
  233. var
  234. l3,oldclabel,oldblabel : tasmlabel;
  235. omitfirstcomp,temptovalue : boolean;
  236. hs : byte;
  237. temp1 : treference;
  238. hop : topcg;
  239. hcond : topcmp;
  240. opsize : tcgsize;
  241. count_var_is_signed : boolean;
  242. begin
  243. oldclabel:=aktcontinuelabel;
  244. oldblabel:=aktbreaklabel;
  245. getlabel(aktcontinuelabel);
  246. getlabel(aktbreaklabel);
  247. getlabel(l3);
  248. { could we spare the first comparison ? }
  249. omitfirstcomp:=false;
  250. if right.nodetype=ordconstn then
  251. if tassignmentnode(left).right.nodetype=ordconstn then
  252. omitfirstcomp:=((nf_backward in flags) and
  253. (tordconstnode(tassignmentnode(left).right).value>=tordconstnode(right).value))
  254. or (not(nf_backward in flags) and
  255. (tordconstnode(tassignmentnode(left).right).value<=tordconstnode(right).value));
  256. { only calculate reference }
  257. rg.cleartempgen;
  258. secondpass(t2);
  259. hs := t2.resulttype.def.size;
  260. opsize := def_cgsize(t2.resulttype.def);
  261. { first set the to value
  262. because the count var can be in the expression !! }
  263. rg.cleartempgen;
  264. secondpass(right);
  265. { calculate pointer value and check if changeable and if so }
  266. { load into temporary variable }
  267. if right.nodetype<>ordconstn then
  268. begin
  269. temp1.symbol:=nil;
  270. tg.gettempofsizereference(exprasmlist,hs,temp1);
  271. temptovalue:=true;
  272. if (right.location.loc=LOC_REGISTER) or
  273. (right.location.loc=LOC_CREGISTER) then
  274. begin
  275. cg.a_load_reg_ref(exprasmlist,opsize,
  276. right.location.register,temp1);
  277. rg.ungetregister(exprasmlist,right.location.register);
  278. end
  279. else
  280. cg.g_concatcopy(exprasmlist,right.location.reference,temp1,
  281. hs,true,false);
  282. end
  283. else
  284. temptovalue:=false;
  285. { produce start assignment }
  286. rg.cleartempgen;
  287. secondpass(left);
  288. count_var_is_signed:=is_signed(t2.resulttype.def);
  289. if nf_backward in flags then
  290. if count_var_is_signed then
  291. hcond:=OC_LT
  292. else
  293. hcond:=OC_B
  294. else
  295. if count_var_is_signed then
  296. hcond:=OC_GT
  297. else
  298. hcond:=OC_A;
  299. load_all_regvars(exprasmlist);
  300. if temptovalue then
  301. begin
  302. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,
  303. temp1,t2.location,aktbreaklabel);
  304. end
  305. else
  306. begin
  307. if not(omitfirstcomp) then
  308. begin
  309. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  310. aword(tordconstnode(right).value),
  311. t2.location,aktbreaklabel);
  312. end;
  313. end;
  314. { align loop target }
  315. exprasmList.concat(Tai_align.Create(aktalignment.loopalign));
  316. cg.a_label(exprasmlist,l3);
  317. { help register must not be in instruction block }
  318. rg.cleartempgen;
  319. if assigned(t1) then
  320. begin
  321. secondpass(t1);
  322. load_all_regvars(exprasmlist);
  323. end;
  324. cg.a_label(exprasmlist,aktcontinuelabel);
  325. { makes no problems there }
  326. rg.cleartempgen;
  327. if nf_backward in flags then
  328. if count_var_is_signed then
  329. hcond:=OC_LTE
  330. else
  331. hcond:=OC_BE
  332. else
  333. if count_var_is_signed then
  334. hcond:=OC_GTE
  335. else
  336. hcond:=OC_AE;
  337. load_all_regvars(exprasmlist);
  338. { produce comparison and the corresponding }
  339. { jump }
  340. if temptovalue then
  341. begin
  342. cg.a_cmp_ref_loc_label(exprasmlist,opsize,hcond,temp1,
  343. t2.location,aktbreaklabel);
  344. end
  345. else
  346. begin
  347. cg.a_cmp_const_loc_label(exprasmlist,opsize,hcond,
  348. aword(tordconstnode(right).value),t2.location,aktbreaklabel);
  349. end;
  350. { according to count direction DEC or INC... }
  351. { must be after the test because of 0 to 255 for bytes !! }
  352. if nf_backward in flags then
  353. hop:=OP_SUB
  354. else
  355. hop:=OP_ADD;
  356. cg.a_op_const_loc(exprasmlist,hop,1,t2.location);
  357. cg.a_jmp_always(exprasmlist,l3);
  358. if temptovalue then
  359. tg.ungetiftemp(exprasmlist,temp1);
  360. { this is the break label: }
  361. cg.a_label(exprasmlist,aktbreaklabel);
  362. aktcontinuelabel:=oldclabel;
  363. aktbreaklabel:=oldblabel;
  364. { a break/continue in a for block can't be seen outside }
  365. flowcontrol:=flowcontrol-[fc_break,fc_continue];
  366. end;
  367. {*****************************************************************************
  368. SecondExitN
  369. *****************************************************************************}
  370. procedure tcgexitnode.pass_2;
  371. var
  372. {op : tasmop;
  373. s : topsize;}
  374. otlabel,oflabel : tasmlabel;
  375. cgsize : tcgsize;
  376. hreg : tregister;
  377. allocated_acc,
  378. allocated_acchigh: boolean;
  379. label
  380. do_jmp;
  381. begin
  382. { load_all_regvars(exprasmlist); }
  383. include(flowcontrol,fc_exit);
  384. if assigned(left) then
  385. if left.nodetype=assignn then
  386. begin
  387. { just do a normal assignment followed by exit }
  388. secondpass(left);
  389. cg.a_jmp_always(exprasmlist,aktexitlabel);
  390. end
  391. else
  392. begin
  393. allocated_acc := false;
  394. allocated_acchigh := false;
  395. otlabel:=truelabel;
  396. oflabel:=falselabel;
  397. getlabel(truelabel);
  398. getlabel(falselabel);
  399. secondpass(left);
  400. { the result of left is not needed anymore after this
  401. node }
  402. location_freetemp(exprasmlist,left.location);
  403. location_release(exprasmlist,left.location);
  404. case left.location.loc of
  405. LOC_FPUREGISTER :
  406. goto do_jmp;
  407. LOC_FLAGS :
  408. begin
  409. cg.a_reg_alloc(exprasmlist,accumulator);
  410. allocated_acc := true;
  411. cg.g_flags2reg(exprasmlist,left.location.resflags,accumulator);
  412. goto do_jmp;
  413. end;
  414. LOC_JUMP :
  415. begin
  416. cg.a_reg_alloc(exprasmlist,accumulator);
  417. { get an 8-bit register }
  418. hreg:=rg.makeregsize(accumulator,OS_8);
  419. allocated_acc := true;
  420. cg.a_label(exprasmlist,truelabel);
  421. cg.a_load_const_reg(exprasmlist,OS_8,1,hreg);
  422. cg.a_jmp_always(exprasmlist,aktexit2label);
  423. cg.a_label(exprasmlist,falselabel);
  424. cg.a_load_const_reg(exprasmlist,OS_8,0,hreg);
  425. goto do_jmp;
  426. end;
  427. end;
  428. case aktprocdef.rettype.def.deftype of
  429. pointerdef,
  430. procvardef :
  431. begin
  432. cg.a_reg_alloc(exprasmlist,accumulator);
  433. allocated_acc := true;
  434. cg.a_load_loc_reg(exprasmlist,left.location,accumulator);
  435. end;
  436. floatdef :
  437. begin
  438. {$ifndef i386}
  439. cg.a_reg_alloc(exprasmlist,fpuresultreg);
  440. {$endif not i386}
  441. cg.a_loadfpu_loc_reg(exprasmlist,left.location,fpuresultreg);
  442. end;
  443. else
  444. begin
  445. cgsize:=def_cgsize(aktprocdef.rettype.def);
  446. cg.a_reg_alloc(exprasmlist,accumulator);
  447. allocated_acc := true;
  448. case cgsize of
  449. OS_64,OS_S64 :
  450. begin
  451. cg.a_reg_alloc(exprasmlist,accumulatorhigh);
  452. allocated_acchigh := true;
  453. cg64.a_load64_loc_reg(exprasmlist,left.location,
  454. joinreg64(accumulator,accumulatorhigh));
  455. end
  456. else
  457. begin
  458. hreg:=rg.makeregsize(accumulator,cgsize);
  459. cg.a_load_loc_reg(exprasmlist,left.location,hreg);
  460. end;
  461. end;
  462. end;
  463. end;
  464. do_jmp:
  465. truelabel:=otlabel;
  466. falselabel:=oflabel;
  467. cg.a_jmp_always(exprasmlist,aktexit2label);
  468. if allocated_acc then
  469. cg.a_reg_dealloc(exprasmlist,accumulator);
  470. if allocated_acchigh then
  471. cg.a_reg_dealloc(exprasmlist,accumulatorhigh);
  472. {$ifndef i386}
  473. if (aktprocdef.rettype.def.deftype = floatdef) then
  474. cg.a_reg_dealloc(exprasmlist,fpuresultreg);
  475. {$endif not i386}
  476. end
  477. else
  478. cg.a_jmp_always(exprasmlist,aktexitlabel);
  479. end;
  480. {*****************************************************************************
  481. SecondBreakN
  482. *****************************************************************************}
  483. procedure tcgbreaknode.pass_2;
  484. begin
  485. include(flowcontrol,fc_break);
  486. if aktbreaklabel<>nil then
  487. begin
  488. load_all_regvars(exprasmlist);
  489. cg.a_jmp_always(exprasmlist,aktbreaklabel)
  490. end
  491. else
  492. CGMessage(cg_e_break_not_allowed);
  493. end;
  494. {*****************************************************************************
  495. SecondContinueN
  496. *****************************************************************************}
  497. procedure tcgcontinuenode.pass_2;
  498. begin
  499. include(flowcontrol,fc_continue);
  500. if aktcontinuelabel<>nil then
  501. begin
  502. load_all_regvars(exprasmlist);
  503. cg.a_jmp_always(exprasmlist,aktcontinuelabel)
  504. end
  505. else
  506. CGMessage(cg_e_continue_not_allowed);
  507. end;
  508. {*****************************************************************************
  509. SecondGoto
  510. *****************************************************************************}
  511. procedure tcggotonode.pass_2;
  512. begin
  513. load_all_regvars(exprasmlist);
  514. cg.a_jmp_always(exprasmlist,labelnr)
  515. end;
  516. {*****************************************************************************
  517. SecondLabel
  518. *****************************************************************************}
  519. procedure tcglabelnode.pass_2;
  520. begin
  521. load_all_regvars(exprasmlist);
  522. cg.a_label(exprasmlist,labelnr);
  523. rg.cleartempgen;
  524. secondpass(left);
  525. end;
  526. {*****************************************************************************
  527. SecondFail
  528. *****************************************************************************}
  529. procedure tcgfailnode.pass_2;
  530. begin
  531. cg.a_jmp_always(exprasmlist,faillabel);
  532. end;
  533. begin
  534. cwhilerepeatnode:=tcgwhilerepeatnode;
  535. cifnode:=tcgifnode;
  536. cfornode:=tcgfornode;
  537. cexitnode:=tcgexitnode;
  538. cbreaknode:=tcgbreaknode;
  539. ccontinuenode:=tcgcontinuenode;
  540. cgotonode:=tcggotonode;
  541. clabelnode:=tcglabelnode;
  542. cfailnode:=tcgfailnode;
  543. end.
  544. {
  545. $Log$
  546. Revision 1.22 2002-07-04 20:43:01 florian
  547. * first x86-64 patches
  548. Revision 1.21 2002/07/01 18:46:22 peter
  549. * internal linker
  550. * reorganized aasm layer
  551. Revision 1.20 2002/07/01 16:23:53 peter
  552. * cg64 patch
  553. * basics for currency
  554. * asnode updates for class and interface (not finished)
  555. Revision 1.19 2002/05/20 13:30:40 carl
  556. * bugfix of hdisponen (base must be set, not index)
  557. * more portability fixes
  558. Revision 1.18 2002/05/18 13:34:09 peter
  559. * readded missing revisions
  560. Revision 1.17 2002/05/16 19:46:37 carl
  561. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  562. + try to fix temp allocation (still in ifdef)
  563. + generic constructor calls
  564. + start of tassembler / tmodulebase class cleanup
  565. Revision 1.15 2002/05/13 19:54:37 peter
  566. * removed n386ld and n386util units
  567. * maybe_save/maybe_restore added instead of the old maybe_push
  568. Revision 1.14 2002/05/12 16:53:07 peter
  569. * moved entry and exitcode to ncgutil and cgobj
  570. * foreach gets extra argument for passing local data to the
  571. iterator function
  572. * -CR checks also class typecasts at runtime by changing them
  573. into as
  574. * fixed compiler to cycle with the -CR option
  575. * fixed stabs with elf writer, finally the global variables can
  576. be watched
  577. * removed a lot of routines from cga unit and replaced them by
  578. calls to cgobj
  579. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  580. u32bit then the other is typecasted also to u32bit without giving
  581. a rangecheck warning/error.
  582. * fixed pascal calling method with reversing also the high tree in
  583. the parast, detected by tcalcst3 test
  584. Revision 1.13 2002/04/21 15:24:38 carl
  585. + a_jmp_cond -> a_jmp_always (a_jmp_cond is NOT portable)
  586. + changeregsize -> rg.makeregsize
  587. Revision 1.12 2002/04/15 19:44:19 peter
  588. * fixed stackcheck that would be called recursively when a stack
  589. error was found
  590. * generic changeregsize(reg,size) for i386 register resizing
  591. * removed some more routines from cga unit
  592. * fixed returnvalue handling
  593. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  594. Revision 1.11 2002/04/04 19:05:57 peter
  595. * removed unused units
  596. * use tlocation.size in cg.a_*loc*() routines
  597. Revision 1.10 2002/04/02 17:11:28 peter
  598. * tlocation,treference update
  599. * LOC_CONSTANT added for better constant handling
  600. * secondadd splitted in multiple routines
  601. * location_force_reg added for loading a location to a register
  602. of a specified size
  603. * secondassignment parses now first the right and then the left node
  604. (this is compatible with Kylix). This saves a lot of push/pop especially
  605. with string operations
  606. * adapted some routines to use the new cg methods
  607. Revision 1.9 2002/03/31 20:26:34 jonas
  608. + a_loadfpu_* and a_loadmm_* methods in tcg
  609. * register allocation is now handled by a class and is mostly processor
  610. independent (+rgobj.pas and i386/rgcpu.pas)
  611. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  612. * some small improvements and fixes to the optimizer
  613. * some register allocation fixes
  614. * some fpuvaroffset fixes in the unary minus node
  615. * push/popusedregisters is now called rg.save/restoreusedregisters and
  616. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  617. also better optimizable)
  618. * fixed and optimized register saving/restoring for new/dispose nodes
  619. * LOC_FPU locations now also require their "register" field to be set to
  620. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  621. - list field removed of the tnode class because it's not used currently
  622. and can cause hard-to-find bugs
  623. Revision 1.8 2002/03/04 19:10:11 peter
  624. * removed compiler warnings
  625. }