n386mat.pas 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315
  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;
  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(tunaryminusnode)
  33. function pass_1 : tnode;override;
  34. procedure pass_2;override;
  35. end;
  36. ti386notnode = class(tnotnode)
  37. procedure pass_2;override;
  38. end;
  39. implementation
  40. uses
  41. globtype,systems,
  42. cutils,verbose,globals,
  43. symconst,symdef,aasmbase,aasmtai,aasmcpu,defutil,
  44. cginfo,cgbase,pass_1,pass_2,
  45. ncon,
  46. cpubase,cpuinfo,
  47. cga,tgobj,ncgutil,cgobj,rgobj,rgcpu;
  48. {*****************************************************************************
  49. TI386MODDIVNODE
  50. *****************************************************************************}
  51. {$ifdef newra}
  52. procedure ti386moddivnode.pass_2;
  53. var r,r2,hreg1,hreg2:Tregister;
  54. power:longint;
  55. hl:Tasmlabel;
  56. op:Tasmop;
  57. pushedregs:Tmaybesave;
  58. begin
  59. secondpass(left);
  60. if codegenerror then
  61. exit;
  62. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  63. secondpass(right);
  64. maybe_restore(exprasmlist,left.location,pushedregs);
  65. if codegenerror then
  66. exit;
  67. if is_64bitint(resulttype.def) then
  68. { should be handled in pass_1 (JM) }
  69. internalerror(200109052);
  70. { put numerator in register }
  71. location_reset(location,LOC_REGISTER,OS_INT);
  72. location_force_reg(exprasmlist,left.location,OS_INT,false);
  73. hreg1:=left.location.register;
  74. if (nodetype=divn) and (right.nodetype=ordconstn) and
  75. ispowerof2(tordconstnode(right).value,power) then
  76. begin
  77. { for signed numbers, the numerator must be adjusted before the
  78. shift instruction, but not wih unsigned numbers! Otherwise,
  79. "Cardinal($ffffffff) div 16" overflows! (JM) }
  80. if is_signed(left.resulttype.def) Then
  81. begin
  82. if (aktOptProcessor <> class386) and
  83. not(cs_littlesize in aktglobalswitches) then
  84. { use a sequence without jumps, saw this in
  85. comp.compilers (JM) }
  86. begin
  87. { no jumps, but more operations }
  88. hreg2:=rg.getregisterint(exprasmlist,OS_INT);
  89. emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
  90. {If the left value is signed, hreg2=$ffffffff, otherwise 0.}
  91. emit_const_reg(A_SAR,S_L,31,hreg2);
  92. {If signed, hreg2=right value-1, otherwise 0.}
  93. emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
  94. { add to the left value }
  95. emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
  96. { release EDX if we used it }
  97. rg.ungetregisterint(exprasmlist,hreg2);
  98. { do the shift }
  99. emit_const_reg(A_SAR,S_L,power,hreg1);
  100. end
  101. else
  102. begin
  103. { a jump, but less operations }
  104. emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
  105. objectlibrary.getlabel(hl);
  106. emitjmp(C_NS,hl);
  107. if power=1 then
  108. emit_reg(A_INC,S_L,hreg1)
  109. else
  110. emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
  111. cg.a_label(exprasmlist,hl);
  112. emit_const_reg(A_SAR,S_L,power,hreg1);
  113. end
  114. end
  115. else
  116. emit_const_reg(A_SHR,S_L,power,hreg1);
  117. location.register:=hreg1;
  118. end
  119. else
  120. begin
  121. {Bring denominator to a register.}
  122. rg.getexplicitregisterint(exprasmlist,NR_EAX);
  123. r.enum:=R_INTREGISTER;
  124. r.number:=NR_EAX;
  125. r2.enum:=R_INTREGISTER;
  126. r2.number:=NR_EDX;
  127. emit_reg_reg(A_MOV,S_L,hreg1,r);
  128. rg.ungetregisterint(exprasmlist,hreg1);
  129. rg.getexplicitregisterint(exprasmlist,NR_EDX);
  130. {Sign extension depends on the left type.}
  131. if torddef(left.resulttype.def).typ=u32bit then
  132. emit_reg_reg(A_XOR,S_L,r2,r2)
  133. else
  134. emit_none(A_CDQ,S_NO);
  135. {Division depends on the right type.}
  136. if torddef(right.resulttype.def).typ=u32bit then
  137. op:=A_DIV
  138. else
  139. op:=A_IDIV;
  140. if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  141. emit_ref(op,S_L,right.location.reference)
  142. else
  143. emit_reg(op,S_L,right.location.register);
  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. rg.ungetregisterint(exprasmlist,r2);
  149. location.register:=rg.getregisterint(exprasmlist,OS_INT);
  150. emit_reg_reg(A_MOV,S_L,r,location.register);
  151. rg.ungetregisterint(exprasmlist,r);
  152. end
  153. else
  154. begin
  155. rg.ungetregisterint(exprasmlist,r);
  156. location.register:=rg.getregisterint(exprasmlist,OS_INT);
  157. emit_reg_reg(A_MOV,S_L,r2,location.register);
  158. rg.ungetregisterint(exprasmlist,r2);
  159. end;
  160. end;
  161. end;
  162. {$else}
  163. procedure ti386moddivnode.pass_2;
  164. var
  165. hreg1 : tregister;
  166. hreg2 : tregister;
  167. r,r2 : Tregister;
  168. shrdiv,popeax,popedx : boolean;
  169. power : longint;
  170. hl : tasmlabel;
  171. pushedregs : tmaybesave;
  172. begin
  173. shrdiv := false;
  174. secondpass(left);
  175. if codegenerror then
  176. exit;
  177. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  178. secondpass(right);
  179. maybe_restore(exprasmlist,left.location,pushedregs);
  180. if codegenerror then
  181. exit;
  182. location_copy(location,left.location);
  183. if is_64bitint(resulttype.def) then
  184. begin
  185. { should be handled in pass_1 (JM) }
  186. internalerror(200109052);
  187. end
  188. else
  189. begin
  190. { put numerator in register }
  191. location_force_reg(exprasmlist,left.location,OS_INT,false);
  192. hreg1:=left.location.register;
  193. if hreg1.enum<>R_INTREGISTER then
  194. internalerror(200302042);
  195. if (nodetype=divn) and (right.nodetype=ordconstn) and
  196. ispowerof2(tordconstnode(right).value,power) then
  197. begin
  198. shrdiv := true;
  199. { for signed numbers, the numerator must be adjusted before the
  200. shift instruction, but not wih unsigned numbers! Otherwise,
  201. "Cardinal($ffffffff) div 16" overflows! (JM) }
  202. if is_signed(left.resulttype.def) Then
  203. begin
  204. if (aktOptProcessor <> class386) and
  205. not(CS_LittleSize in aktglobalswitches) then
  206. { use a sequence without jumps, saw this in
  207. comp.compilers (JM) }
  208. begin
  209. { no jumps, but more operations }
  210. if (hreg1.number = NR_EAX) and
  211. (RS_EDX in rg.unusedregsint) then
  212. begin
  213. hreg2 := rg.getexplicitregisterint(exprasmlist,NR_EDX);
  214. emit_none(A_CDQ,S_NO);
  215. end
  216. else
  217. begin
  218. rg.getexplicitregisterint(exprasmlist,NR_EDI);
  219. hreg2.enum := R_INTREGISTER;
  220. hreg2.number := NR_EDI;
  221. emit_reg_reg(A_MOV,S_L,hreg1,hreg2);
  222. { if the left value is signed, R_EDI := $ffffffff,
  223. otherwise 0 }
  224. emit_const_reg(A_SAR,S_L,31,hreg2);
  225. { if signed, R_EDI := right value-1, otherwise 0 }
  226. end;
  227. emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
  228. { add to the left value }
  229. emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
  230. { release EDX if we used it }
  231. { also releas EDI }
  232. rg.ungetregisterint(exprasmlist,hreg2);
  233. { do the shift }
  234. emit_const_reg(A_SAR,S_L,power,hreg1);
  235. end
  236. else
  237. begin
  238. { a jump, but less operations }
  239. emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
  240. objectlibrary.getlabel(hl);
  241. emitjmp(C_NS,hl);
  242. if power=1 then
  243. emit_reg(A_INC,S_L,hreg1)
  244. else
  245. emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
  246. cg.a_label(exprasmlist,hl);
  247. emit_const_reg(A_SAR,S_L,power,hreg1);
  248. end
  249. end
  250. else
  251. emit_const_reg(A_SHR,S_L,power,hreg1);
  252. end
  253. else
  254. begin
  255. { bring denominator to EDI }
  256. { EDI is always free, it's }
  257. { only used for temporary }
  258. { purposes }
  259. rg.getexplicitregisterint(exprasmlist,NR_EDI);
  260. if right.location.loc<>LOC_CREGISTER then
  261. location_release(exprasmlist,right.location);
  262. r.enum:=R_INTREGISTER;
  263. r.number:=NR_EDI;
  264. cg.a_load_loc_reg(exprasmlist,right.location,r);
  265. popedx:=false;
  266. popeax:=false;
  267. r.number:=NR_EAX;
  268. r2.enum:=R_INTREGISTER;
  269. r2.number:=NR_EDX;
  270. if hreg1.number=NR_EDX then
  271. begin
  272. if not(RS_EAX in rg.unusedregsint) then
  273. begin
  274. emit_reg(A_PUSH,S_L,r);
  275. popeax:=true;
  276. end
  277. else
  278. rg.getexplicitregisterint(exprasmlist,NR_EAX);
  279. emit_reg_reg(A_MOV,S_L,r2,r);
  280. end
  281. else
  282. begin
  283. if not(RS_EDX in rg.unusedregsint) then
  284. begin
  285. emit_reg(A_PUSH,S_L,r2);
  286. popedx:=true;
  287. end
  288. else
  289. rg.getexplicitregisterint(exprasmlist,NR_EDX);
  290. if hreg1.number<>NR_EAX then
  291. begin
  292. if not(RS_EAX in rg.unusedregsint) then
  293. begin
  294. emit_reg(A_PUSH,S_L,r);
  295. popeax:=true;
  296. end
  297. else
  298. rg.getexplicitregisterint(exprasmlist,NR_EAX);
  299. emit_reg_reg(A_MOV,S_L,hreg1,r);
  300. end;
  301. end;
  302. { sign extension depends on the left type }
  303. if torddef(left.resulttype.def).typ=u32bit then
  304. emit_reg_reg(A_XOR,S_L,r2,r2)
  305. else
  306. emit_none(A_CDQ,S_NO);
  307. { division depends on the right type }
  308. r.enum:=R_INTREGISTER;
  309. r.number:=NR_EDI;
  310. if torddef(right.resulttype.def).typ=u32bit then
  311. emit_reg(A_DIV,S_L,r)
  312. else
  313. emit_reg(A_IDIV,S_L,r);
  314. rg.ungetregisterint(exprasmlist,r);
  315. r.enum:=R_INTREGISTER;
  316. r.number:=NR_EAX;
  317. if nodetype=divn then
  318. begin
  319. if not popedx and (hreg1.number <> NR_EDX) then
  320. begin
  321. r2.enum:=R_INTREGISTER;
  322. r2.number:=NR_EDX;
  323. rg.ungetregisterint(exprasmlist,r2);
  324. end;
  325. { if result register is busy then copy }
  326. if popeax then
  327. begin
  328. if hreg1.number=NR_EAX then
  329. internalerror(112);
  330. emit_reg_reg(A_MOV,S_L,r,hreg1)
  331. end
  332. else
  333. if hreg1.number<>NR_EAX then
  334. begin
  335. rg.ungetregisterint(exprasmlist,hreg1);
  336. { no need to allocate eax, that's already done before }
  337. { the div (JM) }
  338. hreg1.number:=NR_EAX;
  339. end;
  340. end
  341. else
  342. begin
  343. if not popeax and (hreg1.number <> NR_EAX)then
  344. begin
  345. r.number:=NR_EAX;
  346. rg.ungetregisterint(exprasmlist,r);
  347. end;
  348. if popedx then
  349. {the mod was done by an (i)div (so the result is now in
  350. edx), but edx was occupied prior to the division, so
  351. move the result into a safe place (JM)}
  352. emit_reg_reg(A_MOV,S_L,r2,hreg1)
  353. else
  354. begin
  355. if hreg1.number <> NR_EDX then
  356. rg.ungetregisterint(exprasmlist,hreg1);
  357. hreg1.number:=NR_EDX
  358. end;
  359. end;
  360. if popeax then
  361. emit_reg(A_POP,S_L,r);
  362. if popedx then
  363. emit_reg(A_POP,S_L,r2);
  364. end;
  365. If not(shrdiv) then
  366. { shrdiv only use hreg1 (which is already in usedinproc, }
  367. { since it was acquired with getregister), the others also }
  368. { use both EAX and EDX (JM) }
  369. begin
  370. include(rg.usedintinproc,RS_EAX);
  371. include(rg.usedintinproc,RS_EDX);
  372. end;
  373. location_reset(location,LOC_REGISTER,OS_INT);
  374. location.register:=hreg1;
  375. end;
  376. end;
  377. {$endif}
  378. {*****************************************************************************
  379. TI386SHLRSHRNODE
  380. *****************************************************************************}
  381. function ti386shlshrnode.first_shlshr64bitint: tnode;
  382. begin
  383. result := nil;
  384. end;
  385. {$ifdef newra}
  386. procedure ti386shlshrnode.pass_2;
  387. var hregister2,hregisterhigh,hregisterlow:Tregister;
  388. r,r2:Tregister;
  389. op:Tasmop;
  390. l1,l2,l3:Tasmlabel;
  391. pushedregs:Tmaybesave;
  392. begin
  393. secondpass(left);
  394. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  395. secondpass(right);
  396. maybe_restore(exprasmlist,left.location,pushedregs);
  397. { determine operator }
  398. if nodetype=shln then
  399. op:=A_SHL
  400. else
  401. op:=A_SHR;
  402. if is_64bitint(left.resulttype.def) then
  403. begin
  404. location_reset(location,LOC_REGISTER,OS_64);
  405. { load left operator in a register }
  406. location_force_reg(exprasmlist,left.location,OS_64,false);
  407. hregisterhigh:=left.location.registerhigh;
  408. hregisterlow:=left.location.registerlow;
  409. if hregisterhigh.enum<>R_INTREGISTER then
  410. internalerror(200302056);
  411. if hregisterlow.enum<>R_INTREGISTER then
  412. internalerror(200302056);
  413. { shifting by a constant directly coded: }
  414. if (right.nodetype=ordconstn) then
  415. begin
  416. { shrd/shl works only for values <=31 !! }
  417. if Tordconstnode(right).value>31 then
  418. begin
  419. if nodetype=shln then
  420. begin
  421. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  422. if ((tordconstnode(right).value and 31) <> 0) then
  423. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  424. hregisterlow);
  425. end
  426. else
  427. begin
  428. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  429. if ((tordconstnode(right).value and 31) <> 0) then
  430. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  431. hregisterhigh);
  432. end;
  433. location.registerhigh:=hregisterlow;
  434. location.registerlow:=hregisterhigh;
  435. end
  436. else
  437. begin
  438. if nodetype=shln then
  439. begin
  440. emit_const_reg_reg(A_SHLD,S_L,tordconstnode(right).value and 31,
  441. hregisterlow,hregisterhigh);
  442. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  443. hregisterlow);
  444. end
  445. else
  446. begin
  447. emit_const_reg_reg(A_SHRD,S_L,tordconstnode(right).value and 31,
  448. hregisterhigh,hregisterlow);
  449. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  450. hregisterhigh);
  451. end;
  452. location.registerlow:=hregisterlow;
  453. location.registerhigh:=hregisterhigh;
  454. end;
  455. end
  456. else
  457. begin
  458. { load right operators in a register }
  459. rg.getexplicitregisterint(exprasmlist,NR_ECX);
  460. hregister2.enum:=R_INTREGISTER;
  461. hregister2.number:=NR_ECX;
  462. cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
  463. if right.location.loc<>LOC_CREGISTER then
  464. location_release(exprasmlist,right.location);
  465. { left operator is already in a register }
  466. { hence are both in a register }
  467. { is it in the case ECX ? }
  468. r.enum:=R_INTREGISTER;
  469. r.number:=NR_ECX;
  470. r2.enum:=R_INTREGISTER;
  471. r2.number:=NR_CL;
  472. { the damned shift instructions work only til a count of 32 }
  473. { so we've to do some tricks here }
  474. objectlibrary.getlabel(l1);
  475. objectlibrary.getlabel(l2);
  476. objectlibrary.getlabel(l3);
  477. emit_const_reg(A_CMP,S_L,64,hregister2);
  478. emitjmp(C_L,l1);
  479. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  480. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  481. cg.a_jmp_always(exprasmlist,l3);
  482. cg.a_label(exprasmlist,l1);
  483. emit_const_reg(A_CMP,S_L,32,hregister2);
  484. emitjmp(C_L,l2);
  485. emit_const_reg(A_SUB,S_L,32,hregister2);
  486. if nodetype=shln then
  487. begin
  488. emit_reg_reg(A_SHL,S_L,r2,hregisterlow);
  489. emit_reg_reg(A_MOV,S_L,hregisterlow,hregisterhigh);
  490. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  491. cg.a_jmp_always(exprasmlist,l3);
  492. cg.a_label(exprasmlist,l2);
  493. emit_reg_reg_reg(A_SHLD,S_L,r2,hregisterlow,hregisterhigh);
  494. emit_reg_reg(A_SHL,S_L,r2,hregisterlow);
  495. end
  496. else
  497. begin
  498. emit_reg_reg(A_SHR,S_L,r2,hregisterhigh);
  499. emit_reg_reg(A_MOV,S_L,hregisterhigh,hregisterlow);
  500. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  501. cg.a_jmp_always(exprasmlist,l3);
  502. cg.a_label(exprasmlist,l2);
  503. emit_reg_reg_reg(A_SHRD,S_L,r2,hregisterhigh,hregisterlow);
  504. emit_reg_reg(A_SHR,S_L,r2,hregisterhigh);
  505. end;
  506. cg.a_label(exprasmlist,l3);
  507. rg.ungetregisterint(exprasmlist,hregister2);
  508. location.registerlow:=hregisterlow;
  509. location.registerhigh:=hregisterhigh;
  510. end;
  511. end
  512. else
  513. begin
  514. { load left operators in a register }
  515. location_copy(location,left.location);
  516. location_force_reg(exprasmlist,location,OS_INT,false);
  517. r2.enum:=R_INTREGISTER;
  518. r2.number:=NR_CL;
  519. { shifting by a constant directly coded: }
  520. if (right.nodetype=ordconstn) then
  521. { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)}
  522. emit_const_reg(op,S_L,tordconstnode(right).value and 31,location.register)
  523. else
  524. begin
  525. { load right operators in a ECX }
  526. if right.location.loc<>LOC_CREGISTER then
  527. location_release(exprasmlist,right.location);
  528. hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
  529. cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
  530. { right operand is in ECX }
  531. emit_reg_reg(op,S_L,r2,location.register);
  532. rg.ungetregisterint(exprasmlist,hregister2);
  533. end;
  534. end;
  535. end;
  536. {$else}
  537. procedure ti386shlshrnode.pass_2;
  538. var
  539. hregister2,hregister3,
  540. hregisterhigh,hregisterlow : tregister;
  541. popecx : boolean;
  542. op : tasmop;
  543. l1,l2,l3 : tasmlabel;
  544. pushedregs : tmaybesave;
  545. r,r2:Tregister;
  546. begin
  547. popecx:=false;
  548. secondpass(left);
  549. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  550. secondpass(right);
  551. maybe_restore(exprasmlist,left.location,pushedregs);
  552. { determine operator }
  553. case nodetype of
  554. shln: op:=A_SHL;
  555. shrn: op:=A_SHR;
  556. end;
  557. if is_64bitint(left.resulttype.def) then
  558. begin
  559. location_reset(location,LOC_REGISTER,OS_64);
  560. { load left operator in a register }
  561. location_force_reg(exprasmlist,left.location,OS_64,false);
  562. hregisterhigh:=left.location.registerhigh;
  563. hregisterlow:=left.location.registerlow;
  564. if hregisterhigh.enum<>R_INTREGISTER then
  565. internalerror(200302056);
  566. if hregisterlow.enum<>R_INTREGISTER then
  567. internalerror(200302056);
  568. { shifting by a constant directly coded: }
  569. if (right.nodetype=ordconstn) then
  570. begin
  571. { shrd/shl works only for values <=31 !! }
  572. if tordconstnode(right).value>31 then
  573. begin
  574. if nodetype=shln then
  575. begin
  576. emit_reg_reg(A_XOR,S_L,hregisterhigh,
  577. hregisterhigh);
  578. if ((tordconstnode(right).value and 31) <> 0) then
  579. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  580. hregisterlow);
  581. end
  582. else
  583. begin
  584. emit_reg_reg(A_XOR,S_L,hregisterlow,
  585. hregisterlow);
  586. if ((tordconstnode(right).value and 31) <> 0) then
  587. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  588. hregisterhigh);
  589. end;
  590. location.registerhigh:=hregisterlow;
  591. location.registerlow:=hregisterhigh;
  592. end
  593. else
  594. begin
  595. if nodetype=shln then
  596. begin
  597. emit_const_reg_reg(A_SHLD,S_L,tordconstnode(right).value and 31,
  598. hregisterlow,hregisterhigh);
  599. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  600. hregisterlow);
  601. end
  602. else
  603. begin
  604. emit_const_reg_reg(A_SHRD,S_L,tordconstnode(right).value and 31,
  605. hregisterhigh,hregisterlow);
  606. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  607. hregisterhigh);
  608. end;
  609. location.registerlow:=hregisterlow;
  610. location.registerhigh:=hregisterhigh;
  611. end;
  612. end
  613. else
  614. begin
  615. { load right operators in a register }
  616. if right.location.loc<>LOC_REGISTER then
  617. begin
  618. if right.location.loc<>LOC_CREGISTER then
  619. location_release(exprasmlist,right.location);
  620. hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
  621. cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
  622. end
  623. else
  624. hregister2:=right.location.register;
  625. { left operator is already in a register }
  626. { hence are both in a register }
  627. { is it in the case ECX ? }
  628. r.enum:=R_INTREGISTER;
  629. r.number:=NR_ECX;
  630. r2.enum:=R_INTREGISTER;
  631. r2.number:=NR_CL;
  632. if (hregisterlow.number=NR_ECX) then
  633. begin
  634. { then only swap }
  635. emit_reg_reg(A_XCHG,S_L,hregisterlow,hregister2);
  636. hregister3:=hregisterlow;
  637. hregisterlow:=hregister2;
  638. hregister2:=hregister3;
  639. end
  640. else if (hregisterhigh.number=NR_ECX) then
  641. begin
  642. { then only swap }
  643. emit_reg_reg(A_XCHG,S_L,hregisterhigh,hregister2);
  644. hregister3:=hregisterhigh;
  645. hregisterhigh:=hregister2;
  646. hregister2:=hregister3;
  647. end
  648. { if second operator not in ECX ? }
  649. else if (hregister2.number<>NR_ECX) then
  650. begin
  651. { ECX occupied then push it }
  652. if not (RS_ECX in rg.unusedregsint) then
  653. begin
  654. popecx:=true;
  655. emit_reg(A_PUSH,S_L,r);
  656. end
  657. else
  658. rg.getexplicitregisterint(exprasmlist,NR_ECX);
  659. emit_reg_reg(A_MOV,S_L,hregister2,r);
  660. end;
  661. if hregister2.number <> NR_ECX then
  662. rg.ungetregisterint(exprasmlist,hregister2);
  663. { the damned shift instructions work only til a count of 32 }
  664. { so we've to do some tricks here }
  665. if nodetype=shln then
  666. begin
  667. objectlibrary.getlabel(l1);
  668. objectlibrary.getlabel(l2);
  669. objectlibrary.getlabel(l3);
  670. emit_const_reg(A_CMP,S_L,64,r);
  671. emitjmp(C_L,l1);
  672. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  673. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  674. cg.a_jmp_always(exprasmlist,l3);
  675. cg.a_label(exprasmlist,l1);
  676. emit_const_reg(A_CMP,S_L,32,r);
  677. emitjmp(C_L,l2);
  678. emit_const_reg(A_SUB,S_L,32,r);
  679. emit_reg_reg(A_SHL,S_L,r2,
  680. hregisterlow);
  681. emit_reg_reg(A_MOV,S_L,hregisterlow,hregisterhigh);
  682. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  683. cg.a_jmp_always(exprasmlist,l3);
  684. cg.a_label(exprasmlist,l2);
  685. emit_reg_reg_reg(A_SHLD,S_L,r2,
  686. hregisterlow,hregisterhigh);
  687. emit_reg_reg(A_SHL,S_L,r2,
  688. hregisterlow);
  689. cg.a_label(exprasmlist,l3);
  690. end
  691. else
  692. begin
  693. objectlibrary.getlabel(l1);
  694. objectlibrary.getlabel(l2);
  695. objectlibrary.getlabel(l3);
  696. emit_const_reg(A_CMP,S_L,64,r);
  697. emitjmp(C_L,l1);
  698. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  699. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  700. cg.a_jmp_always(exprasmlist,l3);
  701. cg.a_label(exprasmlist,l1);
  702. emit_const_reg(A_CMP,S_L,32,r);
  703. emitjmp(C_L,l2);
  704. emit_const_reg(A_SUB,S_L,32,r);
  705. emit_reg_reg(A_SHR,S_L,r2,
  706. hregisterhigh);
  707. emit_reg_reg(A_MOV,S_L,hregisterhigh,hregisterlow);
  708. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  709. cg.a_jmp_always(exprasmlist,l3);
  710. cg.a_label(exprasmlist,l2);
  711. emit_reg_reg_reg(A_SHRD,S_L,r2,
  712. hregisterhigh,hregisterlow);
  713. emit_reg_reg(A_SHR,S_L,r2,
  714. hregisterhigh);
  715. cg.a_label(exprasmlist,l3);
  716. end;
  717. { maybe put ECX back }
  718. if popecx then
  719. emit_reg(A_POP,S_L,r)
  720. else
  721. rg.ungetregisterint(exprasmlist,r);
  722. location.registerlow:=hregisterlow;
  723. location.registerhigh:=hregisterhigh;
  724. end;
  725. end
  726. else
  727. begin
  728. { load left operators in a register }
  729. location_copy(location,left.location);
  730. location_force_reg(exprasmlist,location,OS_INT,false);
  731. r.enum:=R_INTREGISTER;
  732. r.number:=NR_ECX;
  733. r2.enum:=R_INTREGISTER;
  734. r2.number:=NR_CL;
  735. { shifting by a constant directly coded: }
  736. if (right.nodetype=ordconstn) then
  737. begin
  738. { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)
  739. if right.value<=31 then
  740. }
  741. emit_const_reg(op,S_L,tordconstnode(right).value and 31,
  742. location.register);
  743. {
  744. else
  745. emit_reg_reg(A_XOR,S_L,hregister1,
  746. hregister1);
  747. }
  748. end
  749. else
  750. begin
  751. { load right operators in a register }
  752. if right.location.loc<>LOC_REGISTER then
  753. begin
  754. if right.location.loc<>LOC_CREGISTER then
  755. location_release(exprasmlist,right.location);
  756. hregister2:=rg.getexplicitregisterint(exprasmlist,NR_ECX);
  757. cg.a_load_loc_reg(exprasmlist,right.location,hregister2);
  758. end
  759. else
  760. hregister2:=right.location.register;
  761. { left operator is already in a register }
  762. { hence are both in a register }
  763. { is it in the case ECX ? }
  764. if (location.register.number=NR_ECX) then
  765. begin
  766. { then only swap }
  767. emit_reg_reg(A_XCHG,S_L,location.register,hregister2);
  768. hregister3:=location.register;
  769. location.register:=hregister2;
  770. hregister2:=hregister3;
  771. end
  772. { if second operator not in ECX ? }
  773. else if (hregister2.number<>NR_ECX) then
  774. begin
  775. { ECX occupied then push it }
  776. if not (RS_ECX in rg.unusedregsint) then
  777. begin
  778. popecx:=true;
  779. emit_reg(A_PUSH,S_L,r);
  780. end
  781. else
  782. rg.getexplicitregisterint(exprasmlist,NR_ECX);
  783. emit_reg_reg(A_MOV,S_L,hregister2,r);
  784. end;
  785. rg.ungetregisterint(exprasmlist,hregister2);
  786. { right operand is in ECX }
  787. emit_reg_reg(op,S_L,r2,location.register);
  788. { maybe ECX back }
  789. if popecx then
  790. emit_reg(A_POP,S_L,r)
  791. else
  792. rg.ungetregisterint(exprasmlist,r);
  793. end;
  794. end;
  795. end;
  796. {$endif}
  797. {*****************************************************************************
  798. TI386UNARYMINUSNODE
  799. *****************************************************************************}
  800. function ti386unaryminusnode.pass_1 : tnode;
  801. begin
  802. result:=nil;
  803. firstpass(left);
  804. if codegenerror then
  805. exit;
  806. registers32:=left.registers32;
  807. registersfpu:=left.registersfpu;
  808. {$ifdef SUPPORT_MMX}
  809. registersmmx:=left.registersmmx;
  810. {$endif SUPPORT_MMX}
  811. if (left.resulttype.def.deftype=floatdef) then
  812. begin
  813. if (registersfpu < 1) then
  814. registersfpu := 1;
  815. location.loc:=LOC_FPUREGISTER;
  816. end
  817. {$ifdef SUPPORT_MMX}
  818. else if (cs_mmx in aktlocalswitches) and
  819. is_mmx_able_array(left.resulttype.def) then
  820. begin
  821. if (left.location.loc<>LOC_MMXREGISTER) and
  822. (registersmmx<1) then
  823. registersmmx:=1;
  824. end
  825. {$endif SUPPORT_MMX}
  826. else if is_64bitint(left.resulttype.def) then
  827. begin
  828. if (left.location.loc<>LOC_REGISTER) and
  829. (registers32<2) then
  830. registers32:=2;
  831. location.loc:=LOC_REGISTER;
  832. end
  833. else if (left.resulttype.def.deftype=orddef) then
  834. begin
  835. if (left.location.loc<>LOC_REGISTER) and
  836. (registers32<1) then
  837. registers32:=1;
  838. location.loc:=LOC_REGISTER;
  839. end;
  840. end;
  841. procedure ti386unaryminusnode.pass_2;
  842. var r:Tregister;
  843. {$ifdef SUPPORT_MMX}
  844. procedure do_mmx_neg;
  845. var
  846. op : tasmop;
  847. r: Tregister;
  848. begin
  849. location_reset(location,LOC_MMXREGISTER,OS_NO);
  850. if cs_mmx_saturation in aktlocalswitches then
  851. case mmx_type(resulttype.def) of
  852. mmxs8bit:
  853. op:=A_PSUBSB;
  854. mmxu8bit:
  855. op:=A_PSUBUSB;
  856. mmxs16bit,mmxfixed16:
  857. op:=A_PSUBSW;
  858. mmxu16bit:
  859. op:=A_PSUBUSW;
  860. end
  861. else
  862. case mmx_type(resulttype.def) of
  863. mmxs8bit,mmxu8bit:
  864. op:=A_PSUBB;
  865. mmxs16bit,mmxu16bit,mmxfixed16:
  866. op:=A_PSUBW;
  867. mmxs32bit,mmxu32bit:
  868. op:=A_PSUBD;
  869. end;
  870. r.enum:=R_MM7;
  871. emit_reg_reg(op,S_NO,location.register,r);
  872. emit_reg_reg(A_MOVQ,S_NO,r,location.register);
  873. end;
  874. {$endif}
  875. begin
  876. if is_64bitint(left.resulttype.def) then
  877. begin
  878. secondpass(left);
  879. { load left operator in a register }
  880. location_copy(location,left.location);
  881. location_force_reg(exprasmlist,location,OS_64,false);
  882. emit_reg(A_NOT,S_L,location.registerhigh);
  883. emit_reg(A_NEG,S_L,location.registerlow);
  884. emit_const_reg(A_SBB,S_L,-1,location.registerhigh);
  885. end
  886. else
  887. begin
  888. secondpass(left);
  889. location_reset(location,LOC_REGISTER,OS_INT);
  890. case left.location.loc of
  891. LOC_REGISTER:
  892. begin
  893. location.register:=left.location.register;
  894. emit_reg(A_NEG,S_L,location.register);
  895. end;
  896. LOC_CREGISTER:
  897. begin
  898. location.register:=rg.getregisterint(exprasmlist,OS_INT);
  899. emit_reg_reg(A_MOV,S_L,left.location.register,
  900. location.register);
  901. emit_reg(A_NEG,S_L,location.register);
  902. end;
  903. {$ifdef SUPPORT_MMX}
  904. LOC_MMXREGISTER:
  905. begin
  906. location_copy(location,left.location);
  907. r.enum:=R_MM7;
  908. emit_reg_reg(A_PXOR,S_NO,r,r);
  909. do_mmx_neg;
  910. end;
  911. LOC_CMMXREGISTER:
  912. begin
  913. location.register:=rg.getregistermm(exprasmlist);
  914. r.enum:=R_MM7;
  915. emit_reg_reg(A_PXOR,S_NO,r,r);
  916. emit_reg_reg(A_MOVQ,S_NO,left.location.register,
  917. location.register);
  918. do_mmx_neg;
  919. end;
  920. {$endif SUPPORT_MMX}
  921. LOC_REFERENCE,
  922. LOC_CREFERENCE:
  923. begin
  924. reference_release(exprasmlist,left.location.reference);
  925. if (left.resulttype.def.deftype=floatdef) then
  926. begin
  927. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  928. location.register.enum:=R_ST;
  929. cg.a_loadfpu_ref_reg(exprasmlist,
  930. def_cgsize(left.resulttype.def),
  931. left.location.reference,location.register);
  932. emit_none(A_FCHS,S_NO);
  933. end
  934. {$ifdef SUPPORT_MMX}
  935. else if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
  936. begin
  937. r.enum:=R_MM7;
  938. location.register:=rg.getregistermm(exprasmlist);
  939. emit_reg_reg(A_PXOR,S_NO,r,r);
  940. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
  941. do_mmx_neg;
  942. end
  943. {$endif SUPPORT_MMX}
  944. else
  945. begin
  946. location.register:=rg.getregisterint(exprasmlist,OS_INT);
  947. emit_ref_reg(A_MOV,S_L,left.location.reference,location.register);
  948. emit_reg(A_NEG,S_L,location.register);
  949. end;
  950. end;
  951. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  952. begin
  953. { "load st,st" is ignored by the code generator }
  954. r.enum:=R_ST;
  955. cg.a_loadfpu_reg_reg(exprasmlist,left.location.register,r);
  956. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  957. location.register.enum:=R_ST;
  958. emit_none(A_FCHS,S_NO);
  959. end;
  960. else
  961. internalerror(200203225);
  962. end;
  963. end;
  964. { Here was a problem... }
  965. { Operand to be negated always }
  966. { seems to be converted to signed }
  967. { 32-bit before doing neg!! }
  968. { So this is useless... }
  969. { that's not true: -2^31 gives an overflow error if it is negaded (FK) }
  970. { emitoverflowcheck(p);}
  971. end;
  972. {*****************************************************************************
  973. TI386NOTNODE
  974. *****************************************************************************}
  975. procedure ti386notnode.pass_2;
  976. const
  977. flagsinvers : array[F_E..F_BE] of tresflags =
  978. (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
  979. F_BE,F_B,F_AE,F_A);
  980. var
  981. hl : tasmlabel;
  982. opsize : topsize;
  983. {$ifdef SUPPORT_MMX}
  984. r,r2 : tregister;
  985. {$endif SUPPORT_MMX}
  986. begin
  987. if is_boolean(resulttype.def) then
  988. begin
  989. opsize:=def_opsize(resulttype.def);
  990. { the second pass could change the location of left }
  991. { if it is a register variable, so we've to do }
  992. { this before the case statement }
  993. if left.location.loc<>LOC_JUMP then
  994. secondpass(left);
  995. case left.location.loc of
  996. LOC_JUMP :
  997. begin
  998. location_reset(location,LOC_JUMP,OS_NO);
  999. hl:=truelabel;
  1000. truelabel:=falselabel;
  1001. falselabel:=hl;
  1002. secondpass(left);
  1003. maketojumpbool(exprasmlist,left,lr_load_regvars);
  1004. hl:=truelabel;
  1005. truelabel:=falselabel;
  1006. falselabel:=hl;
  1007. end;
  1008. LOC_FLAGS :
  1009. begin
  1010. location_release(exprasmlist,left.location);
  1011. location_reset(location,LOC_FLAGS,OS_NO);
  1012. location.resflags:=flagsinvers[left.location.resflags];
  1013. end;
  1014. LOC_CONSTANT,
  1015. LOC_REGISTER,
  1016. LOC_CREGISTER,
  1017. LOC_REFERENCE,
  1018. LOC_CREFERENCE :
  1019. begin
  1020. location_force_reg(exprasmlist,left.location,def_cgsize(resulttype.def),true);
  1021. emit_reg_reg(A_TEST,opsize,left.location.register,left.location.register);
  1022. location_release(exprasmlist,left.location);
  1023. location_reset(location,LOC_FLAGS,OS_NO);
  1024. location.resflags:=F_E;
  1025. end;
  1026. else
  1027. internalerror(200203224);
  1028. end;
  1029. end
  1030. {$ifdef SUPPORT_MMX}
  1031. else
  1032. if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
  1033. begin
  1034. secondpass(left);
  1035. location_reset(location,LOC_MMXREGISTER,OS_NO);
  1036. { prepare EDI }
  1037. r.enum:=R_INTREGISTER;
  1038. r.number:=NR_EDI;
  1039. r2.enum:=R_MM7;
  1040. rg.getexplicitregisterint(exprasmlist,NR_EDI);
  1041. emit_const_reg(A_MOV,S_L,longint($ffffffff),r);
  1042. { load operand }
  1043. case left.location.loc of
  1044. LOC_MMXREGISTER:
  1045. location_copy(location,left.location);
  1046. LOC_CMMXREGISTER:
  1047. begin
  1048. location.register:=rg.getregistermm(exprasmlist);
  1049. emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
  1050. end;
  1051. LOC_REFERENCE,
  1052. LOC_CREFERENCE:
  1053. begin
  1054. location_release(exprasmlist,left.location);
  1055. location.register:=rg.getregistermm(exprasmlist);
  1056. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,location.register);
  1057. end;
  1058. end;
  1059. { load mask }
  1060. emit_reg_reg(A_MOVD,S_NO,r,r2);
  1061. rg.ungetregisterint(exprasmlist,r);
  1062. { lower 32 bit }
  1063. emit_reg_reg(A_PXOR,S_D,r2,location.register);
  1064. { shift mask }
  1065. emit_const_reg(A_PSLLQ,S_NO,32,r2);
  1066. { higher 32 bit }
  1067. emit_reg_reg(A_PXOR,S_D,r2,location.register);
  1068. end
  1069. {$endif SUPPORT_MMX}
  1070. else if is_64bitint(left.resulttype.def) then
  1071. begin
  1072. secondpass(left);
  1073. location_copy(location,left.location);
  1074. location_force_reg(exprasmlist,location,OS_64,false);
  1075. emit_reg(A_NOT,S_L,location.registerlow);
  1076. emit_reg(A_NOT,S_L,location.registerhigh);
  1077. end
  1078. else
  1079. begin
  1080. secondpass(left);
  1081. location_copy(location,left.location);
  1082. location_force_reg(exprasmlist,location,def_cgsize(resulttype.def),false);
  1083. opsize:=def_opsize(resulttype.def);
  1084. emit_reg(A_NOT,opsize,location.register);
  1085. end;
  1086. end;
  1087. begin
  1088. cmoddivnode:=ti386moddivnode;
  1089. cshlshrnode:=ti386shlshrnode;
  1090. cunaryminusnode:=ti386unaryminusnode;
  1091. cnotnode:=ti386notnode;
  1092. end.
  1093. {
  1094. $Log$
  1095. Revision 1.48 2003-03-28 19:16:57 peter
  1096. * generic constructor working for i386
  1097. * remove fixed self register
  1098. * esi added as address register for i386
  1099. Revision 1.47 2003/03/08 20:36:41 daniel
  1100. + Added newra version of Ti386shlshrnode
  1101. + Added interference graph construction code
  1102. Revision 1.46 2003/03/08 13:59:17 daniel
  1103. * Work to handle new register notation in ag386nsm
  1104. + Added newra version of Ti386moddivnode
  1105. Revision 1.45 2003/02/19 22:00:15 daniel
  1106. * Code generator converted to new register notation
  1107. - Horribily outdated todo.txt removed
  1108. Revision 1.44 2003/01/13 18:37:44 daniel
  1109. * Work on register conversion
  1110. Revision 1.43 2003/01/13 14:54:34 daniel
  1111. * Further work to convert codegenerator register convention;
  1112. internalerror bug fixed.
  1113. Revision 1.42 2003/01/08 18:43:57 daniel
  1114. * Tregister changed into a record
  1115. Revision 1.41 2002/11/25 17:43:26 peter
  1116. * splitted defbase in defutil,symutil,defcmp
  1117. * merged isconvertable and is_equal into compare_defs(_ext)
  1118. * made operator search faster by walking the list only once
  1119. Revision 1.40 2002/09/07 15:25:10 peter
  1120. * old logs removed and tabs fixed
  1121. Revision 1.39 2002/08/15 15:15:55 carl
  1122. * jmpbuf size allocation for exceptions is now cpu specific (as it should)
  1123. * more generic nodes for maths
  1124. * several fixes for better m68k support
  1125. Revision 1.38 2002/08/14 19:18:16 carl
  1126. * bugfix of unaryminus node with left LOC_CREGISTER
  1127. Revision 1.37 2002/08/12 15:08:42 carl
  1128. + stab register indexes for powerpc (moved from gdb to cpubase)
  1129. + tprocessor enumeration moved to cpuinfo
  1130. + linker in target_info is now a class
  1131. * many many updates for m68k (will soon start to compile)
  1132. - removed some ifdef or correct them for correct cpu
  1133. Revision 1.36 2002/08/11 14:32:30 peter
  1134. * renamed current_library to objectlibrary
  1135. Revision 1.35 2002/08/11 13:24:17 peter
  1136. * saving of asmsymbols in ppu supported
  1137. * asmsymbollist global is removed and moved into a new class
  1138. tasmlibrarydata that will hold the info of a .a file which
  1139. corresponds with a single module. Added librarydata to tmodule
  1140. to keep the library info stored for the module. In the future the
  1141. objectfiles will also be stored to the tasmlibrarydata class
  1142. * all getlabel/newasmsymbol and friends are moved to the new class
  1143. Revision 1.34 2002/08/02 07:44:31 jonas
  1144. * made assigned() handling generic
  1145. * add nodes now can also evaluate constant expressions at compile time
  1146. that contain nil nodes
  1147. Revision 1.33 2002/07/20 11:58:02 florian
  1148. * types.pas renamed to defbase.pas because D6 contains a types
  1149. unit so this would conflicts if D6 programms are compiled
  1150. + Willamette/SSE2 instructions to assembler added
  1151. Revision 1.32 2002/07/01 18:46:33 peter
  1152. * internal linker
  1153. * reorganized aasm layer
  1154. Revision 1.31 2002/05/18 13:34:25 peter
  1155. * readded missing revisions
  1156. Revision 1.30 2002/05/16 19:46:51 carl
  1157. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1158. + try to fix temp allocation (still in ifdef)
  1159. + generic constructor calls
  1160. + start of tassembler / tmodulebase class cleanup
  1161. Revision 1.28 2002/05/13 19:54:38 peter
  1162. * removed n386ld and n386util units
  1163. * maybe_save/maybe_restore added instead of the old maybe_push
  1164. Revision 1.27 2002/05/12 16:53:17 peter
  1165. * moved entry and exitcode to ncgutil and cgobj
  1166. * foreach gets extra argument for passing local data to the
  1167. iterator function
  1168. * -CR checks also class typecasts at runtime by changing them
  1169. into as
  1170. * fixed compiler to cycle with the -CR option
  1171. * fixed stabs with elf writer, finally the global variables can
  1172. be watched
  1173. * removed a lot of routines from cga unit and replaced them by
  1174. calls to cgobj
  1175. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1176. u32bit then the other is typecasted also to u32bit without giving
  1177. a rangecheck warning/error.
  1178. * fixed pascal calling method with reversing also the high tree in
  1179. the parast, detected by tcalcst3 test
  1180. Revision 1.26 2002/04/04 19:06:12 peter
  1181. * removed unused units
  1182. * use tlocation.size in cg.a_*loc*() routines
  1183. Revision 1.25 2002/04/02 17:11:36 peter
  1184. * tlocation,treference update
  1185. * LOC_CONSTANT added for better constant handling
  1186. * secondadd splitted in multiple routines
  1187. * location_force_reg added for loading a location to a register
  1188. of a specified size
  1189. * secondassignment parses now first the right and then the left node
  1190. (this is compatible with Kylix). This saves a lot of push/pop especially
  1191. with string operations
  1192. * adapted some routines to use the new cg methods
  1193. Revision 1.24 2002/03/31 20:26:39 jonas
  1194. + a_loadfpu_* and a_loadmm_* methods in tcg
  1195. * register allocation is now handled by a class and is mostly processor
  1196. independent (+rgobj.pas and i386/rgcpu.pas)
  1197. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1198. * some small improvements and fixes to the optimizer
  1199. * some register allocation fixes
  1200. * some fpuvaroffset fixes in the unary minus node
  1201. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1202. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1203. also better optimizable)
  1204. * fixed and optimized register saving/restoring for new/dispose nodes
  1205. * LOC_FPU locations now also require their "register" field to be set to
  1206. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1207. - list field removed of the tnode class because it's not used currently
  1208. and can cause hard-to-find bugs
  1209. Revision 1.23 2002/03/04 19:10:14 peter
  1210. * removed compiler warnings
  1211. }