n386mat.pas 49 KB

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