n386mat.pas 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate i386 assembler for math 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 n386mat;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nmat,ncgmat,nx86mat;
  23. type
  24. ti386moddivnode = class(tmoddivnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386shlshrnode = class(tshlshrnode)
  28. procedure pass_2;override;
  29. { everything will be handled in pass_2 }
  30. function first_shlshr64bitint: tnode; override;
  31. end;
  32. ti386unaryminusnode = class(tx86unaryminusnode)
  33. end;
  34. ti386notnode = class(tcgnotnode)
  35. procedure second_boolean;override;
  36. {$ifdef SUPPORT_MMX}
  37. procedure second_mmx;override;
  38. {$endif SUPPORT_MMX}
  39. end;
  40. implementation
  41. uses
  42. globtype,systems,
  43. cutils,verbose,globals,
  44. symconst,symdef,aasmbase,aasmtai,defutil,
  45. cgbase,pass_1,pass_2,
  46. ncon,
  47. cpubase,cpuinfo,
  48. cga,ncgutil,cgobj;
  49. {*****************************************************************************
  50. TI386MODDIVNODE
  51. *****************************************************************************}
  52. procedure ti386moddivnode.pass_2;
  53. var hreg1,hreg2:Tregister;
  54. power:longint;
  55. hl:Tasmlabel;
  56. op:Tasmop;
  57. begin
  58. secondpass(left);
  59. if codegenerror then
  60. exit;
  61. secondpass(right);
  62. if codegenerror then
  63. exit;
  64. if is_64bitint(resulttype.def) then
  65. { should be handled in pass_1 (JM) }
  66. internalerror(200109052);
  67. { put numerator in register }
  68. location_reset(location,LOC_REGISTER,OS_INT);
  69. location_force_reg(exprasmlist,left.location,OS_INT,false);
  70. hreg1:=left.location.register;
  71. if (nodetype=divn) and (right.nodetype=ordconstn) and
  72. ispowerof2(tordconstnode(right).value,power) then
  73. begin
  74. { for signed numbers, the numerator must be adjusted before the
  75. shift instruction, but not wih unsigned numbers! Otherwise,
  76. "Cardinal($ffffffff) div 16" overflows! (JM) }
  77. if is_signed(left.resulttype.def) Then
  78. begin
  79. if (aktOptProcessor <> class386) and
  80. not(cs_littlesize in aktglobalswitches) then
  81. { use a sequence without jumps, saw this in
  82. comp.compilers (JM) }
  83. begin
  84. { no jumps, but more operations }
  85. hreg2:=cg.getintregister(exprasmlist,OS_INT);
  86. emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
  87. {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
  88. emit_const_reg(A_SAR,S_L,31,hreg2);
  89. {If signed, hreg2=right value-1, otherwise 0.}
  90. emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
  91. { add to the left value }
  92. emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
  93. { release EDX if we used it }
  94. cg.ungetregister(exprasmlist,hreg2);
  95. { do the shift }
  96. emit_const_reg(A_SAR,S_L,power,hreg1);
  97. end
  98. else
  99. begin
  100. { a jump, but less operations }
  101. emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
  102. objectlibrary.getlabel(hl);
  103. cg.a_jmp_flags(exprasmlist,F_NS,hl);
  104. if power=1 then
  105. emit_reg(A_INC,S_L,hreg1)
  106. else
  107. emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
  108. cg.a_label(exprasmlist,hl);
  109. emit_const_reg(A_SAR,S_L,power,hreg1);
  110. end
  111. end
  112. else
  113. emit_const_reg(A_SHR,S_L,power,hreg1);
  114. location.register:=hreg1;
  115. end
  116. else
  117. begin
  118. {Bring denominator to a register.}
  119. cg.ungetregister(exprasmlist,hreg1);
  120. cg.getexplicitregister(exprasmlist,NR_EAX);
  121. emit_reg_reg(A_MOV,S_L,hreg1,NR_EAX);
  122. cg.getexplicitregister(exprasmlist,NR_EDX);
  123. {Sign extension depends on the left type.}
  124. if torddef(left.resulttype.def).typ=u32bit then
  125. emit_reg_reg(A_XOR,S_L,NR_EDX,NR_EDX)
  126. else
  127. emit_none(A_CDQ,S_NO);
  128. {Division depends on the right type.}
  129. if Torddef(right.resulttype.def).typ=u32bit then
  130. op:=A_DIV
  131. else
  132. op:=A_IDIV;
  133. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  134. emit_ref(op,S_L,right.location.reference)
  135. else if right.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  136. emit_reg(op,S_L,right.location.register)
  137. else
  138. begin
  139. hreg1:=cg.getintregister(exprasmlist,right.location.size);
  140. cg.a_load_loc_reg(exprasmlist,OS_32,right.location,hreg1);
  141. cg.ungetregister(exprasmlist,hreg1);
  142. emit_reg(op,S_L,hreg1);
  143. end;
  144. location_release(exprasmlist,right.location);
  145. {Copy the result into a new register. Release EAX & EDX.}
  146. if nodetype=divn then
  147. begin
  148. cg.ungetregister(exprasmlist,NR_EDX);
  149. cg.ungetregister(exprasmlist,NR_EAX);
  150. location.register:=cg.getintregister(exprasmlist,OS_INT);
  151. emit_reg_reg(A_MOV,S_L,NR_EAX,location.register);
  152. end
  153. else
  154. begin
  155. cg.ungetregister(exprasmlist,NR_EAX);
  156. cg.ungetregister(exprasmlist,NR_EDX);
  157. location.register:=cg.getintregister(exprasmlist,OS_INT);
  158. emit_reg_reg(A_MOV,S_L,NR_EDX,location.register);
  159. end;
  160. end;
  161. end;
  162. {*****************************************************************************
  163. TI386SHLRSHRNODE
  164. *****************************************************************************}
  165. function ti386shlshrnode.first_shlshr64bitint: tnode;
  166. begin
  167. result := nil;
  168. end;
  169. procedure ti386shlshrnode.pass_2;
  170. var hregisterhigh,hregisterlow:Tregister;
  171. op:Tasmop;
  172. l1,l2,l3:Tasmlabel;
  173. begin
  174. secondpass(left);
  175. secondpass(right);
  176. { determine operator }
  177. if nodetype=shln then
  178. op:=A_SHL
  179. else
  180. op:=A_SHR;
  181. if is_64bitint(left.resulttype.def) then
  182. begin
  183. location_reset(location,LOC_REGISTER,OS_64);
  184. { load left operator in a register }
  185. location_force_reg(exprasmlist,left.location,OS_64,false);
  186. hregisterhigh:=left.location.registerhigh;
  187. hregisterlow:=left.location.registerlow;
  188. { shifting by a constant directly coded: }
  189. if (right.nodetype=ordconstn) then
  190. begin
  191. { shrd/shl works only for values <=31 !! }
  192. if Tordconstnode(right).value>63 then
  193. begin
  194. cg.a_load_const_reg(exprasmlist,OS_32,0,hregisterhigh);
  195. cg.a_load_const_reg(exprasmlist,OS_32,0,hregisterlow);
  196. location.registerlow:=hregisterlow;
  197. location.registerhigh:=hregisterhigh;
  198. end
  199. else if Tordconstnode(right).value>31 then
  200. begin
  201. if nodetype=shln then
  202. begin
  203. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  204. if ((tordconstnode(right).value and 31) <> 0) then
  205. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  206. hregisterlow);
  207. end
  208. else
  209. begin
  210. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  211. if ((tordconstnode(right).value and 31) <> 0) then
  212. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  213. hregisterhigh);
  214. end;
  215. location.registerhigh:=hregisterlow;
  216. location.registerlow:=hregisterhigh;
  217. end
  218. else
  219. begin
  220. if nodetype=shln then
  221. begin
  222. emit_const_reg_reg(A_SHLD,S_L,tordconstnode(right).value and 31,
  223. hregisterlow,hregisterhigh);
  224. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  225. hregisterlow);
  226. end
  227. else
  228. begin
  229. emit_const_reg_reg(A_SHRD,S_L,tordconstnode(right).value and 31,
  230. hregisterhigh,hregisterlow);
  231. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  232. hregisterhigh);
  233. end;
  234. location.registerlow:=hregisterlow;
  235. location.registerhigh:=hregisterhigh;
  236. end;
  237. end
  238. else
  239. begin
  240. { load right operators in a register }
  241. cg.getexplicitregister(exprasmlist,NR_ECX);
  242. cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
  243. if right.location.loc<>LOC_CREGISTER then
  244. location_release(exprasmlist,right.location);
  245. { left operator is already in a register }
  246. { hence are both in a register }
  247. { is it in the case ECX ? }
  248. { the damned shift instructions work only til a count of 32 }
  249. { so we've to do some tricks here }
  250. objectlibrary.getlabel(l1);
  251. objectlibrary.getlabel(l2);
  252. objectlibrary.getlabel(l3);
  253. emit_const_reg(A_CMP,S_L,64,NR_ECX);
  254. cg.a_jmp_flags(exprasmlist,F_L,l1);
  255. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  256. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  257. cg.a_jmp_always(exprasmlist,l3);
  258. cg.a_label(exprasmlist,l1);
  259. emit_const_reg(A_CMP,S_L,32,NR_ECX);
  260. cg.a_jmp_flags(exprasmlist,F_L,l2);
  261. emit_const_reg(A_SUB,S_L,32,NR_ECX);
  262. if nodetype=shln then
  263. begin
  264. emit_reg_reg(A_SHL,S_L,NR_CL,hregisterlow);
  265. emit_reg_reg(A_MOV,S_L,hregisterlow,hregisterhigh);
  266. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  267. cg.a_jmp_always(exprasmlist,l3);
  268. cg.a_label(exprasmlist,l2);
  269. emit_reg_reg_reg(A_SHLD,S_L,NR_CL,hregisterlow,hregisterhigh);
  270. emit_reg_reg(A_SHL,S_L,NR_CL,hregisterlow);
  271. end
  272. else
  273. begin
  274. emit_reg_reg(A_SHR,S_L,NR_CL,hregisterhigh);
  275. emit_reg_reg(A_MOV,S_L,hregisterhigh,hregisterlow);
  276. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  277. cg.a_jmp_always(exprasmlist,l3);
  278. cg.a_label(exprasmlist,l2);
  279. emit_reg_reg_reg(A_SHRD,S_L,NR_CL,hregisterhigh,hregisterlow);
  280. emit_reg_reg(A_SHR,S_L,NR_CL,hregisterhigh);
  281. end;
  282. cg.a_label(exprasmlist,l3);
  283. cg.ungetregister(exprasmlist,NR_ECX);
  284. location.registerlow:=hregisterlow;
  285. location.registerhigh:=hregisterhigh;
  286. end;
  287. end
  288. else
  289. begin
  290. { load left operators in a register }
  291. location_copy(location,left.location);
  292. location_force_reg(exprasmlist,location,OS_INT,false);
  293. { shifting by a constant directly coded: }
  294. if (right.nodetype=ordconstn) then
  295. { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
  296. emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
  297. else
  298. begin
  299. { load right operators in a ECX }
  300. if right.location.loc<>LOC_CREGISTER then
  301. location_release(exprasmlist,right.location);
  302. cg.getexplicitregister(exprasmlist,NR_ECX);
  303. cg.a_load_loc_reg(exprasmlist,OS_32,right.location,NR_ECX);
  304. { right operand is in ECX }
  305. cg.ungetregister(exprasmlist,NR_ECX);
  306. emit_reg_reg(op,S_L,NR_CL,location.register);
  307. end;
  308. end;
  309. end;
  310. {*****************************************************************************
  311. TI386NOTNODE
  312. *****************************************************************************}
  313. procedure ti386notnode.second_boolean;
  314. var
  315. hl : tasmlabel;
  316. opsize : topsize;
  317. begin
  318. opsize:=def_opsize(resulttype.def);
  319. if left.expectloc=LOC_JUMP then
  320. begin
  321. location_reset(location,LOC_JUMP,OS_NO);
  322. hl:=truelabel;
  323. truelabel:=falselabel;
  324. falselabel:=hl;
  325. secondpass(left);
  326. maketojumpbool(exprasmlist,left,lr_load_regvars);
  327. hl:=truelabel;
  328. truelabel:=falselabel;
  329. falselabel:=hl;
  330. end
  331. else
  332. begin
  333. { the second pass could change the location of left }
  334. { if it is a register variable, so we've to do }
  335. { this before the case statement }
  336. secondpass(left);
  337. case left.expectloc of
  338. LOC_FLAGS :
  339. begin
  340. location_release(exprasmlist,left.location);
  341. location_reset(location,LOC_FLAGS,OS_NO);
  342. location.resflags:=left.location.resflags;
  343. inverse_flags(location.resflags);
  344. end;
  345. LOC_CONSTANT,
  346. LOC_REGISTER,
  347. LOC_CREGISTER,
  348. LOC_REFERENCE,
  349. LOC_CREFERENCE :
  350. begin
  351. location_force_reg(exprasmlist,left.location,def_cgsize(resulttype.def),true);
  352. location_release(exprasmlist,left.location);
  353. emit_reg_reg(A_TEST,opsize,left.location.register,left.location.register);
  354. location_reset(location,LOC_FLAGS,OS_NO);
  355. location.resflags:=F_E;
  356. end;
  357. else
  358. internalerror(200203224);
  359. end;
  360. end;
  361. end;
  362. {$ifdef SUPPORT_MMX}
  363. procedure ti386notnode.second_mmx;
  364. var hreg,r:Tregister;
  365. begin
  366. secondpass(left);
  367. location_reset(location,LOC_MMXREGISTER,OS_NO);
  368. r:=cg.getintregister(exprasmlist,OS_INT);
  369. emit_const_reg(A_MOV,S_L,longint($ffffffff),r);
  370. { load operand }
  371. case left.location.loc of
  372. LOC_MMXREGISTER:
  373. location_copy(location,left.location);
  374. LOC_CMMXREGISTER:
  375. begin
  376. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  377. emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
  378. end;
  379. LOC_REFERENCE,
  380. LOC_CREFERENCE:
  381. begin
  382. location_release(exprasmlist,left.location);
  383. location.register:=cg.getmmxregister(exprasmlist,OS_M64);
  384. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
  385. end;
  386. end;
  387. { load mask }
  388. hreg:=cg.getmmxregister(exprasmlist,OS_M64);
  389. emit_reg_reg(A_MOVD,S_NO,r,hreg);
  390. cg.ungetregister(exprasmlist,r);
  391. { lower 32 bit }
  392. emit_reg_reg(A_PXOR,S_D,hreg,location.register);
  393. { shift mask }
  394. emit_const_reg(A_PSLLQ,S_NO,32,hreg);
  395. { higher 32 bit }
  396. cg.ungetregister(exprasmlist,hreg);
  397. emit_reg_reg(A_PXOR,S_D,hreg,location.register);
  398. end;
  399. {$endif SUPPORT_MMX}
  400. begin
  401. cunaryminusnode:=ti386unaryminusnode;
  402. cmoddivnode:=ti386moddivnode;
  403. cshlshrnode:=ti386shlshrnode;
  404. cnotnode:=ti386notnode;
  405. end.
  406. {
  407. $Log$
  408. Revision 1.68 2003-12-26 13:19:16 florian
  409. * rtl and compiler compile with -Cfsse2
  410. Revision 1.67 2003/12/25 01:07:09 florian
  411. + $fputype directive support
  412. + single data type operations with sse unit
  413. * fixed more x86-64 stuff
  414. Revision 1.66 2003/12/10 17:28:41 peter
  415. * int64 shl/shr > 63 returns 0
  416. Revision 1.65 2003/10/10 17:48:14 peter
  417. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  418. * tregisteralloctor renamed to trgobj
  419. * removed rgobj from a lot of units
  420. * moved location_* and reference_* to cgobj
  421. * first things for mmx register allocation
  422. Revision 1.64 2003/10/09 21:31:37 daniel
  423. * Register allocator splitted, ans abstract now
  424. Revision 1.63 2003/10/01 20:34:49 peter
  425. * procinfo unit contains tprocinfo
  426. * cginfo renamed to cgbase
  427. * moved cgmessage to verbose
  428. * fixed ppc and sparc compiles
  429. Revision 1.62 2003/09/29 20:58:56 peter
  430. * optimized releasing of registers
  431. Revision 1.61 2003/09/28 21:48:20 peter
  432. * fix register leaks
  433. Revision 1.60 2003/09/03 15:55:01 peter
  434. * NEWRA branch merged
  435. Revision 1.59.2.2 2003/08/31 13:50:16 daniel
  436. * Remove sorting and use pregenerated indexes
  437. * Some work on making things compile
  438. Revision 1.59.2.1 2003/08/29 17:29:00 peter
  439. * next batch of updates
  440. Revision 1.59 2003/07/02 22:18:04 peter
  441. * paraloc splitted in callerparaloc,calleeparaloc
  442. * sparc calling convention updates
  443. Revision 1.58 2003/06/13 21:19:31 peter
  444. * current_procdef removed, use current_procinfo.procdef instead
  445. Revision 1.57 2003/06/03 21:11:09 peter
  446. * cg.a_load_* get a from and to size specifier
  447. * makeregsize only accepts newregister
  448. * i386 uses generic tcgnotnode,tcgunaryminus
  449. Revision 1.56 2003/06/03 13:01:59 daniel
  450. * Register allocator finished
  451. Revision 1.55 2003/05/31 15:04:31 peter
  452. * load_loc_reg update
  453. Revision 1.54 2003/05/22 21:32:29 peter
  454. * removed some unit dependencies
  455. Revision 1.53 2003/04/22 23:50:23 peter
  456. * firstpass uses expectloc
  457. * checks if there are differences between the expectloc and
  458. location.loc from secondpass in EXTDEBUG
  459. Revision 1.52 2003/04/22 14:33:38 peter
  460. * removed some notes/hints
  461. Revision 1.51 2003/04/22 10:09:35 daniel
  462. + Implemented the actual register allocator
  463. + Scratch registers unavailable when new register allocator used
  464. + maybe_save/maybe_restore unavailable when new register allocator used
  465. Revision 1.50 2003/04/21 19:15:26 peter
  466. * when ecx is not available allocated another register
  467. Revision 1.49 2003/04/17 10:02:48 daniel
  468. * Tweaked register allocate/deallocate positition to less interferences
  469. are generated.
  470. Revision 1.48 2003/03/28 19:16:57 peter
  471. * generic constructor working for i386
  472. * remove fixed self register
  473. * esi added as address register for i386
  474. Revision 1.47 2003/03/08 20:36:41 daniel
  475. + Added newra version of Ti386shlshrnode
  476. + Added interference graph construction code
  477. Revision 1.46 2003/03/08 13:59:17 daniel
  478. * Work to handle new register notation in ag386nsm
  479. + Added newra version of Ti386moddivnode
  480. Revision 1.45 2003/02/19 22:00:15 daniel
  481. * Code generator converted to new register notation
  482. - Horribily outdated todo.txt removed
  483. Revision 1.44 2003/01/13 18:37:44 daniel
  484. * Work on register conversion
  485. Revision 1.43 2003/01/13 14:54:34 daniel
  486. * Further work to convert codegenerator register convention;
  487. internalerror bug fixed.
  488. Revision 1.42 2003/01/08 18:43:57 daniel
  489. * Tregister changed into a record
  490. Revision 1.41 2002/11/25 17:43:26 peter
  491. * splitted defbase in defutil,symutil,defcmp
  492. * merged isconvertable and is_equal into compare_defs(_ext)
  493. * made operator search faster by walking the list only once
  494. Revision 1.40 2002/09/07 15:25:10 peter
  495. * old logs removed and tabs fixed
  496. Revision 1.39 2002/08/15 15:15:55 carl
  497. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  498. * more generic nodes for maths
  499. * several fixes for better m68k support
  500. Revision 1.38 2002/08/14 19:18:16 carl
  501. * bugfix of unaryminus node with left LOC_CREGISTER
  502. Revision 1.37 2002/08/12 15:08:42 carl
  503. + stab register indexes for powerpc (moved from gdb to cpubase)
  504. + tprocessor enumeration moved to cpuinfo
  505. + linker in target_info is now a class
  506. * many many updates for m68k (will soon start to compile)
  507. - removed some ifdef or correct them for correct cpu
  508. Revision 1.36 2002/08/11 14:32:30 peter
  509. * renamed current_library to objectlibrary
  510. Revision 1.35 2002/08/11 13:24:17 peter
  511. * saving of asmsymbols in ppu supported
  512. * asmsymbollist global is removed and moved into a new class
  513. tasmlibrarydata that will hold the info of a .a file which
  514. corresponds with a single module. Added librarydata to tmodule
  515. to keep the library info stored for the module. In the future the
  516. objectfiles will also be stored to the tasmlibrarydata class
  517. * all getlabel/newasmsymbol and friends are moved to the new class
  518. Revision 1.34 2002/08/02 07:44:31 jonas
  519. * made assigned() handling generic
  520. * add nodes now can also evaluate constant expressions at compile time
  521. that contain nil nodes
  522. Revision 1.33 2002/07/20 11:58:02 florian
  523. * types.pas renamed to defbase.pas because D6 contains a types
  524. unit so this would conflicts if D6 programms are compiled
  525. + Willamette/SSE2 instructions to assembler added
  526. Revision 1.32 2002/07/01 18:46:33 peter
  527. * internal linker
  528. * reorganized aasm layer
  529. Revision 1.31 2002/05/18 13:34:25 peter
  530. * readded missing revisions
  531. Revision 1.30 2002/05/16 19:46:51 carl
  532. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  533. + try to fix temp allocation (still in ifdef)
  534. + generic constructor calls
  535. + start of tassembler / tmodulebase class cleanup
  536. Revision 1.28 2002/05/13 19:54:38 peter
  537. * removed n386ld and n386util units
  538. * maybe_save/maybe_restore added instead of the old maybe_push
  539. Revision 1.27 2002/05/12 16:53:17 peter
  540. * moved entry and exitcode to ncgutil and cgobj
  541. * foreach gets extra argument for passing local data to the
  542. iterator function
  543. * -CR checks also class typecasts at runtime by changing them
  544. into as
  545. * fixed compiler to cycle with the -CR option
  546. * fixed stabs with elf writer, finally the global variables can
  547. be watched
  548. * removed a lot of routines from cga unit and replaced them by
  549. calls to cgobj
  550. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  551. u32bit then the other is typecasted also to u32bit without giving
  552. a rangecheck warning/error.
  553. * fixed pascal calling method with reversing also the high tree in
  554. the parast, detected by tcalcst3 test
  555. Revision 1.26 2002/04/04 19:06:12 peter
  556. * removed unused units
  557. * use tlocation.size in cg.a_*loc*() routines
  558. Revision 1.25 2002/04/02 17:11:36 peter
  559. * tlocation,treference update
  560. * LOC_CONSTANT added for better constant handling
  561. * secondadd splitted in multiple routines
  562. * location_force_reg added for loading a location to a register
  563. of a specified size
  564. * secondassignment parses now first the right and then the left node
  565. (this is compatible with Kylix). This saves a lot of push/pop especially
  566. with string operations
  567. * adapted some routines to use the new cg methods
  568. Revision 1.24 2002/03/31 20:26:39 jonas
  569. + a_loadfpu_* and a_loadmm_* methods in tcg
  570. * register allocation is now handled by a class and is mostly processor
  571. independent (+rgobj.pas and i386/rgcpu.pas)
  572. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  573. * some small improvements and fixes to the optimizer
  574. * some register allocation fixes
  575. * some fpuvaroffset fixes in the unary minus node
  576. * push/popusedregisters is now called rg.save/restoreusedregisters and
  577. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  578. also better optimizable)
  579. * fixed and optimized register saving/restoring for new/dispose nodes
  580. * LOC_FPU locations now also require their "register" field to be set to
  581. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  582. - list field removed of the tnode class because it's not used currently
  583. and can cause hard-to-find bugs
  584. Revision 1.23 2002/03/04 19:10:14 peter
  585. * removed compiler warnings
  586. }