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