n386mat.pas 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.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. end;
  30. ti386unaryminusnode = class(tunaryminusnode)
  31. function pass_1 : tnode;override;
  32. procedure pass_2;override;
  33. end;
  34. ti386notnode = class(tnotnode)
  35. procedure pass_2;override;
  36. end;
  37. implementation
  38. uses
  39. globtype,systems,
  40. cutils,verbose,globals,
  41. symconst,symdef,aasm,types,
  42. cgbase,temp_gen,pass_1,pass_2,
  43. ncon,
  44. cpubase,
  45. cga,tgcpu,n386util;
  46. {*****************************************************************************
  47. TI386MODDIVNODE
  48. *****************************************************************************}
  49. procedure ti386moddivnode.pass_2;
  50. var
  51. unusedregisters : tregisterset;
  52. usablecount, regstopush : byte;
  53. hreg1 : tregister;
  54. hreg2 : tregister;
  55. shrdiv, andmod, pushed,popeax,popedx : boolean;
  56. power : longint;
  57. hl : tasmlabel;
  58. hloc : tlocation;
  59. pushedreg : tpushed;
  60. typename,opname : string[6];
  61. begin
  62. shrdiv := false;
  63. andmod := false;
  64. secondpass(left);
  65. pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
  66. secondpass(right);
  67. if pushed then
  68. restore(left,is_64bitint(left.resulttype.def));
  69. set_location(location,left.location);
  70. if is_64bitint(resulttype.def) then
  71. begin
  72. { should be handled in pass_1 (JM) }
  73. internalerror(200109052);
  74. end
  75. else
  76. begin
  77. { put numerator in register }
  78. if left.location.loc<>LOC_REGISTER then
  79. begin
  80. if left.location.loc=LOC_CREGISTER then
  81. begin
  82. hreg1:=getregister32;
  83. emit_reg_reg(A_MOV,S_L,left.location.register,hreg1);
  84. end
  85. else
  86. begin
  87. del_reference(left.location.reference);
  88. hreg1:=getregister32;
  89. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  90. hreg1);
  91. end;
  92. clear_location(left.location);
  93. left.location.loc:=LOC_REGISTER;
  94. left.location.register:=hreg1;
  95. end
  96. else hreg1:=left.location.register;
  97. if (nodetype=divn) and (right.nodetype=ordconstn) and
  98. ispowerof2(tordconstnode(right).value,power) then
  99. Begin
  100. shrdiv := true;
  101. {for signed numbers, the numerator must be adjusted before the
  102. shift instruction, but not wih unsigned numbers! Otherwise,
  103. "Cardinal($ffffffff) div 16" overflows! (JM)}
  104. If is_signed(left.resulttype.def) Then
  105. Begin
  106. If (aktOptProcessor <> class386) and
  107. not(CS_LittleSize in aktglobalswitches) then
  108. { use a sequence without jumps, saw this in
  109. comp.compilers (JM) }
  110. begin
  111. { no jumps, but more operations }
  112. if (hreg1 = R_EAX) and
  113. (R_EDX in unused) then
  114. begin
  115. hreg2 := getexplicitregister32(R_EDX);
  116. emit_none(A_CDQ,S_NO);
  117. end
  118. else
  119. begin
  120. getexplicitregister32(R_EDI);
  121. hreg2 := R_EDI;
  122. emit_reg_reg(A_MOV,S_L,hreg1,R_EDI);
  123. { if the left value is signed, R_EDI := $ffffffff,
  124. otherwise 0 }
  125. emit_const_reg(A_SAR,S_L,31,R_EDI);
  126. { if signed, R_EDI := right value-1, otherwise 0 }
  127. end;
  128. emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg2);
  129. { add to the left value }
  130. emit_reg_reg(A_ADD,S_L,hreg2,hreg1);
  131. { release EDX if we used it }
  132. { also releas EDI }
  133. ungetregister32(hreg2);
  134. { do the shift }
  135. emit_const_reg(A_SAR,S_L,power,hreg1);
  136. end
  137. else
  138. begin
  139. { a jump, but less operations }
  140. emit_reg_reg(A_TEST,S_L,hreg1,hreg1);
  141. getlabel(hl);
  142. emitjmp(C_NS,hl);
  143. if power=1 then
  144. emit_reg(A_INC,S_L,hreg1)
  145. else
  146. emit_const_reg(A_ADD,S_L,tordconstnode(right).value-1,hreg1);
  147. emitlab(hl);
  148. emit_const_reg(A_SAR,S_L,power,hreg1);
  149. end
  150. End
  151. Else
  152. emit_const_reg(A_SHR,S_L,power,hreg1);
  153. End
  154. else
  155. if (nodetype=modn) and (right.nodetype=ordconstn) and
  156. ispowerof2(tordconstnode(right).value,power) and Not(is_signed(left.resulttype.def)) Then
  157. {is there a similar trick for MOD'ing signed numbers? (JM)}
  158. Begin
  159. emit_const_reg(A_AND,S_L,tordconstnode(right).value-1,hreg1);
  160. andmod := true;
  161. End
  162. else
  163. begin
  164. { bring denominator to EDI }
  165. { EDI is always free, it's }
  166. { only used for temporary }
  167. { purposes }
  168. getexplicitregister32(R_EDI);
  169. if (right.location.loc<>LOC_REGISTER) and
  170. (right.location.loc<>LOC_CREGISTER) then
  171. begin
  172. del_reference(right.location.reference);
  173. left.location.loc:=LOC_REGISTER;
  174. emit_ref_reg(A_MOV,S_L,newreference(right.location.reference),R_EDI);
  175. end
  176. else
  177. begin
  178. emit_reg_reg(A_MOV,S_L,right.location.register,R_EDI);
  179. ungetregister32(right.location.register);
  180. end;
  181. popedx:=false;
  182. popeax:=false;
  183. if hreg1=R_EDX then
  184. begin
  185. if not(R_EAX in unused) then
  186. begin
  187. emit_reg(A_PUSH,S_L,R_EAX);
  188. popeax:=true;
  189. end
  190. else
  191. getexplicitregister32(R_EAX);
  192. emit_reg_reg(A_MOV,S_L,R_EDX,R_EAX);
  193. end
  194. else
  195. begin
  196. if not(R_EDX in unused) then
  197. begin
  198. emit_reg(A_PUSH,S_L,R_EDX);
  199. popedx:=true;
  200. end
  201. else
  202. getexplicitregister32(R_EDX);
  203. if hreg1<>R_EAX then
  204. begin
  205. if not(R_EAX in unused) then
  206. begin
  207. emit_reg(A_PUSH,S_L,R_EAX);
  208. popeax:=true;
  209. end
  210. else
  211. getexplicitregister32(R_EAX);
  212. emit_reg_reg(A_MOV,S_L,hreg1,R_EAX);
  213. end;
  214. end;
  215. { sign extension depends on the left type }
  216. if torddef(left.resulttype.def).typ=u32bit then
  217. emit_reg_reg(A_XOR,S_L,R_EDX,R_EDX)
  218. else
  219. emit_none(A_CDQ,S_NO);
  220. { division depends on the right type }
  221. if torddef(right.resulttype.def).typ=u32bit then
  222. emit_reg(A_DIV,S_L,R_EDI)
  223. else
  224. emit_reg(A_IDIV,S_L,R_EDI);
  225. ungetregister32(R_EDI);
  226. if nodetype=divn then
  227. begin
  228. { if result register is busy then copy }
  229. if popeax then
  230. begin
  231. if hreg1=R_EAX then
  232. internalerror(112);
  233. emit_reg_reg(A_MOV,S_L,R_EAX,hreg1)
  234. end
  235. else
  236. if hreg1<>R_EAX then
  237. Begin
  238. ungetregister32(hreg1);
  239. { no need to allocate eax, that's already done before }
  240. { the div (JM) }
  241. hreg1 := R_EAX;
  242. end;
  243. if not popedx and (hreg1 <> R_EDX) then
  244. ungetregister(R_EDX);
  245. end
  246. else
  247. {if we did the mod by an "and", the result is in hreg1 and
  248. EDX certainly hasn't been pushed (JM)}
  249. if not(andmod) Then
  250. begin
  251. if popedx then
  252. {the mod was done by an (i)div (so the result is now in
  253. edx), but edx was occupied prior to the division, so
  254. move the result into a safe place (JM)}
  255. emit_reg_reg(A_MOV,S_L,R_EDX,hreg1)
  256. else
  257. Begin
  258. if hreg1 <> R_EDX then
  259. ungetregister32(hreg1);
  260. hreg1 := R_EDX
  261. End;
  262. if not popeax and (hreg1 <> R_EAX)then
  263. ungetregister(R_EAX);
  264. end;
  265. if popeax then
  266. emit_reg(A_POP,S_L,R_EAX);
  267. if popedx then
  268. emit_reg(A_POP,S_L,R_EDX);
  269. end;
  270. If not(andmod or shrdiv) then
  271. {andmod and shrdiv only use hreg1 (which is already in usedinproc,
  272. since it was acquired with getregister), the others also use both
  273. EAX and EDX (JM)}
  274. Begin
  275. usedinproc:=usedinproc or ($80 shr byte(R_EAX));
  276. usedinproc:=usedinproc or ($80 shr byte(R_EDX));
  277. End;
  278. clear_location(location);
  279. location.loc:=LOC_REGISTER;
  280. location.register:=hreg1;
  281. end;
  282. end;
  283. {*****************************************************************************
  284. TI386SHLRSHRNODE
  285. *****************************************************************************}
  286. procedure ti386shlshrnode.pass_2;
  287. var
  288. hregister1,hregister2,hregister3,
  289. hregisterhigh,hregisterlow : tregister;
  290. pushed,popecx : boolean;
  291. op : tasmop;
  292. l1,l2,l3 : tasmlabel;
  293. begin
  294. popecx:=false;
  295. secondpass(left);
  296. pushed:=maybe_push(right.registers32,left,is_64bitint(left.resulttype.def));
  297. secondpass(right);
  298. if pushed then
  299. restore(left,is_64bitint(left.resulttype.def));
  300. if is_64bitint(left.resulttype.def) then
  301. begin
  302. { load left operator in a register }
  303. if left.location.loc<>LOC_REGISTER then
  304. begin
  305. if left.location.loc=LOC_CREGISTER then
  306. begin
  307. hregisterlow:=getregister32;
  308. hregisterhigh:=getregister32;
  309. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  310. hregisterlow);
  311. emit_reg_reg(A_MOV,S_L,left.location.registerhigh,
  312. hregisterlow);
  313. end
  314. else
  315. begin
  316. del_reference(left.location.reference);
  317. hregisterlow:=getregister32;
  318. hregisterhigh:=getregister32;
  319. emit_mov_ref_reg64(left.location.reference,
  320. hregisterlow,
  321. hregisterhigh);
  322. end;
  323. end
  324. else
  325. begin
  326. hregisterlow:=left.location.registerlow;
  327. hregisterhigh:=left.location.registerhigh;
  328. end;
  329. { shifting by a constant directly coded: }
  330. if (right.nodetype=ordconstn) then
  331. begin
  332. { shrd/shl works only for values <=31 !! }
  333. if tordconstnode(right).value>31 then
  334. begin
  335. if nodetype=shln then
  336. begin
  337. emit_reg_reg(A_XOR,S_L,hregisterhigh,
  338. hregisterhigh);
  339. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  340. hregisterlow);
  341. end
  342. else
  343. begin
  344. emit_reg_reg(A_XOR,S_L,hregisterlow,
  345. hregisterlow);
  346. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  347. hregisterhigh);
  348. end;
  349. location.registerhigh:=hregisterlow;
  350. location.registerlow:=hregisterhigh;
  351. end
  352. else
  353. begin
  354. if nodetype=shln then
  355. begin
  356. emit_const_reg_reg(A_SHLD,S_L,tordconstnode(right).value and 31,
  357. hregisterlow,hregisterhigh);
  358. emit_const_reg(A_SHL,S_L,tordconstnode(right).value and 31,
  359. hregisterlow);
  360. end
  361. else
  362. begin
  363. emit_const_reg_reg(A_SHRD,S_L,tordconstnode(right).value and 31,
  364. hregisterhigh,hregisterlow);
  365. emit_const_reg(A_SHR,S_L,tordconstnode(right).value and 31,
  366. hregisterhigh);
  367. end;
  368. location.registerlow:=hregisterlow;
  369. location.registerhigh:=hregisterhigh;
  370. end;
  371. location.loc:=LOC_REGISTER;
  372. end
  373. else
  374. begin
  375. { load right operators in a register }
  376. if right.location.loc<>LOC_REGISTER then
  377. begin
  378. if right.location.loc=LOC_CREGISTER then
  379. begin
  380. hregister2:=getexplicitregister32(R_ECX);
  381. emit_reg_reg(A_MOV,S_L,right.location.register,
  382. hregister2);
  383. end
  384. else
  385. begin
  386. del_reference(right.location.reference);
  387. hregister2:=getexplicitregister32(R_ECX);
  388. emit_ref_reg(A_MOV,S_L,newreference(right.location.reference),
  389. hregister2);
  390. end;
  391. end
  392. else
  393. hregister2:=right.location.register;
  394. { left operator is already in a register }
  395. { hence are both in a register }
  396. { is it in the case ECX ? }
  397. if (hregisterlow=R_ECX) then
  398. begin
  399. { then only swap }
  400. emit_reg_reg(A_XCHG,S_L,hregisterlow,hregister2);
  401. hregister3:=hregisterlow;
  402. hregisterlow:=hregister2;
  403. hregister2:=hregister3;
  404. end
  405. else if (hregisterhigh=R_ECX) then
  406. begin
  407. { then only swap }
  408. emit_reg_reg(A_XCHG,S_L,hregisterhigh,hregister2);
  409. hregister3:=hregisterhigh;
  410. hregisterhigh:=hregister2;
  411. hregister2:=hregister3;
  412. end
  413. { if second operator not in ECX ? }
  414. else if (hregister2<>R_ECX) then
  415. begin
  416. { ECX occupied then push it }
  417. if not (R_ECX in unused) then
  418. begin
  419. popecx:=true;
  420. emit_reg(A_PUSH,S_L,R_ECX);
  421. end
  422. else
  423. getexplicitregister32(R_ECX);
  424. emit_reg_reg(A_MOV,S_L,hregister2,R_ECX);
  425. end;
  426. if hregister2 <> R_ECX then
  427. ungetregister32(hregister2);
  428. { the damned shift instructions work only til a count of 32 }
  429. { so we've to do some tricks here }
  430. if nodetype=shln then
  431. begin
  432. getlabel(l1);
  433. getlabel(l2);
  434. getlabel(l3);
  435. emit_const_reg(A_CMP,S_L,64,R_ECX);
  436. emitjmp(C_L,l1);
  437. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  438. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  439. emitjmp(C_None,l3);
  440. emitlab(l1);
  441. emit_const_reg(A_CMP,S_L,32,R_ECX);
  442. emitjmp(C_L,l2);
  443. emit_const_reg(A_SUB,S_L,32,R_ECX);
  444. emit_reg_reg(A_SHL,S_L,R_CL,
  445. hregisterlow);
  446. emit_reg_reg(A_MOV,S_L,hregisterlow,hregisterhigh);
  447. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  448. emitjmp(C_None,l3);
  449. emitlab(l2);
  450. emit_reg_reg_reg(A_SHLD,S_L,R_CL,
  451. hregisterlow,hregisterhigh);
  452. emit_reg_reg(A_SHL,S_L,R_CL,
  453. hregisterlow);
  454. emitlab(l3);
  455. end
  456. else
  457. begin
  458. getlabel(l1);
  459. getlabel(l2);
  460. getlabel(l3);
  461. emit_const_reg(A_CMP,S_L,64,R_ECX);
  462. emitjmp(C_L,l1);
  463. emit_reg_reg(A_XOR,S_L,hregisterlow,hregisterlow);
  464. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  465. emitjmp(C_None,l3);
  466. emitlab(l1);
  467. emit_const_reg(A_CMP,S_L,32,R_ECX);
  468. emitjmp(C_L,l2);
  469. emit_const_reg(A_SUB,S_L,32,R_ECX);
  470. emit_reg_reg(A_SHR,S_L,R_CL,
  471. hregisterhigh);
  472. emit_reg_reg(A_MOV,S_L,hregisterhigh,hregisterlow);
  473. emit_reg_reg(A_XOR,S_L,hregisterhigh,hregisterhigh);
  474. emitjmp(C_None,l3);
  475. emitlab(l2);
  476. emit_reg_reg_reg(A_SHRD,S_L,R_CL,
  477. hregisterhigh,hregisterlow);
  478. emit_reg_reg(A_SHR,S_L,R_CL,
  479. hregisterhigh);
  480. emitlab(l3);
  481. end;
  482. { maybe put ECX back }
  483. if popecx then
  484. emit_reg(A_POP,S_L,R_ECX)
  485. else ungetregister32(R_ECX);
  486. location.registerlow:=hregisterlow;
  487. location.registerhigh:=hregisterhigh;
  488. end;
  489. end
  490. else
  491. begin
  492. { load left operators in a register }
  493. if left.location.loc<>LOC_REGISTER then
  494. begin
  495. if left.location.loc=LOC_CREGISTER then
  496. begin
  497. hregister1:=getregister32;
  498. emit_reg_reg(A_MOV,S_L,left.location.register,
  499. hregister1);
  500. end
  501. else
  502. begin
  503. del_reference(left.location.reference);
  504. hregister1:=getregister32;
  505. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  506. hregister1);
  507. end;
  508. end
  509. else
  510. hregister1:=left.location.register;
  511. { determine operator }
  512. if nodetype=shln then
  513. op:=A_SHL
  514. else
  515. op:=A_SHR;
  516. { shifting by a constant directly coded: }
  517. if (right.nodetype=ordconstn) then
  518. begin
  519. { l shl 32 should 0 imho, but neither TP nor Delphi do it in this way (FK)
  520. if right.value<=31 then
  521. }
  522. emit_const_reg(op,S_L,tordconstnode(right).value and 31,
  523. hregister1);
  524. {
  525. else
  526. emit_reg_reg(A_XOR,S_L,hregister1,
  527. hregister1);
  528. }
  529. location.loc:=LOC_REGISTER;
  530. location.register:=hregister1;
  531. end
  532. else
  533. begin
  534. { load right operators in a register }
  535. if right.location.loc<>LOC_REGISTER then
  536. begin
  537. if right.location.loc=LOC_CREGISTER then
  538. begin
  539. hregister2:=getexplicitregister32(R_ECX);
  540. emit_reg_reg(A_MOV,S_L,right.location.register,
  541. hregister2);
  542. end
  543. else
  544. begin
  545. del_reference(right.location.reference);
  546. hregister2:=getexplicitregister32(R_ECX);
  547. emit_ref_reg(A_MOV,S_L,newreference(right.location.reference),
  548. hregister2);
  549. end;
  550. end
  551. else
  552. hregister2:=right.location.register;
  553. { left operator is already in a register }
  554. { hence are both in a register }
  555. { is it in the case ECX ? }
  556. if (hregister1=R_ECX) then
  557. begin
  558. { then only swap }
  559. emit_reg_reg(A_XCHG,S_L,hregister1,hregister2);
  560. hregister3:=hregister1;
  561. hregister1:=hregister2;
  562. hregister2:=hregister3;
  563. end
  564. { if second operator not in ECX ? }
  565. else if (hregister2<>R_ECX) then
  566. begin
  567. { ECX occupied then push it }
  568. if not (R_ECX in unused) then
  569. begin
  570. popecx:=true;
  571. emit_reg(A_PUSH,S_L,R_ECX);
  572. end
  573. else
  574. getexplicitregister32(R_ECX);
  575. emit_reg_reg(A_MOV,S_L,hregister2,R_ECX);
  576. end;
  577. ungetregister32(hregister2);
  578. { right operand is in ECX }
  579. emit_reg_reg(op,S_L,R_CL,hregister1);
  580. { maybe ECX back }
  581. if popecx then
  582. emit_reg(A_POP,S_L,R_ECX)
  583. else
  584. ungetregister32(R_ECX);
  585. location.register:=hregister1;
  586. end;
  587. end;
  588. end;
  589. {*****************************************************************************
  590. TI386UNARYMINUSNODE
  591. *****************************************************************************}
  592. function ti386unaryminusnode.pass_1 : tnode;
  593. begin
  594. result:=nil;
  595. firstpass(left);
  596. if codegenerror then
  597. exit;
  598. registers32:=left.registers32;
  599. registersfpu:=left.registersfpu;
  600. {$ifdef SUPPORT_MMX}
  601. registersmmx:=left.registersmmx;
  602. {$endif SUPPORT_MMX}
  603. if (left.resulttype.def.deftype=floatdef) then
  604. begin
  605. location.loc:=LOC_FPU;
  606. end
  607. {$ifdef SUPPORT_MMX}
  608. else if (cs_mmx in aktlocalswitches) and
  609. is_mmx_able_array(left.resulttype.def) then
  610. begin
  611. if (left.location.loc<>LOC_MMXREGISTER) and
  612. (registersmmx<1) then
  613. registersmmx:=1;
  614. end
  615. {$endif SUPPORT_MMX}
  616. else if is_64bitint(left.resulttype.def) then
  617. begin
  618. if (left.location.loc<>LOC_REGISTER) and
  619. (registers32<2) then
  620. registers32:=2;
  621. location.loc:=LOC_REGISTER;
  622. end
  623. else if (left.resulttype.def.deftype=orddef) then
  624. begin
  625. if (left.location.loc<>LOC_REGISTER) and
  626. (registers32<1) then
  627. registers32:=1;
  628. location.loc:=LOC_REGISTER;
  629. end;
  630. end;
  631. procedure ti386unaryminusnode.pass_2;
  632. {$ifdef SUPPORT_MMX}
  633. procedure do_mmx_neg;
  634. var
  635. op : tasmop;
  636. begin
  637. location.loc:=LOC_MMXREGISTER;
  638. if cs_mmx_saturation in aktlocalswitches then
  639. case mmx_type(resulttype.def) of
  640. mmxs8bit:
  641. op:=A_PSUBSB;
  642. mmxu8bit:
  643. op:=A_PSUBUSB;
  644. mmxs16bit,mmxfixed16:
  645. op:=A_PSUBSW;
  646. mmxu16bit:
  647. op:=A_PSUBUSW;
  648. end
  649. else
  650. case mmx_type(resulttype.def) of
  651. mmxs8bit,mmxu8bit:
  652. op:=A_PSUBB;
  653. mmxs16bit,mmxu16bit,mmxfixed16:
  654. op:=A_PSUBW;
  655. mmxs32bit,mmxu32bit:
  656. op:=A_PSUBD;
  657. end;
  658. emit_reg_reg(op,S_NO,location.register,R_MM7);
  659. emit_reg_reg(A_MOVQ,S_NO,R_MM7,location.register);
  660. end;
  661. {$endif}
  662. begin
  663. if is_64bitint(left.resulttype.def) then
  664. begin
  665. secondpass(left);
  666. clear_location(location);
  667. location.loc:=LOC_REGISTER;
  668. case left.location.loc of
  669. LOC_REGISTER :
  670. begin
  671. location.registerlow:=left.location.registerlow;
  672. location.registerhigh:=left.location.registerhigh;
  673. end;
  674. LOC_CREGISTER :
  675. begin
  676. location.registerlow:=getregister32;
  677. location.registerhigh:=getregister32;
  678. emit_reg_reg(A_MOV,S_L,left.location.registerlow,location.registerlow);
  679. emit_reg_reg(A_MOV,S_L,left.location.registerhigh,location.registerhigh);
  680. end;
  681. LOC_REFERENCE,LOC_MEM :
  682. begin
  683. del_reference(left.location.reference);
  684. location.registerlow:=getregister32;
  685. location.registerhigh:=getregister32;
  686. emit_mov_ref_reg64(left.location.reference,
  687. location.registerlow,
  688. location.registerhigh);
  689. end;
  690. end;
  691. {
  692. emit_reg(A_NEG,S_L,location.registerlow);
  693. emit_const_reg(A_ADC,S_L,0,location.registerhigh);
  694. emit_reg(A_NEG,S_L,location.registerhigh);
  695. }
  696. emit_reg(A_NOT,S_L,location.registerhigh);
  697. emit_reg(A_NEG,S_L,location.registerlow);
  698. emit_const_reg(A_SBB,S_L,-1,location.registerhigh);
  699. end
  700. else
  701. begin
  702. secondpass(left);
  703. location.loc:=LOC_REGISTER;
  704. case left.location.loc of
  705. LOC_REGISTER:
  706. begin
  707. location.register:=left.location.register;
  708. emit_reg(A_NEG,S_L,location.register);
  709. end;
  710. LOC_CREGISTER:
  711. begin
  712. location.register:=getregister32;
  713. emit_reg_reg(A_MOV,S_L,location.register,
  714. location.register);
  715. emit_reg(A_NEG,S_L,location.register);
  716. end;
  717. {$ifdef SUPPORT_MMX}
  718. LOC_MMXREGISTER:
  719. begin
  720. set_location(location,left.location);
  721. emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
  722. do_mmx_neg;
  723. end;
  724. LOC_CMMXREGISTER:
  725. begin
  726. location.register:=getregistermmx;
  727. emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
  728. emit_reg_reg(A_MOVQ,S_NO,left.location.register,
  729. location.register);
  730. do_mmx_neg;
  731. end;
  732. {$endif SUPPORT_MMX}
  733. LOC_REFERENCE,LOC_MEM:
  734. begin
  735. del_reference(left.location.reference);
  736. if (left.resulttype.def.deftype=floatdef) then
  737. begin
  738. location.loc:=LOC_FPU;
  739. floatload(tfloatdef(left.resulttype.def).typ,
  740. left.location.reference);
  741. emit_none(A_FCHS,S_NO);
  742. end
  743. {$ifdef SUPPORT_MMX}
  744. else if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
  745. begin
  746. location.register:=getregistermmx;
  747. emit_reg_reg(A_PXOR,S_NO,R_MM7,R_MM7);
  748. emit_ref_reg(A_MOVQ,S_NO,
  749. newreference(left.location.reference),
  750. location.register);
  751. do_mmx_neg;
  752. end
  753. {$endif SUPPORT_MMX}
  754. else
  755. begin
  756. location.register:=getregister32;
  757. emit_ref_reg(A_MOV,S_L,
  758. newreference(left.location.reference),
  759. location.register);
  760. emit_reg(A_NEG,S_L,location.register);
  761. end;
  762. end;
  763. LOC_FPU:
  764. begin
  765. location.loc:=LOC_FPU;
  766. emit_none(A_FCHS,S_NO);
  767. end;
  768. LOC_CFPUREGISTER:
  769. begin
  770. emit_reg(A_FLD,S_NO,
  771. correct_fpuregister(left.location.register,fpuvaroffset));
  772. inc(fpuvaroffset);
  773. location.loc:=LOC_FPU;
  774. emit_none(A_FCHS,S_NO);
  775. end;
  776. end;
  777. end;
  778. { Here was a problem... }
  779. { Operand to be negated always }
  780. { seems to be converted to signed }
  781. { 32-bit before doing neg!! }
  782. { So this is useless... }
  783. { that's not true: -2^31 gives an overflow error if it is negaded (FK) }
  784. { emitoverflowcheck(p);}
  785. end;
  786. {*****************************************************************************
  787. TI386NOTNODE
  788. *****************************************************************************}
  789. procedure ti386notnode.pass_2;
  790. const
  791. flagsinvers : array[F_E..F_BE] of tresflags =
  792. (F_NE,F_E,F_LE,F_GE,F_L,F_G,F_NC,F_C,
  793. F_BE,F_B,F_AE,F_A);
  794. var
  795. hl : tasmlabel;
  796. opsize : topsize;
  797. begin
  798. if is_boolean(resulttype.def) then
  799. begin
  800. opsize:=def_opsize(resulttype.def);
  801. { the second pass could change the location of left }
  802. { if it is a register variable, so we've to do }
  803. { this before the case statement }
  804. if left.location.loc in [LOC_REFERENCE,LOC_MEM,
  805. LOC_FLAGS,LOC_REGISTER,LOC_CREGISTER] then
  806. secondpass(left);
  807. case left.location.loc of
  808. LOC_JUMP :
  809. begin
  810. hl:=truelabel;
  811. truelabel:=falselabel;
  812. falselabel:=hl;
  813. secondpass(left);
  814. maketojumpbool(left);
  815. hl:=truelabel;
  816. truelabel:=falselabel;
  817. falselabel:=hl;
  818. end;
  819. LOC_FLAGS :
  820. location.resflags:=flagsinvers[left.location.resflags];
  821. LOC_REGISTER :
  822. begin
  823. {location.register:=left.location.register;
  824. emit_const_reg(A_XOR,opsize,1,location.register);}
  825. location.loc:=LOC_FLAGS;
  826. location.resflags:=F_E;
  827. emit_reg_reg(A_TEST,opsize,
  828. left.location.register,left.location.register);
  829. ungetregister(left.location.register);
  830. end;
  831. LOC_CREGISTER :
  832. begin
  833. clear_location(location);
  834. location.loc:=LOC_REGISTER;
  835. location.register:=def_getreg(resulttype.def);
  836. emit_reg_reg(A_MOV,opsize,left.location.register,location.register);
  837. emit_reg_reg(A_TEST,opsize,location.register,location.register);
  838. ungetregister(location.register);
  839. location.loc:=LOC_FLAGS;
  840. location.resflags:=F_E;
  841. end;
  842. LOC_REFERENCE,
  843. LOC_MEM :
  844. begin
  845. clear_location(location);
  846. location.loc:=LOC_REGISTER;
  847. del_reference(left.location.reference);
  848. { this was placed before del_ref => internaalerror(10) }
  849. location.register:=def_getreg(resulttype.def);
  850. emit_ref_reg(A_MOV,opsize,
  851. newreference(left.location.reference),location.register);
  852. emit_reg_reg(A_TEST,opsize,location.register,location.register);
  853. ungetregister(location.register);
  854. location.loc:=LOC_FLAGS;
  855. location.resflags:=F_E;
  856. end;
  857. end;
  858. end
  859. {$ifdef SUPPORT_MMX}
  860. else
  861. if (cs_mmx in aktlocalswitches) and is_mmx_able_array(left.resulttype.def) then
  862. begin
  863. secondpass(left);
  864. location.loc:=LOC_MMXREGISTER;
  865. { prepare EDI }
  866. getexplicitregister32(R_EDI);
  867. emit_const_reg(A_MOV,S_L,longint($ffffffff),R_EDI);
  868. { load operand }
  869. case left.location.loc of
  870. LOC_MMXREGISTER:
  871. set_location(location,left.location);
  872. LOC_CMMXREGISTER:
  873. begin
  874. location.register:=getregistermmx;
  875. emit_reg_reg(A_MOVQ,S_NO,left.location.register,location.register);
  876. end;
  877. LOC_REFERENCE,LOC_MEM:
  878. begin
  879. del_reference(left.location.reference);
  880. location.register:=getregistermmx;
  881. emit_ref_reg(A_MOVQ,S_NO,
  882. newreference(left.location.reference),location.register);
  883. end;
  884. end;
  885. { load mask }
  886. emit_reg_reg(A_MOVD,S_NO,R_EDI,R_MM7);
  887. ungetregister32(R_EDI);
  888. { lower 32 bit }
  889. emit_reg_reg(A_PXOR,S_D,R_MM7,location.register);
  890. { shift mask }
  891. emit_const_reg(A_PSLLQ,S_NO,32,R_MM7);
  892. { higher 32 bit }
  893. emit_reg_reg(A_PXOR,S_D,R_MM7,location.register);
  894. end
  895. {$endif SUPPORT_MMX}
  896. else if is_64bitint(left.resulttype.def) then
  897. begin
  898. secondpass(left);
  899. clear_location(location);
  900. location.loc:=LOC_REGISTER;
  901. case left.location.loc of
  902. LOC_REGISTER :
  903. begin
  904. location.registerlow:=left.location.registerlow;
  905. location.registerhigh:=left.location.registerhigh;
  906. emit_reg(A_NOT,S_L,location.registerlow);
  907. emit_reg(A_NOT,S_L,location.registerhigh);
  908. end;
  909. LOC_CREGISTER :
  910. begin
  911. location.registerlow:=getregister32;
  912. location.registerhigh:=getregister32;
  913. emit_reg_reg(A_MOV,S_L,left.location.registerlow,location.registerlow);
  914. emit_reg_reg(A_MOV,S_L,left.location.registerhigh,location.registerhigh);
  915. emit_reg(A_NOT,S_L,location.registerlow);
  916. emit_reg(A_NOT,S_L,location.registerhigh);
  917. end;
  918. LOC_REFERENCE,LOC_MEM :
  919. begin
  920. del_reference(left.location.reference);
  921. location.registerlow:=getregister32;
  922. location.registerhigh:=getregister32;
  923. emit_mov_ref_reg64(left.location.reference,
  924. location.registerlow,
  925. location.registerhigh);
  926. emit_reg(A_NOT,S_L,location.registerlow);
  927. emit_reg(A_NOT,S_L,location.registerhigh);
  928. end;
  929. end;
  930. end
  931. else
  932. begin
  933. secondpass(left);
  934. clear_location(location);
  935. opsize:=def_opsize(resulttype.def);
  936. location.loc:=LOC_REGISTER;
  937. case left.location.loc of
  938. LOC_REGISTER :
  939. begin
  940. location.register:=left.location.register;
  941. emit_reg(A_NOT,opsize,location.register);
  942. end;
  943. LOC_CREGISTER :
  944. begin
  945. location.register:=def_getreg(resulttype.def);
  946. emit_reg_reg(A_MOV,opsize,left.location.register,location.register);
  947. emit_reg(A_NOT,opsize,location.register);
  948. end;
  949. LOC_REFERENCE,LOC_MEM :
  950. begin
  951. del_reference(left.location.reference);
  952. location.register:=def_getreg(resulttype.def);
  953. emit_ref_reg(A_MOV,opsize,
  954. newreference(left.location.reference),location.register);
  955. emit_reg(A_NOT,opsize,location.register);
  956. end;
  957. end;
  958. end;
  959. end;
  960. begin
  961. cmoddivnode:=ti386moddivnode;
  962. cshlshrnode:=ti386shlshrnode;
  963. cunaryminusnode:=ti386unaryminusnode;
  964. cnotnode:=ti386notnode;
  965. end.
  966. {
  967. $Log$
  968. Revision 1.16 2001-09-05 15:22:10 jonas
  969. * made multiplying, dividing and mod'ing of int64 and qword processor
  970. independent with compilerprocs (+ small optimizations by using shift/and
  971. where possible)
  972. Revision 1.15 2001/08/29 12:03:23 jonas
  973. * fixed wrong regalloc info around FPC_MUL/DIV/MOD_INT64/QWORD calls
  974. * fixed partial result overwriting with the above calls too
  975. Revision 1.14 2001/08/26 13:37:00 florian
  976. * some cg reorganisation
  977. * some PPC updates
  978. Revision 1.13 2001/04/13 01:22:19 peter
  979. * symtable change to classes
  980. * range check generation and errors fixed, make cycle DEBUG=1 works
  981. * memory leaks fixed
  982. Revision 1.12 2001/04/04 22:37:06 peter
  983. * fix for not with no 32bit values
  984. Revision 1.11 2001/04/02 21:20:38 peter
  985. * resulttype rewrite
  986. Revision 1.10 2001/02/03 12:52:34 jonas
  987. * fixed web bug 1383
  988. Revision 1.9 2000/12/07 17:19:46 jonas
  989. * new constant handling: from now on, hex constants >$7fffffff are
  990. parsed as unsigned constants (otherwise, $80000000 got sign extended
  991. and became $ffffffff80000000), all constants in the longint range
  992. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  993. are cardinals and the rest are int64's.
  994. * added lots of longint typecast to prevent range check errors in the
  995. compiler and rtl
  996. * type casts of symbolic ordinal constants are now preserved
  997. * fixed bug where the original resulttype.def wasn't restored correctly
  998. after doing a 64bit rangecheck
  999. Revision 1.8 2000/12/05 11:44:33 jonas
  1000. + new integer regvar handling, should be much more efficient
  1001. Revision 1.7 2000/11/29 00:30:48 florian
  1002. * unused units removed from uses clause
  1003. * some changes for widestrings
  1004. Revision 1.6 2000/11/20 14:05:50 jonas
  1005. * fixed bug in my changes to fix the regalloc info for div/mod ("merged")
  1006. Revision 1.5 2000/10/31 22:02:56 peter
  1007. * symtable splitted, no real code changes
  1008. Revision 1.4 2000/10/19 16:26:52 jonas
  1009. * fixed wrong regalloc info for secondmoddiv ("merged", also small
  1010. correction made afterwards in fixes branch)
  1011. Revision 1.3 2000/10/17 15:41:48 jonas
  1012. * fixed stupid error in previous commit :/
  1013. Revision 1.1 2000/10/15 09:33:32 peter
  1014. * moved n386*.pas to i386/ cpu_target dir
  1015. Revision 1.4 2000/10/14 10:14:49 peter
  1016. * moehrendorf oct 2000 rewrite
  1017. Revision 1.3 2000/09/30 16:08:45 peter
  1018. * more cg11 updates
  1019. Revision 1.2 2000/09/24 15:06:18 peter
  1020. * use defines.inc
  1021. Revision 1.1 2000/09/22 22:24:37 florian
  1022. * initial revision
  1023. }