n386mat.pas 43 KB

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