n386mat.pas 53 KB

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