n386mat.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  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,ncgutil;
  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:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  304. hregisterhigh:=getregisterint;
  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:=getregisterint;
  314. hregisterhigh:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  672. location.registerhigh:=getregisterint;
  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:=getregisterint;
  680. location.registerhigh:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  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:=getregisterint;
  894. location.registerhigh:=getregisterint;
  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:=getregisterint;
  904. location.registerhigh:=getregisterint;
  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.22 2001-12-30 17:24:47 jonas
  951. * range checking is now processor independent (part in cgobj, part in cg64f32) and should work correctly again (it needed some changes after the changes of the low and high of tordef's to int64) * maketojumpbool() is now processor independent (in ncgutil) * getregister32 is now called getregisterint
  952. Revision 1.21 2001/12/29 15:27:24 jonas
  953. * made 'mod powerof2' -> 'and' optimization processor independent
  954. Revision 1.20 2001/12/27 15:33:58 jonas
  955. * fixed fpuregister counting errors ("merged")
  956. Revision 1.19 2001/12/07 13:03:49 jonas
  957. * fixed web bug 1716
  958. Revision 1.18 2001/12/04 15:57:28 jonas
  959. * never generate any "shll/shrl $0,%reg" anymore
  960. Revision 1.17 2001/12/02 16:19:17 jonas
  961. * less unnecessary regvar loading with if-statements
  962. Revision 1.16 2001/09/05 15:22:10 jonas
  963. * made multiplying, dividing and mod'ing of int64 and qword processor
  964. independent with compilerprocs (+ small optimizations by using shift/and
  965. where possible)
  966. Revision 1.15 2001/08/29 12:03:23 jonas
  967. * fixed wrong regalloc info around FPC_MUL/DIV/MOD_INT64/QWORD calls
  968. * fixed partial result overwriting with the above calls too
  969. Revision 1.14 2001/08/26 13:37:00 florian
  970. * some cg reorganisation
  971. * some PPC updates
  972. Revision 1.13 2001/04/13 01:22:19 peter
  973. * symtable change to classes
  974. * range check generation and errors fixed, make cycle DEBUG=1 works
  975. * memory leaks fixed
  976. Revision 1.12 2001/04/04 22:37:06 peter
  977. * fix for not with no 32bit values
  978. Revision 1.11 2001/04/02 21:20:38 peter
  979. * resulttype rewrite
  980. Revision 1.10 2001/02/03 12:52:34 jonas
  981. * fixed web bug 1383
  982. Revision 1.9 2000/12/07 17:19:46 jonas
  983. * new constant handling: from now on, hex constants >$7fffffff are
  984. parsed as unsigned constants (otherwise, $80000000 got sign extended
  985. and became $ffffffff80000000), all constants in the longint range
  986. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  987. are cardinals and the rest are int64's.
  988. * added lots of longint typecast to prevent range check errors in the
  989. compiler and rtl
  990. * type casts of symbolic ordinal constants are now preserved
  991. * fixed bug where the original resulttype.def wasn't restored correctly
  992. after doing a 64bit rangecheck
  993. Revision 1.8 2000/12/05 11:44:33 jonas
  994. + new integer regvar handling, should be much more efficient
  995. Revision 1.7 2000/11/29 00:30:48 florian
  996. * unused units removed from uses clause
  997. * some changes for widestrings
  998. Revision 1.6 2000/11/20 14:05:50 jonas
  999. * fixed bug in my changes to fix the regalloc info for div/mod ("merged")
  1000. Revision 1.5 2000/10/31 22:02:56 peter
  1001. * symtable splitted, no real code changes
  1002. Revision 1.4 2000/10/19 16:26:52 jonas
  1003. * fixed wrong regalloc info for secondmoddiv ("merged", also small
  1004. correction made afterwards in fixes branch)
  1005. Revision 1.3 2000/10/17 15:41:48 jonas
  1006. * fixed stupid error in previous commit :/
  1007. Revision 1.1 2000/10/15 09:33:32 peter
  1008. * moved n386*.pas to i386/ cpu_target dir
  1009. Revision 1.4 2000/10/14 10:14:49 peter
  1010. * moehrendorf oct 2000 rewrite
  1011. Revision 1.3 2000/09/30 16:08:45 peter
  1012. * more cg11 updates
  1013. Revision 1.2 2000/09/24 15:06:18 peter
  1014. * use defines.inc
  1015. Revision 1.1 2000/09/22 22:24:37 florian
  1016. * initial revision
  1017. }