n386add.pas 106 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318
  1. {
  2. $Id$
  3. Copyright (c) 2000 by Florian Klaempfl
  4. Code generation for add nodes on the i386
  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 n386add;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. nadd,cpubase;
  23. type
  24. ti386addnode = class(taddnode)
  25. procedure pass_2;override;
  26. function getresflags(unsigned : boolean) : tresflags;
  27. procedure SetResultLocation(cmpop,unsigned : boolean);
  28. procedure addstring;
  29. procedure addset;
  30. end;
  31. implementation
  32. uses
  33. globtype,systems,
  34. cutils,cobjects,verbose,globals,
  35. symconst,symtable,aasm,types,
  36. hcodegen,temp_gen,pass_2,
  37. cpuasm,
  38. node,ncon,nset,
  39. cgai386,n386util,tgeni386;
  40. function ti386addnode.getresflags(unsigned : boolean) : tresflags;
  41. begin
  42. if not(unsigned) then
  43. begin
  44. if nf_swaped in flags then
  45. case nodetype of
  46. equaln : getresflags:=F_E;
  47. unequaln : getresflags:=F_NE;
  48. ltn : getresflags:=F_G;
  49. lten : getresflags:=F_GE;
  50. gtn : getresflags:=F_L;
  51. gten : getresflags:=F_LE;
  52. end
  53. else
  54. case nodetype of
  55. equaln : getresflags:=F_E;
  56. unequaln : getresflags:=F_NE;
  57. ltn : getresflags:=F_L;
  58. lten : getresflags:=F_LE;
  59. gtn : getresflags:=F_G;
  60. gten : getresflags:=F_GE;
  61. end;
  62. end
  63. else
  64. begin
  65. if nf_swaped in flags then
  66. case nodetype of
  67. equaln : getresflags:=F_E;
  68. unequaln : getresflags:=F_NE;
  69. ltn : getresflags:=F_A;
  70. lten : getresflags:=F_AE;
  71. gtn : getresflags:=F_B;
  72. gten : getresflags:=F_BE;
  73. end
  74. else
  75. case nodetype of
  76. equaln : getresflags:=F_E;
  77. unequaln : getresflags:=F_NE;
  78. ltn : getresflags:=F_B;
  79. lten : getresflags:=F_BE;
  80. gtn : getresflags:=F_A;
  81. gten : getresflags:=F_AE;
  82. end;
  83. end;
  84. end;
  85. procedure ti386addnode.SetResultLocation(cmpop,unsigned : boolean);
  86. begin
  87. { remove temporary location if not a set or string }
  88. { that's a bad hack (FK) who did this ? }
  89. if (left.resulttype^.deftype<>stringdef) and
  90. ((left.resulttype^.deftype<>setdef) or (psetdef(left.resulttype)^.settype=smallset)) and
  91. (left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  92. ungetiftemp(left.location.reference);
  93. if (right.resulttype^.deftype<>stringdef) and
  94. ((right.resulttype^.deftype<>setdef) or (psetdef(right.resulttype)^.settype=smallset)) and
  95. (right.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  96. ungetiftemp(right.location.reference);
  97. { in case of comparison operation the put result in the flags }
  98. if cmpop then
  99. begin
  100. clear_location(location);
  101. location.loc:=LOC_FLAGS;
  102. location.resflags:=getresflags(unsigned);
  103. end;
  104. end;
  105. {*****************************************************************************
  106. Addstring
  107. *****************************************************************************}
  108. procedure ti386addnode.addstring;
  109. var
  110. {$ifdef newoptimizations2}
  111. l: pasmlabel;
  112. hreg: tregister;
  113. href2: preference;
  114. oldregisterdef: boolean;
  115. {$endif newoptimizations2}
  116. pushedregs : tpushed;
  117. href : treference;
  118. pushed,
  119. cmpop : boolean;
  120. regstopush : byte;
  121. begin
  122. { string operations are not commutative }
  123. if nf_swaped in flags then
  124. swapleftright;
  125. case pstringdef(left.resulttype)^.string_typ of
  126. st_ansistring:
  127. begin
  128. case nodetype of
  129. addn:
  130. begin
  131. cmpop:=false;
  132. secondpass(left);
  133. { to avoid problem with maybe_push and restore }
  134. set_location(location,left.location);
  135. pushed:=maybe_push(right.registers32,self,false);
  136. secondpass(right);
  137. if pushed then
  138. begin
  139. restore(self,false);
  140. set_location(left.location,location);
  141. end;
  142. { get the temp location, must be done before regs are
  143. released/pushed because after the release the regs are
  144. still used for the push (PFV) }
  145. clear_location(location);
  146. location.loc:=LOC_MEM;
  147. gettempansistringreference(location.reference);
  148. decrstringref(cansistringdef,location.reference);
  149. { release used registers }
  150. del_location(right.location);
  151. del_location(left.location);
  152. { push the still used registers }
  153. pushusedregisters(pushedregs,$ff);
  154. { push data }
  155. emitpushreferenceaddr(location.reference);
  156. emit_push_loc(right.location);
  157. emit_push_loc(left.location);
  158. emitcall('FPC_ANSISTR_CONCAT');
  159. popusedregisters(pushedregs);
  160. maybe_loadesi;
  161. ungetiftempansi(left.location.reference);
  162. ungetiftempansi(right.location.reference);
  163. end;
  164. ltn,lten,gtn,gten,
  165. equaln,unequaln:
  166. begin
  167. cmpop:=true;
  168. if (nodetype in [equaln,unequaln]) and
  169. (left.nodetype=stringconstn) and
  170. (tstringconstnode(left).len=0) then
  171. begin
  172. secondpass(right);
  173. { release used registers }
  174. del_location(right.location);
  175. del_location(left.location);
  176. case right.location.loc of
  177. LOC_REFERENCE,LOC_MEM:
  178. emit_const_ref(A_CMP,S_L,0,newreference(right.location.reference));
  179. LOC_REGISTER,LOC_CREGISTER:
  180. emit_const_reg(A_CMP,S_L,0,right.location.register);
  181. end;
  182. ungetiftempansi(left.location.reference);
  183. ungetiftempansi(right.location.reference);
  184. end
  185. else if (nodetype in [equaln,unequaln]) and
  186. (right.nodetype=stringconstn) and
  187. (tstringconstnode(right).len=0) then
  188. begin
  189. secondpass(left);
  190. { release used registers }
  191. del_location(right.location);
  192. del_location(left.location);
  193. case right.location.loc of
  194. LOC_REFERENCE,LOC_MEM:
  195. emit_const_ref(A_CMP,S_L,0,newreference(left.location.reference));
  196. LOC_REGISTER,LOC_CREGISTER:
  197. emit_const_reg(A_CMP,S_L,0,left.location.register);
  198. end;
  199. ungetiftempansi(left.location.reference);
  200. ungetiftempansi(right.location.reference);
  201. end
  202. else
  203. begin
  204. secondpass(left);
  205. pushed:=maybe_push(right.registers32,left,false);
  206. secondpass(right);
  207. if pushed then
  208. restore(left,false);
  209. { release used registers }
  210. del_location(right.location);
  211. del_location(left.location);
  212. { push the still used registers }
  213. pushusedregisters(pushedregs,$ff);
  214. { push data }
  215. case right.location.loc of
  216. LOC_REFERENCE,LOC_MEM:
  217. emit_push_mem(right.location.reference);
  218. LOC_REGISTER,LOC_CREGISTER:
  219. emit_reg(A_PUSH,S_L,right.location.register);
  220. end;
  221. case left.location.loc of
  222. LOC_REFERENCE,LOC_MEM:
  223. emit_push_mem(left.location.reference);
  224. LOC_REGISTER,LOC_CREGISTER:
  225. emit_reg(A_PUSH,S_L,left.location.register);
  226. end;
  227. emitcall('FPC_ANSISTR_COMPARE');
  228. emit_reg_reg(A_OR,S_L,R_EAX,R_EAX);
  229. popusedregisters(pushedregs);
  230. maybe_loadesi;
  231. ungetiftempansi(left.location.reference);
  232. ungetiftempansi(right.location.reference);
  233. end;
  234. end;
  235. end;
  236. { the result of ansicompare is signed }
  237. SetResultLocation(cmpop,false);
  238. end;
  239. st_shortstring:
  240. begin
  241. case nodetype of
  242. addn:
  243. begin
  244. cmpop:=false;
  245. secondpass(left);
  246. { if str_concat is set in expr
  247. s:=s+ ... no need to create a temp string (PM) }
  248. if (left.nodetype<>addn) and not(nf_use_strconcat in flags) then
  249. begin
  250. { can only reference be }
  251. { string in register would be funny }
  252. { therefore produce a temporary string }
  253. gettempofsizereference(256,href);
  254. copyshortstring(href,left.location.reference,255,false,true);
  255. { release the registers }
  256. { done by copyshortstring now (JM) }
  257. { del_reference(left.location.reference); }
  258. ungetiftemp(left.location.reference);
  259. { does not hurt: }
  260. clear_location(left.location);
  261. left.location.loc:=LOC_MEM;
  262. left.location.reference:=href;
  263. {$ifdef newoptimizations2}
  264. { length of temp string = 255 (JM) }
  265. { *** redefining a type is not allowed!! (thanks, Pierre) }
  266. { also problem with constant string! }
  267. pstringdef(left.resulttype)^.len := 255;
  268. {$endif newoptimizations2}
  269. end;
  270. secondpass(right);
  271. {$ifdef newoptimizations2}
  272. { special case for string := string + char (JM) }
  273. { needs string length stuff from above! }
  274. hreg := R_NO;
  275. if is_shortstring(left.resulttype) and
  276. is_char(right.resulttype) then
  277. begin
  278. getlabel(l);
  279. getexplicitregister32(R_EDI);
  280. { load the current string length }
  281. emit_ref_reg(A_MOVZX,S_BL,
  282. newreference(left.location.reference),R_EDI);
  283. { is it already maximal? }
  284. emit_const_reg(A_CMP,S_L,
  285. pstringdef(left.resulttype)^.len,R_EDI);
  286. emitjmp(C_E,l);
  287. { no, so add the new character }
  288. { is it a constant char? }
  289. if (right.nodetype <> ordconstn) then
  290. { no, make sure it is in a register }
  291. if right.location.loc in [LOC_REFERENCE,LOC_MEM] then
  292. begin
  293. { free the registers of right }
  294. del_reference(right.location.reference);
  295. { get register for the char }
  296. hreg := reg32toreg8(getregister32);
  297. emit_ref_reg(A_MOV,S_B,
  298. newreference(right.location.reference),
  299. hreg);
  300. { I don't think a temp char exists, but it won't hurt (JM)Ê}
  301. ungetiftemp(right.location.reference);
  302. end
  303. else hreg := right.location.register;
  304. href2 := newreference(left.location.reference);
  305. { we need a new reference to store the character }
  306. { at the end of the string. Check if the base or }
  307. { index register is still free }
  308. if (left.location.reference.base <> R_NO) and
  309. (left.location.reference.index <> R_NO) then
  310. begin
  311. { they're not free, so add the base reg to }
  312. { the string length (since the index can }
  313. { have a scalefactor) and use EDI as base }
  314. emit_reg_reg(A_ADD,S_L,
  315. left.location.reference.base,R_EDI);
  316. href2^.base := R_EDI;
  317. end
  318. else
  319. { at least one is still free, so put EDI there }
  320. if href2^.base = R_NO then
  321. href2^.base := R_EDI
  322. else
  323. begin
  324. href2^.index := R_EDI;
  325. href2^.scalefactor := 1;
  326. end;
  327. { we need to be one position after the last char }
  328. inc(href2^.offset);
  329. { increase the string length }
  330. emit_ref(A_INC,S_B,newreference(left.location.reference));
  331. { and store the character at the end of the string }
  332. if (right.nodetype <> ordconstn) then
  333. begin
  334. { no new_reference(href2) because it's only }
  335. { used once (JM) }
  336. emit_reg_ref(A_MOV,S_B,hreg,href2);
  337. ungetregister(hreg);
  338. end
  339. else
  340. emit_const_ref(A_MOV,S_B,right.value,href2);
  341. emitlab(l);
  342. ungetregister32(R_EDI);
  343. end
  344. else
  345. begin
  346. {$endif newoptimizations2}
  347. { on the right we do not need the register anymore too }
  348. { Instead of releasing them already, simply do not }
  349. { push them (so the release is in the right place, }
  350. { because emitpushreferenceaddr doesn't need extra }
  351. { registers) (JM) }
  352. regstopush := $ff;
  353. remove_non_regvars_from_loc(right.location,
  354. regstopush);
  355. pushusedregisters(pushedregs,regstopush);
  356. { push the maximum possible length of the result }
  357. {$ifdef newoptimizations2}
  358. { string (could be < 255 chars now) (JM) }
  359. emit_const(A_PUSH,S_L,
  360. pstringdef(left.resulttype)^.len);
  361. {$endif newoptimizations2}
  362. emitpushreferenceaddr(left.location.reference);
  363. { the optimizer can more easily put the }
  364. { deallocations in the right place if it happens }
  365. { too early than when it happens too late (if }
  366. { the pushref needs a "lea (..),edi; push edi") }
  367. del_reference(right.location.reference);
  368. emitpushreferenceaddr(right.location.reference);
  369. {$ifdef newoptimizations2}
  370. emitcall('FPC_SHORTSTR_CONCAT_LEN');
  371. {$else newoptimizations2}
  372. emitcall('FPC_SHORTSTR_CONCAT');
  373. {$endif newoptimizations2}
  374. ungetiftemp(right.location.reference);
  375. maybe_loadesi;
  376. popusedregisters(pushedregs);
  377. {$ifdef newoptimizations2}
  378. end;
  379. {$endif newoptimizations2}
  380. set_location(location,left.location);
  381. end;
  382. ltn,lten,gtn,gten,
  383. equaln,unequaln :
  384. begin
  385. cmpop:=true;
  386. { generate better code for s='' and s<>'' }
  387. if (nodetype in [equaln,unequaln]) and
  388. (((left.nodetype=stringconstn) and (str_length(left)=0)) or
  389. ((right.nodetype=stringconstn) and (str_length(right)=0))) then
  390. begin
  391. secondpass(left);
  392. { are too few registers free? }
  393. pushed:=maybe_push(right.registers32,left,false);
  394. secondpass(right);
  395. if pushed then
  396. restore(left,false);
  397. { only one node can be stringconstn }
  398. { else pass 1 would have evaluted }
  399. { this node }
  400. if left.nodetype=stringconstn then
  401. emit_const_ref(
  402. A_CMP,S_B,0,newreference(right.location.reference))
  403. else
  404. emit_const_ref(
  405. A_CMP,S_B,0,newreference(left.location.reference));
  406. del_reference(right.location.reference);
  407. del_reference(left.location.reference);
  408. end
  409. else
  410. begin
  411. pushusedregisters(pushedregs,$ff);
  412. secondpass(left);
  413. emitpushreferenceaddr(left.location.reference);
  414. del_reference(left.location.reference);
  415. secondpass(right);
  416. emitpushreferenceaddr(right.location.reference);
  417. del_reference(right.location.reference);
  418. emitcall('FPC_SHORTSTR_COMPARE');
  419. maybe_loadesi;
  420. popusedregisters(pushedregs);
  421. end;
  422. ungetiftemp(left.location.reference);
  423. ungetiftemp(right.location.reference);
  424. end;
  425. else CGMessage(type_e_mismatch);
  426. end;
  427. SetResultLocation(cmpop,true);
  428. end;
  429. end;
  430. end;
  431. {*****************************************************************************
  432. Addset
  433. *****************************************************************************}
  434. procedure ti386addnode.addset;
  435. var
  436. createset,
  437. cmpop,
  438. pushed : boolean;
  439. href : treference;
  440. pushedregs : tpushed;
  441. regstopush: byte;
  442. begin
  443. cmpop:=false;
  444. { not commutative }
  445. if nf_swaped in flags then
  446. swapleftright;
  447. { optimize first loading of a set }
  448. {$ifdef usecreateset}
  449. if (right.nodetype=setelementn) and
  450. not(assigned(right.right)) and
  451. is_emptyset(left) then
  452. createset:=true
  453. else
  454. {$endif}
  455. begin
  456. createset:=false;
  457. secondpass(left);
  458. end;
  459. { are too few registers free? }
  460. pushed:=maybe_push(right.registers32,left,false);
  461. secondpass(right);
  462. if codegenerror then
  463. exit;
  464. if pushed then
  465. restore(left,false);
  466. set_location(location,left.location);
  467. { handle operations }
  468. case nodetype of
  469. equaln,
  470. unequaln
  471. {$IfNDef NoSetInclusion}
  472. ,lten, gten
  473. {$EndIf NoSetInclusion}
  474. : begin
  475. cmpop:=true;
  476. del_location(left.location);
  477. del_location(right.location);
  478. pushusedregisters(pushedregs,$ff);
  479. {$IfNDef NoSetInclusion}
  480. If (nodetype in [equaln, unequaln, lten]) Then
  481. Begin
  482. {$EndIf NoSetInclusion}
  483. emitpushreferenceaddr(right.location.reference);
  484. emitpushreferenceaddr(left.location.reference);
  485. {$IfNDef NoSetInclusion}
  486. End
  487. Else {gten = lten, if the arguments are reversed}
  488. Begin
  489. emitpushreferenceaddr(left.location.reference);
  490. emitpushreferenceaddr(right.location.reference);
  491. End;
  492. Case nodetype of
  493. equaln, unequaln:
  494. {$EndIf NoSetInclusion}
  495. emitcall('FPC_SET_COMP_SETS');
  496. {$IfNDef NoSetInclusion}
  497. lten, gten:
  498. Begin
  499. emitcall('FPC_SET_CONTAINS_SETS');
  500. { we need a jne afterwards, not a jnbe/jnae }
  501. nodetype := equaln;
  502. End;
  503. End;
  504. {$EndIf NoSetInclusion}
  505. maybe_loadesi;
  506. popusedregisters(pushedregs);
  507. ungetiftemp(left.location.reference);
  508. ungetiftemp(right.location.reference);
  509. end;
  510. addn : begin
  511. { add can be an other SET or Range or Element ! }
  512. { del_location(right.location);
  513. done in pushsetelement below PM
  514. And someone added it again because those registers must
  515. not be pushed by the pushusedregisters, however this
  516. breaks the optimizer (JM)
  517. del_location(right.location);
  518. pushusedregisters(pushedregs,$ff);}
  519. regstopush := $ff;
  520. remove_non_regvars_from_loc(right.location,regstopush);
  521. remove_non_regvars_from_loc(left.location,regstopush);
  522. pushusedregisters(pushedregs,regstopush);
  523. { this is still right before the instruction that uses }
  524. { left.location, but that can be fixed by the }
  525. { optimizer. There must never be an additional }
  526. { between the release and the use, because that is not }
  527. { detected/fixed. As Pierre said above, right.loc }
  528. { will be released in pushsetelement (JM) }
  529. del_location(left.location);
  530. href.symbol:=nil;
  531. gettempofsizereference(32,href);
  532. if createset then
  533. begin
  534. pushsetelement(tunarynode(right).left);
  535. emitpushreferenceaddr(href);
  536. emitcall('FPC_SET_CREATE_ELEMENT');
  537. end
  538. else
  539. begin
  540. { add a range or a single element? }
  541. if right.nodetype=setelementn then
  542. begin
  543. {$IfNDef regallocfix}
  544. concatcopy(left.location.reference,href,32,false,false);
  545. {$Else regallocfix}
  546. concatcopy(left.location.reference,href,32,true,false);
  547. {$EndIf regallocfix}
  548. if assigned(tbinarynode(right).right) then
  549. begin
  550. pushsetelement(tbinarynode(right).right);
  551. pushsetelement(tunarynode(right).left);
  552. emitpushreferenceaddr(href);
  553. emitcall('FPC_SET_SET_RANGE');
  554. end
  555. else
  556. begin
  557. pushsetelement(tunarynode(right).left);
  558. emitpushreferenceaddr(href);
  559. emitcall('FPC_SET_SET_BYTE');
  560. end;
  561. end
  562. else
  563. begin
  564. { must be an other set }
  565. emitpushreferenceaddr(href);
  566. emitpushreferenceaddr(right.location.reference);
  567. {$IfDef regallocfix}
  568. del_location(right.location);
  569. {$EndIf regallocfix}
  570. emitpushreferenceaddr(left.location.reference);
  571. {$IfDef regallocfix}
  572. del_location(left.location);
  573. {$EndIf regallocfix}
  574. emitcall('FPC_SET_ADD_SETS');
  575. end;
  576. end;
  577. maybe_loadesi;
  578. popusedregisters(pushedregs);
  579. ungetiftemp(left.location.reference);
  580. ungetiftemp(right.location.reference);
  581. location.loc:=LOC_MEM;
  582. location.reference:=href;
  583. end;
  584. subn,
  585. symdifn,
  586. muln : begin
  587. { Find out which registers have to pushed (JM) }
  588. regstopush := $ff;
  589. remove_non_regvars_from_loc(left.location,regstopush);
  590. remove_non_regvars_from_loc(right.location,regstopush);
  591. { Push them (JM) }
  592. pushusedregisters(pushedregs,regstopush);
  593. href.symbol:=nil;
  594. gettempofsizereference(32,href);
  595. emitpushreferenceaddr(href);
  596. { Release the registers right before they're used, }
  597. { see explanation in cgai386.pas:loadansistring for }
  598. { info why this is done right before the push (JM) }
  599. del_location(right.location);
  600. emitpushreferenceaddr(right.location.reference);
  601. { The same here }
  602. del_location(left.location);
  603. emitpushreferenceaddr(left.location.reference);
  604. case nodetype of
  605. subn : emitcall('FPC_SET_SUB_SETS');
  606. symdifn : emitcall('FPC_SET_SYMDIF_SETS');
  607. muln : emitcall('FPC_SET_MUL_SETS');
  608. end;
  609. maybe_loadesi;
  610. popusedregisters(pushedregs);
  611. ungetiftemp(left.location.reference);
  612. ungetiftemp(right.location.reference);
  613. location.loc:=LOC_MEM;
  614. location.reference:=href;
  615. end;
  616. else
  617. CGMessage(type_e_mismatch);
  618. end;
  619. SetResultLocation(cmpop,true);
  620. end;
  621. {*****************************************************************************
  622. pass_2
  623. *****************************************************************************}
  624. procedure ti386addnode.pass_2;
  625. { is also being used for xor, and "mul", "sub, or and comparative }
  626. { operators }
  627. label do_normal;
  628. var
  629. hregister,hregister2 : tregister;
  630. noswap,popeax,popedx,
  631. pushed,mboverflow,cmpop : boolean;
  632. op,op2 : tasmop;
  633. resflags : tresflags;
  634. otl,ofl : pasmlabel;
  635. power : longint;
  636. opsize : topsize;
  637. hl4: pasmlabel;
  638. hr : preference;
  639. { true, if unsigned types are compared }
  640. unsigned : boolean;
  641. { true, if a small set is handled with the longint code }
  642. is_set : boolean;
  643. { is_in_dest if the result is put directly into }
  644. { the resulting refernce or varregister }
  645. is_in_dest : boolean;
  646. { true, if for sets subtractions the extra not should generated }
  647. extra_not : boolean;
  648. {$ifdef SUPPORT_MMX}
  649. mmxbase : tmmxtype;
  650. {$endif SUPPORT_MMX}
  651. pushedreg : tpushed;
  652. hloc : tlocation;
  653. regstopush: byte;
  654. procedure firstjmp64bitcmp;
  655. var
  656. oldnodetype : tnodetype;
  657. begin
  658. { the jump the sequence is a little bit hairy }
  659. case nodetype of
  660. ltn,gtn:
  661. begin
  662. emitjmp(flag_2_cond[getresflags(unsigned)],truelabel);
  663. { cheat a little bit for the negative test }
  664. toggleflag(nf_swaped);
  665. emitjmp(flag_2_cond[getresflags(unsigned)],falselabel);
  666. toggleflag(nf_swaped);
  667. end;
  668. lten,gten:
  669. begin
  670. oldnodetype:=nodetype;
  671. if nodetype=lten then
  672. nodetype:=ltn
  673. else
  674. nodetype:=gtn;
  675. emitjmp(flag_2_cond[getresflags(unsigned)],truelabel);
  676. { cheat for the negative test }
  677. if nodetype=ltn then
  678. nodetype:=gtn
  679. else
  680. nodetype:=ltn;
  681. emitjmp(flag_2_cond[getresflags(unsigned)],falselabel);
  682. nodetype:=oldnodetype;
  683. end;
  684. equaln:
  685. emitjmp(C_NE,falselabel);
  686. unequaln:
  687. emitjmp(C_NE,truelabel);
  688. end;
  689. end;
  690. procedure secondjmp64bitcmp;
  691. begin
  692. { the jump the sequence is a little bit hairy }
  693. case nodetype of
  694. ltn,gtn,lten,gten:
  695. begin
  696. { the comparisaion of the low dword have to be }
  697. { always unsigned! }
  698. emitjmp(flag_2_cond[getresflags(true)],truelabel);
  699. emitjmp(C_None,falselabel);
  700. end;
  701. equaln:
  702. begin
  703. emitjmp(C_NE,falselabel);
  704. emitjmp(C_None,truelabel);
  705. end;
  706. unequaln:
  707. begin
  708. emitjmp(C_NE,truelabel);
  709. emitjmp(C_None,falselabel);
  710. end;
  711. end;
  712. end;
  713. begin
  714. { to make it more readable, string and set (not smallset!) have their
  715. own procedures }
  716. case left.resulttype^.deftype of
  717. stringdef : begin
  718. addstring;
  719. exit;
  720. end;
  721. setdef : begin
  722. { normalsets are handled separate }
  723. if not(psetdef(left.resulttype)^.settype=smallset) then
  724. begin
  725. addset;
  726. exit;
  727. end;
  728. end;
  729. end;
  730. { defaults }
  731. unsigned:=false;
  732. is_in_dest:=false;
  733. extra_not:=false;
  734. noswap:=false;
  735. opsize:=S_L;
  736. { are we a (small)set, must be set here because the side can be
  737. swapped ! (PFV) }
  738. is_set:=(left.resulttype^.deftype=setdef);
  739. { calculate the operator which is more difficult }
  740. firstcomplex(self);
  741. { handling boolean expressions extra: }
  742. if is_boolean(left.resulttype) and
  743. is_boolean(right.resulttype) then
  744. begin
  745. if (porddef(left.resulttype)^.typ=bool8bit) or
  746. (porddef(right.resulttype)^.typ=bool8bit) then
  747. opsize:=S_B
  748. else
  749. if (porddef(left.resulttype)^.typ=bool16bit) or
  750. (porddef(right.resulttype)^.typ=bool16bit) then
  751. opsize:=S_W
  752. else
  753. opsize:=S_L;
  754. if (cs_full_boolean_eval in aktlocalswitches) or
  755. (nodetype in
  756. [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  757. begin
  758. if left.nodetype=ordconstn then
  759. swapleftright;
  760. if left.location.loc=LOC_JUMP then
  761. begin
  762. otl:=truelabel;
  763. getlabel(truelabel);
  764. ofl:=falselabel;
  765. getlabel(falselabel);
  766. end;
  767. secondpass(left);
  768. { if in flags then copy first to register, because the
  769. flags can be destroyed }
  770. case left.location.loc of
  771. LOC_FLAGS:
  772. locflags2reg(left.location,opsize);
  773. LOC_JUMP:
  774. locjump2reg(left.location,opsize, otl, ofl);
  775. end;
  776. set_location(location,left.location);
  777. pushed:=maybe_push(right.registers32,self,false);
  778. if right.location.loc=LOC_JUMP then
  779. begin
  780. otl:=truelabel;
  781. getlabel(truelabel);
  782. ofl:=falselabel;
  783. getlabel(falselabel);
  784. end;
  785. secondpass(right);
  786. if pushed then
  787. begin
  788. restore(self,false);
  789. set_location(left.location,location);
  790. end;
  791. case right.location.loc of
  792. LOC_FLAGS:
  793. locflags2reg(right.location,opsize);
  794. LOC_JUMP:
  795. locjump2reg(right.location,opsize,otl,ofl);
  796. end;
  797. goto do_normal;
  798. end;
  799. case nodetype of
  800. andn,
  801. orn : begin
  802. clear_location(location);
  803. location.loc:=LOC_JUMP;
  804. cmpop:=false;
  805. case nodetype of
  806. andn : begin
  807. otl:=truelabel;
  808. getlabel(truelabel);
  809. secondpass(left);
  810. maketojumpbool(left);
  811. emitlab(truelabel);
  812. truelabel:=otl;
  813. end;
  814. orn : begin
  815. ofl:=falselabel;
  816. getlabel(falselabel);
  817. secondpass(left);
  818. maketojumpbool(left);
  819. emitlab(falselabel);
  820. falselabel:=ofl;
  821. end;
  822. else
  823. CGMessage(type_e_mismatch);
  824. end;
  825. secondpass(right);
  826. maketojumpbool(right);
  827. end;
  828. else
  829. CGMessage(type_e_mismatch);
  830. end
  831. end
  832. else
  833. begin
  834. { in case of constant put it to the left }
  835. if (left.nodetype=ordconstn) then
  836. swapleftright;
  837. secondpass(left);
  838. { this will be complicated as
  839. a lot of code below assumes that
  840. location and left.location are the same }
  841. {$ifdef test_dest_loc}
  842. if dest_loc_known and (dest_loc_tree=p) and
  843. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  844. begin
  845. set_location(location,dest_loc);
  846. in_dest_loc:=true;
  847. is_in_dest:=true;
  848. end
  849. else
  850. {$endif test_dest_loc}
  851. set_location(location,left.location);
  852. { are too few registers free? }
  853. pushed:=maybe_push(right.registers32,self,is_64bitint(left.resulttype));
  854. secondpass(right);
  855. if pushed then
  856. begin
  857. restore(self,is_64bitint(left.resulttype));
  858. set_location(left.location,location);
  859. end;
  860. if (left.resulttype^.deftype=pointerdef) or
  861. (right.resulttype^.deftype=pointerdef) or
  862. ((right.resulttype^.deftype=objectdef) and
  863. pobjectdef(right.resulttype)^.is_class and
  864. (left.resulttype^.deftype=objectdef) and
  865. pobjectdef(left.resulttype)^.is_class
  866. ) or
  867. (left.resulttype^.deftype=classrefdef) or
  868. (left.resulttype^.deftype=procvardef) or
  869. ((left.resulttype^.deftype=enumdef) and
  870. (left.resulttype^.size=4)) or
  871. ((left.resulttype^.deftype=orddef) and
  872. (porddef(left.resulttype)^.typ=s32bit)) or
  873. ((right.resulttype^.deftype=orddef) and
  874. (porddef(right.resulttype)^.typ=s32bit)) or
  875. ((left.resulttype^.deftype=orddef) and
  876. (porddef(left.resulttype)^.typ=u32bit)) or
  877. ((right.resulttype^.deftype=orddef) and
  878. (porddef(right.resulttype)^.typ=u32bit)) or
  879. { as well as small sets }
  880. is_set then
  881. begin
  882. do_normal:
  883. mboverflow:=false;
  884. cmpop:=false;
  885. {$ifndef cardinalmulfix}
  886. unsigned :=
  887. (left.resulttype^.deftype=pointerdef) or
  888. (right.resulttype^.deftype=pointerdef) or
  889. ((left.resulttype^.deftype=orddef) and
  890. (porddef(left.resulttype)^.typ=u32bit)) or
  891. ((right.resulttype^.deftype=orddef) and
  892. (porddef(right.resulttype)^.typ=u32bit));
  893. {$else cardinalmulfix}
  894. unsigned := not(is_signed(left.resulttype)) or
  895. not(is_signed(right.resulttype));
  896. {$endif cardinalmulfix}
  897. case nodetype of
  898. addn : begin
  899. { this is a really ugly hack!!!!!!!!!! }
  900. { this could be done later using EDI }
  901. { as it is done for subn }
  902. { instead of two registers!!!! }
  903. if is_set then
  904. begin
  905. { adding elements is not commutative }
  906. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  907. swapleftright;
  908. { are we adding set elements ? }
  909. if right.nodetype=setelementn then
  910. begin
  911. { no range support for smallsets! }
  912. if assigned(tsetelementnode(right).right) then
  913. internalerror(43244);
  914. { bts requires both elements to be registers }
  915. if left.location.loc in [LOC_MEM,LOC_REFERENCE] then
  916. begin
  917. ungetiftemp(left.location.reference);
  918. del_location(left.location);
  919. {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  920. hregister:=getregister32;
  921. emit_ref_reg(A_MOV,opsize,
  922. newreference(left.location.reference),hregister);
  923. clear_location(left.location);
  924. left.location.loc:=LOC_REGISTER;
  925. left.location.register:=hregister;
  926. set_location(location,left.location);
  927. end;
  928. if right.location.loc in [LOC_MEM,LOC_REFERENCE] then
  929. begin
  930. ungetiftemp(right.location.reference);
  931. del_location(right.location);
  932. hregister:=getregister32;
  933. emit_ref_reg(A_MOV,opsize,
  934. newreference(right.location.reference),hregister);
  935. clear_location(right.location);
  936. right.location.loc:=LOC_REGISTER;
  937. right.location.register:=hregister;
  938. end;
  939. op:=A_BTS;
  940. noswap:=true;
  941. end
  942. else
  943. op:=A_OR;
  944. mboverflow:=false;
  945. unsigned:=false;
  946. end
  947. else
  948. begin
  949. op:=A_ADD;
  950. mboverflow:=true;
  951. end;
  952. end;
  953. symdifn : begin
  954. { the symetric diff is only for sets }
  955. if is_set then
  956. begin
  957. op:=A_XOR;
  958. mboverflow:=false;
  959. unsigned:=false;
  960. end
  961. else
  962. CGMessage(type_e_mismatch);
  963. end;
  964. muln : begin
  965. if is_set then
  966. begin
  967. op:=A_AND;
  968. mboverflow:=false;
  969. unsigned:=false;
  970. end
  971. else
  972. begin
  973. if unsigned then
  974. op:=A_MUL
  975. else
  976. op:=A_IMUL;
  977. mboverflow:=true;
  978. end;
  979. end;
  980. subn : begin
  981. if is_set then
  982. begin
  983. op:=A_AND;
  984. mboverflow:=false;
  985. unsigned:=false;
  986. {$IfNDef NoSetConstNot}
  987. If (right.nodetype = setconstn) then
  988. right.location.reference.offset := not(right.location.reference.offset)
  989. Else
  990. {$EndIf NoNosetConstNot}
  991. extra_not:=true;
  992. end
  993. else
  994. begin
  995. op:=A_SUB;
  996. mboverflow:=true;
  997. end;
  998. end;
  999. ltn,lten,
  1000. gtn,gten,
  1001. equaln,unequaln : begin
  1002. {$IfNDef NoSetInclusion}
  1003. If is_set Then
  1004. Case nodetype of
  1005. lten,gten:
  1006. Begin
  1007. If nodetype = lten then
  1008. swapleftright;
  1009. if left.location.loc in [LOC_MEM,LOC_REFERENCE] then
  1010. begin
  1011. ungetiftemp(left.location.reference);
  1012. del_reference(left.location.reference);
  1013. hregister:=getregister32;
  1014. emit_ref_reg(A_MOV,opsize,
  1015. newreference(left.location.reference),hregister);
  1016. clear_location(left.location);
  1017. left.location.loc:=LOC_REGISTER;
  1018. left.location.register:=hregister;
  1019. set_location(location,left.location);
  1020. end
  1021. else
  1022. if left.location.loc = LOC_CREGISTER Then
  1023. {save the register var in a temp register, because
  1024. its value is going to be modified}
  1025. begin
  1026. hregister := getregister32;
  1027. emit_reg_reg(A_MOV,opsize,
  1028. left.location.register,hregister);
  1029. clear_location(left.location);
  1030. left.location.loc:=LOC_REGISTER;
  1031. left.location.register:=hregister;
  1032. set_location(location,left.location);
  1033. end;
  1034. {here, left.location should be LOC_REGISTER}
  1035. If right.location.loc in [LOC_MEM,LOC_REFERENCE] Then
  1036. emit_ref_reg(A_AND,opsize,
  1037. newreference(right.location.reference),left.location.register)
  1038. Else
  1039. emit_reg_reg(A_AND,opsize,
  1040. right.location.register,left.location.register);
  1041. {warning: ugly hack ahead: we need a "jne" after the cmp, so
  1042. change the nodetype from lten/gten to equaln}
  1043. nodetype := equaln
  1044. End;
  1045. {no < or > support for sets}
  1046. ltn,gtn: CGMessage(type_e_mismatch);
  1047. End;
  1048. {$EndIf NoSetInclusion}
  1049. op:=A_CMP;
  1050. cmpop:=true;
  1051. end;
  1052. xorn : op:=A_XOR;
  1053. orn : op:=A_OR;
  1054. andn : op:=A_AND;
  1055. else
  1056. CGMessage(type_e_mismatch);
  1057. end;
  1058. { filter MUL, which requires special handling }
  1059. if op=A_MUL then
  1060. begin
  1061. popeax:=false;
  1062. popedx:=false;
  1063. { here you need to free the symbol first }
  1064. { left.location and right.location must }
  1065. { only be freed when they are really released, }
  1066. { because the optimizer NEEDS correct regalloc }
  1067. { info!!! (JM) }
  1068. clear_location(location);
  1069. { the location.register will be filled in later (JM) }
  1070. location.loc:=LOC_REGISTER;
  1071. {$IfNDef NoShlMul}
  1072. if right.nodetype=ordconstn then
  1073. swapleftright;
  1074. If (left.nodetype = ordconstn) and
  1075. ispowerof2(tordconstnode(left).value, power) and
  1076. not(cs_check_overflow in aktlocalswitches) then
  1077. Begin
  1078. { This release will be moved after the next }
  1079. { instruction by the optimizer. No need to }
  1080. { release left.location, since it's a }
  1081. { constant (JM) }
  1082. release_loc(right.location);
  1083. location.register := getregister32;
  1084. emitloadord2reg(right.location,u32bitdef,location.register,false);
  1085. emit_const_reg(A_SHL,S_L,power,location.register)
  1086. End
  1087. Else
  1088. Begin
  1089. {$EndIf NoShlMul}
  1090. regstopush := $ff;
  1091. remove_non_regvars_from_loc(right.location,regstopush);
  1092. remove_non_regvars_from_loc(left.location,regstopush);
  1093. { now, regstopush does NOT contain EAX and/or EDX if they are }
  1094. { used in either the left or the right location, excepts if }
  1095. {they are regvars. It DOES contain them if they are used in }
  1096. { another location (JM) }
  1097. if not(R_EAX in unused) and ((regstopush and ($80 shr byte(R_EAX))) <> 0) then
  1098. begin
  1099. emit_reg(A_PUSH,S_L,R_EAX);
  1100. popeax:=true;
  1101. end;
  1102. if not(R_EDX in unused) and ((regstopush and ($80 shr byte(R_EDX))) <> 0) then
  1103. begin
  1104. emit_reg(A_PUSH,S_L,R_EDX);
  1105. popedx:=true;
  1106. end;
  1107. { left.location can be R_EAX !!! }
  1108. getexplicitregister32(R_EDI);
  1109. { load the left value }
  1110. emitloadord2reg(left.location,u32bitdef,R_EDI,true);
  1111. release_loc(left.location);
  1112. { allocate EAX }
  1113. if R_EAX in unused then
  1114. exprasmlist^.concat(new(pairegalloc,alloc(R_EAX)));
  1115. { load he right value }
  1116. emitloadord2reg(right.location,u32bitdef,R_EAX,true);
  1117. release_loc(right.location);
  1118. { allocate EAX if it isn't yet allocated (JM) }
  1119. if (R_EAX in unused) then
  1120. exprasmlist^.concat(new(pairegalloc,alloc(R_EAX)));
  1121. { also allocate EDX, since it is also modified by }
  1122. { a mul (JM) }
  1123. if R_EDX in unused then
  1124. exprasmlist^.concat(new(pairegalloc,alloc(R_EDX)));
  1125. emit_reg(A_MUL,S_L,R_EDI);
  1126. ungetregister32(R_EDI);
  1127. if R_EDX in unused then
  1128. exprasmlist^.concat(new(pairegalloc,dealloc(R_EDX)));
  1129. if R_EAX in unused then
  1130. exprasmlist^.concat(new(pairegalloc,dealloc(R_EAX)));
  1131. location.register := getregister32;
  1132. emit_reg_reg(A_MOV,S_L,R_EAX,location.register);
  1133. if popedx then
  1134. emit_reg(A_POP,S_L,R_EDX);
  1135. if popeax then
  1136. emit_reg(A_POP,S_L,R_EAX);
  1137. {$IfNDef NoShlMul}
  1138. End;
  1139. {$endif NoShlMul}
  1140. SetResultLocation(false,true);
  1141. exit;
  1142. end;
  1143. { Convert flags to register first }
  1144. if (left.location.loc=LOC_FLAGS) then
  1145. locflags2reg(left.location,opsize);
  1146. if (right.location.loc=LOC_FLAGS) then
  1147. locflags2reg(right.location,opsize);
  1148. { left and right no register? }
  1149. { then one must be demanded }
  1150. if (left.location.loc<>LOC_REGISTER) and
  1151. (right.location.loc<>LOC_REGISTER) then
  1152. begin
  1153. { register variable ? }
  1154. if (left.location.loc=LOC_CREGISTER) then
  1155. begin
  1156. { it is OK if this is the destination }
  1157. if is_in_dest then
  1158. begin
  1159. hregister:=location.register;
  1160. emit_reg_reg(A_MOV,opsize,left.location.register,
  1161. hregister);
  1162. end
  1163. else
  1164. if cmpop then
  1165. begin
  1166. { do not disturb the register }
  1167. hregister:=location.register;
  1168. end
  1169. else
  1170. begin
  1171. case opsize of
  1172. S_L : hregister:=getregister32;
  1173. S_B : hregister:=reg32toreg8(getregister32);
  1174. end;
  1175. emit_reg_reg(A_MOV,opsize,left.location.register,
  1176. hregister);
  1177. end
  1178. end
  1179. else
  1180. begin
  1181. ungetiftemp(left.location.reference);
  1182. del_reference(left.location.reference);
  1183. if is_in_dest then
  1184. begin
  1185. hregister:=location.register;
  1186. emit_ref_reg(A_MOV,opsize,
  1187. newreference(left.location.reference),hregister);
  1188. end
  1189. else
  1190. begin
  1191. { first give free, then demand new register }
  1192. case opsize of
  1193. S_L : hregister:=getregister32;
  1194. S_W : hregister:=reg32toreg16(getregister32);
  1195. S_B : hregister:=reg32toreg8(getregister32);
  1196. end;
  1197. emit_ref_reg(A_MOV,opsize,
  1198. newreference(left.location.reference),hregister);
  1199. end;
  1200. end;
  1201. clear_location(location);
  1202. location.loc:=LOC_REGISTER;
  1203. location.register:=hregister;
  1204. end
  1205. else
  1206. { if on the right the register then swap }
  1207. if not(noswap) and (right.location.loc=LOC_REGISTER) then
  1208. begin
  1209. swap_location(location,right.location);
  1210. { newly swapped also set swapped flag }
  1211. toggleflag(nf_swaped);
  1212. end;
  1213. { at this point, location.loc should be LOC_REGISTER }
  1214. { and location.register should be a valid register }
  1215. { containing the left result }
  1216. if right.location.loc<>LOC_REGISTER then
  1217. begin
  1218. if (nodetype=subn) and (nf_swaped in flags) then
  1219. begin
  1220. if right.location.loc=LOC_CREGISTER then
  1221. begin
  1222. if extra_not then
  1223. emit_reg(A_NOT,opsize,location.register);
  1224. getexplicitregister32(R_EDI);
  1225. emit_reg_reg(A_MOV,opsize,right.location.register,R_EDI);
  1226. emit_reg_reg(op,opsize,location.register,R_EDI);
  1227. emit_reg_reg(A_MOV,opsize,R_EDI,location.register);
  1228. ungetregister32(R_EDI);
  1229. end
  1230. else
  1231. begin
  1232. if extra_not then
  1233. emit_reg(A_NOT,opsize,location.register);
  1234. getexplicitregister32(R_EDI);
  1235. emit_ref_reg(A_MOV,opsize,
  1236. newreference(right.location.reference),R_EDI);
  1237. emit_reg_reg(op,opsize,location.register,R_EDI);
  1238. emit_reg_reg(A_MOV,opsize,R_EDI,location.register);
  1239. ungetregister32(R_EDI);
  1240. ungetiftemp(right.location.reference);
  1241. del_reference(right.location.reference);
  1242. end;
  1243. end
  1244. else
  1245. begin
  1246. if (right.nodetype=ordconstn) and
  1247. (op=A_CMP) and
  1248. (tordconstnode(right).value=0) then
  1249. begin
  1250. emit_reg_reg(A_TEST,opsize,location.register,
  1251. location.register);
  1252. end
  1253. else if (right.nodetype=ordconstn) and
  1254. (op=A_ADD) and
  1255. (tordconstnode(right).value=1) and
  1256. not(cs_check_overflow in aktlocalswitches) then
  1257. begin
  1258. emit_reg(A_INC,opsize,
  1259. location.register);
  1260. end
  1261. else if (right.nodetype=ordconstn) and
  1262. (op=A_SUB) and
  1263. (tordconstnode(right).value=1) and
  1264. not(cs_check_overflow in aktlocalswitches) then
  1265. begin
  1266. emit_reg(A_DEC,opsize,
  1267. location.register);
  1268. end
  1269. else if (right.nodetype=ordconstn) and
  1270. (op=A_IMUL) and
  1271. (ispowerof2(tordconstnode(right).value,power)) and
  1272. not(cs_check_overflow in aktlocalswitches) then
  1273. begin
  1274. emit_const_reg(A_SHL,opsize,power,
  1275. location.register);
  1276. end
  1277. else
  1278. begin
  1279. if (right.location.loc=LOC_CREGISTER) then
  1280. begin
  1281. if extra_not then
  1282. begin
  1283. getexplicitregister32(R_EDI);
  1284. emit_reg_reg(A_MOV,S_L,right.location.register,R_EDI);
  1285. emit_reg(A_NOT,S_L,R_EDI);
  1286. emit_reg_reg(A_AND,S_L,R_EDI,
  1287. location.register);
  1288. ungetregister32(R_EDI);
  1289. end
  1290. else
  1291. begin
  1292. emit_reg_reg(op,opsize,right.location.register,
  1293. location.register);
  1294. end;
  1295. end
  1296. else
  1297. begin
  1298. if extra_not then
  1299. begin
  1300. getexplicitregister32(R_EDI);
  1301. emit_ref_reg(A_MOV,S_L,newreference(
  1302. right.location.reference),R_EDI);
  1303. emit_reg(A_NOT,S_L,R_EDI);
  1304. emit_reg_reg(A_AND,S_L,R_EDI,
  1305. location.register);
  1306. ungetregister32(R_EDI);
  1307. end
  1308. else
  1309. begin
  1310. emit_ref_reg(op,opsize,newreference(
  1311. right.location.reference),location.register);
  1312. end;
  1313. ungetiftemp(right.location.reference);
  1314. del_reference(right.location.reference);
  1315. end;
  1316. end;
  1317. end;
  1318. end
  1319. else
  1320. begin
  1321. { when swapped another result register }
  1322. if (nodetype=subn) and (nf_swaped in flags) then
  1323. begin
  1324. if extra_not then
  1325. emit_reg(A_NOT,S_L,location.register);
  1326. emit_reg_reg(op,opsize,
  1327. location.register,right.location.register);
  1328. swap_location(location,right.location);
  1329. { newly swapped also set swapped flag }
  1330. { just to maintain ordering }
  1331. toggleflag(nf_swaped);
  1332. end
  1333. else
  1334. begin
  1335. if extra_not then
  1336. emit_reg(A_NOT,S_L,right.location.register);
  1337. emit_reg_reg(op,opsize,
  1338. right.location.register,
  1339. location.register);
  1340. end;
  1341. case opsize of
  1342. S_L : ungetregister32(right.location.register);
  1343. S_B : ungetregister32(reg8toreg32(right.location.register));
  1344. end;
  1345. end;
  1346. if cmpop then
  1347. case opsize of
  1348. S_L : ungetregister32(location.register);
  1349. S_B : ungetregister32(reg8toreg32(location.register));
  1350. end;
  1351. { only in case of overflow operations }
  1352. { produce overflow code }
  1353. { we must put it here directly, because sign of operation }
  1354. { is in unsigned VAR!! }
  1355. if mboverflow then
  1356. begin
  1357. if cs_check_overflow in aktlocalswitches then
  1358. begin
  1359. getlabel(hl4);
  1360. if unsigned then
  1361. emitjmp(C_NB,hl4)
  1362. else
  1363. emitjmp(C_NO,hl4);
  1364. emitcall('FPC_OVERFLOW');
  1365. emitlab(hl4);
  1366. end;
  1367. end;
  1368. end
  1369. else
  1370. { Char type }
  1371. if ((left.resulttype^.deftype=orddef) and
  1372. (porddef(left.resulttype)^.typ=uchar)) or
  1373. { enumeration type 16 bit }
  1374. ((left.resulttype^.deftype=enumdef) and
  1375. (left.resulttype^.size=1)) then
  1376. begin
  1377. case nodetype of
  1378. ltn,lten,gtn,gten,
  1379. equaln,unequaln :
  1380. cmpop:=true;
  1381. else CGMessage(type_e_mismatch);
  1382. end;
  1383. unsigned:=true;
  1384. { left and right no register? }
  1385. { the one must be demanded }
  1386. if (location.loc<>LOC_REGISTER) and
  1387. (right.location.loc<>LOC_REGISTER) then
  1388. begin
  1389. if location.loc=LOC_CREGISTER then
  1390. begin
  1391. if cmpop then
  1392. { do not disturb register }
  1393. hregister:=location.register
  1394. else
  1395. begin
  1396. hregister:=reg32toreg8(getregister32);
  1397. emit_reg_reg(A_MOV,S_B,location.register,
  1398. hregister);
  1399. end;
  1400. end
  1401. else
  1402. begin
  1403. del_reference(location.reference);
  1404. { first give free then demand new register }
  1405. hregister:=reg32toreg8(getregister32);
  1406. emit_ref_reg(A_MOV,S_B,newreference(location.reference),
  1407. hregister);
  1408. end;
  1409. clear_location(location);
  1410. location.loc:=LOC_REGISTER;
  1411. location.register:=hregister;
  1412. end;
  1413. { now p always a register }
  1414. if (right.location.loc=LOC_REGISTER) and
  1415. (location.loc<>LOC_REGISTER) then
  1416. begin
  1417. swap_location(location,right.location);
  1418. { newly swapped also set swapped flag }
  1419. toggleflag(nf_swaped);
  1420. end;
  1421. if right.location.loc<>LOC_REGISTER then
  1422. begin
  1423. if right.location.loc=LOC_CREGISTER then
  1424. begin
  1425. emit_reg_reg(A_CMP,S_B,
  1426. right.location.register,location.register);
  1427. end
  1428. else
  1429. begin
  1430. emit_ref_reg(A_CMP,S_B,newreference(
  1431. right.location.reference),location.register);
  1432. del_reference(right.location.reference);
  1433. end;
  1434. end
  1435. else
  1436. begin
  1437. emit_reg_reg(A_CMP,S_B,right.location.register,
  1438. location.register);
  1439. ungetregister32(reg8toreg32(right.location.register));
  1440. end;
  1441. ungetregister32(reg8toreg32(location.register));
  1442. end
  1443. else
  1444. { 16 bit enumeration type }
  1445. if ((left.resulttype^.deftype=enumdef) and
  1446. (left.resulttype^.size=2)) then
  1447. begin
  1448. case nodetype of
  1449. ltn,lten,gtn,gten,
  1450. equaln,unequaln :
  1451. cmpop:=true;
  1452. else CGMessage(type_e_mismatch);
  1453. end;
  1454. unsigned:=true;
  1455. { left and right no register? }
  1456. { the one must be demanded }
  1457. if (location.loc<>LOC_REGISTER) and
  1458. (right.location.loc<>LOC_REGISTER) then
  1459. begin
  1460. if location.loc=LOC_CREGISTER then
  1461. begin
  1462. if cmpop then
  1463. { do not disturb register }
  1464. hregister:=location.register
  1465. else
  1466. begin
  1467. hregister:=reg32toreg16(getregister32);
  1468. emit_reg_reg(A_MOV,S_W,location.register,
  1469. hregister);
  1470. end;
  1471. end
  1472. else
  1473. begin
  1474. del_reference(location.reference);
  1475. { first give free then demand new register }
  1476. hregister:=reg32toreg16(getregister32);
  1477. emit_ref_reg(A_MOV,S_W,newreference(location.reference),
  1478. hregister);
  1479. end;
  1480. clear_location(location);
  1481. location.loc:=LOC_REGISTER;
  1482. location.register:=hregister;
  1483. end;
  1484. { now p always a register }
  1485. if (right.location.loc=LOC_REGISTER) and
  1486. (location.loc<>LOC_REGISTER) then
  1487. begin
  1488. swap_location(location,right.location);
  1489. { newly swapped also set swapped flag }
  1490. toggleflag(nf_swaped);
  1491. end;
  1492. if right.location.loc<>LOC_REGISTER then
  1493. begin
  1494. if right.location.loc=LOC_CREGISTER then
  1495. begin
  1496. emit_reg_reg(A_CMP,S_W,
  1497. right.location.register,location.register);
  1498. end
  1499. else
  1500. begin
  1501. emit_ref_reg(A_CMP,S_W,newreference(
  1502. right.location.reference),location.register);
  1503. del_reference(right.location.reference);
  1504. end;
  1505. end
  1506. else
  1507. begin
  1508. emit_reg_reg(A_CMP,S_W,right.location.register,
  1509. location.register);
  1510. ungetregister32(reg16toreg32(right.location.register));
  1511. end;
  1512. ungetregister32(reg16toreg32(location.register));
  1513. end
  1514. else
  1515. { 64 bit types }
  1516. if is_64bitint(left.resulttype) then
  1517. begin
  1518. mboverflow:=false;
  1519. cmpop:=false;
  1520. unsigned:=((left.resulttype^.deftype=orddef) and
  1521. (porddef(left.resulttype)^.typ=u64bit)) or
  1522. ((right.resulttype^.deftype=orddef) and
  1523. (porddef(right.resulttype)^.typ=u64bit));
  1524. case nodetype of
  1525. addn : begin
  1526. begin
  1527. op:=A_ADD;
  1528. op2:=A_ADC;
  1529. mboverflow:=true;
  1530. end;
  1531. end;
  1532. subn : begin
  1533. op:=A_SUB;
  1534. op2:=A_SBB;
  1535. mboverflow:=true;
  1536. end;
  1537. ltn,lten,
  1538. gtn,gten,
  1539. equaln,unequaln:
  1540. begin
  1541. op:=A_CMP;
  1542. op2:=A_CMP;
  1543. cmpop:=true;
  1544. end;
  1545. xorn:
  1546. begin
  1547. op:=A_XOR;
  1548. op2:=A_XOR;
  1549. end;
  1550. orn:
  1551. begin
  1552. op:=A_OR;
  1553. op2:=A_OR;
  1554. end;
  1555. andn:
  1556. begin
  1557. op:=A_AND;
  1558. op2:=A_AND;
  1559. end;
  1560. muln:
  1561. ;
  1562. else
  1563. CGMessage(type_e_mismatch);
  1564. end;
  1565. if nodetype=muln then
  1566. begin
  1567. { save lcoation, because we change it now }
  1568. set_location(hloc,location);
  1569. release_qword_loc(location);
  1570. release_qword_loc(right.location);
  1571. location.registerlow:=getexplicitregister32(R_EAX);
  1572. location.registerhigh:=getexplicitregister32(R_EDX);
  1573. pushusedregisters(pushedreg,$ff
  1574. and not($80 shr byte(location.registerlow))
  1575. and not($80 shr byte(location.registerhigh)));
  1576. if cs_check_overflow in aktlocalswitches then
  1577. push_int(1)
  1578. else
  1579. push_int(0);
  1580. { the left operand is in hloc, because the
  1581. location of left is location but location
  1582. is already destroyed
  1583. }
  1584. emit_pushq_loc(hloc);
  1585. clear_location(hloc);
  1586. emit_pushq_loc(right.location);
  1587. if porddef(resulttype)^.typ=u64bit then
  1588. emitcall('FPC_MUL_QWORD')
  1589. else
  1590. emitcall('FPC_MUL_INT64');
  1591. emit_reg_reg(A_MOV,S_L,R_EAX,location.registerlow);
  1592. emit_reg_reg(A_MOV,S_L,R_EDX,location.registerhigh);
  1593. popusedregisters(pushedreg);
  1594. location.loc:=LOC_REGISTER;
  1595. end
  1596. else
  1597. begin
  1598. { left and right no register? }
  1599. { then one must be demanded }
  1600. if (left.location.loc<>LOC_REGISTER) and
  1601. (right.location.loc<>LOC_REGISTER) then
  1602. begin
  1603. { register variable ? }
  1604. if (left.location.loc=LOC_CREGISTER) then
  1605. begin
  1606. { it is OK if this is the destination }
  1607. if is_in_dest then
  1608. begin
  1609. hregister:=location.registerlow;
  1610. hregister2:=location.registerhigh;
  1611. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  1612. hregister);
  1613. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  1614. hregister2);
  1615. end
  1616. else
  1617. if cmpop then
  1618. begin
  1619. { do not disturb the register }
  1620. hregister:=location.registerlow;
  1621. hregister2:=location.registerhigh;
  1622. end
  1623. else
  1624. begin
  1625. hregister:=getregister32;
  1626. hregister2:=getregister32;
  1627. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  1628. hregister);
  1629. emit_reg_reg(A_MOV,S_L,left.location.registerhigh,
  1630. hregister2);
  1631. end
  1632. end
  1633. else
  1634. begin
  1635. ungetiftemp(left.location.reference);
  1636. del_reference(left.location.reference);
  1637. if is_in_dest then
  1638. begin
  1639. hregister:=location.registerlow;
  1640. hregister2:=location.registerhigh;
  1641. emit_mov_ref_reg64(left.location.reference,hregister,hregister2);
  1642. end
  1643. else
  1644. begin
  1645. hregister:=getregister32;
  1646. hregister2:=getregister32;
  1647. emit_mov_ref_reg64(left.location.reference,hregister,hregister2);
  1648. end;
  1649. end;
  1650. clear_location(location);
  1651. location.loc:=LOC_REGISTER;
  1652. location.registerlow:=hregister;
  1653. location.registerhigh:=hregister2;
  1654. end
  1655. else
  1656. { if on the right the register then swap }
  1657. if not(noswap) and (right.location.loc=LOC_REGISTER) then
  1658. begin
  1659. swap_location(location,right.location);
  1660. { newly swapped also set swapped flag }
  1661. toggleflag(nf_swaped);
  1662. end;
  1663. { at this point, location.loc should be LOC_REGISTER }
  1664. { and location.register should be a valid register }
  1665. { containing the left result }
  1666. if right.location.loc<>LOC_REGISTER then
  1667. begin
  1668. if (nodetype=subn) and (nf_swaped in flags) then
  1669. begin
  1670. if right.location.loc=LOC_CREGISTER then
  1671. begin
  1672. getexplicitregister32(R_EDI);
  1673. emit_reg_reg(A_MOV,opsize,right.location.register,R_EDI);
  1674. emit_reg_reg(op,opsize,location.register,R_EDI);
  1675. emit_reg_reg(A_MOV,opsize,R_EDI,location.register);
  1676. ungetregister32(R_EDI);
  1677. getexplicitregister32(R_EDI);
  1678. emit_reg_reg(A_MOV,opsize,right.location.registerhigh,R_EDI);
  1679. { the carry flag is still ok }
  1680. emit_reg_reg(op2,opsize,location.registerhigh,R_EDI);
  1681. emit_reg_reg(A_MOV,opsize,R_EDI,location.registerhigh);
  1682. ungetregister32(R_EDI);
  1683. end
  1684. else
  1685. begin
  1686. getexplicitregister32(R_EDI);
  1687. emit_ref_reg(A_MOV,opsize,
  1688. newreference(right.location.reference),R_EDI);
  1689. emit_reg_reg(op,opsize,location.registerlow,R_EDI);
  1690. emit_reg_reg(A_MOV,opsize,R_EDI,location.registerlow);
  1691. ungetregister32(R_EDI);
  1692. getexplicitregister32(R_EDI);
  1693. hr:=newreference(right.location.reference);
  1694. inc(hr^.offset,4);
  1695. emit_ref_reg(A_MOV,opsize,
  1696. hr,R_EDI);
  1697. { here the carry flag is still preserved }
  1698. emit_reg_reg(op2,opsize,location.registerhigh,R_EDI);
  1699. emit_reg_reg(A_MOV,opsize,R_EDI,
  1700. location.registerhigh);
  1701. ungetregister32(R_EDI);
  1702. ungetiftemp(right.location.reference);
  1703. del_reference(right.location.reference);
  1704. end;
  1705. end
  1706. else if cmpop then
  1707. begin
  1708. if (right.location.loc=LOC_CREGISTER) then
  1709. begin
  1710. emit_reg_reg(A_CMP,S_L,right.location.registerhigh,
  1711. location.registerhigh);
  1712. firstjmp64bitcmp;
  1713. emit_reg_reg(A_CMP,S_L,right.location.registerlow,
  1714. location.registerlow);
  1715. secondjmp64bitcmp;
  1716. end
  1717. else
  1718. begin
  1719. hr:=newreference(right.location.reference);
  1720. inc(hr^.offset,4);
  1721. emit_ref_reg(A_CMP,S_L,
  1722. hr,location.registerhigh);
  1723. firstjmp64bitcmp;
  1724. emit_ref_reg(A_CMP,S_L,newreference(
  1725. right.location.reference),location.registerlow);
  1726. secondjmp64bitcmp;
  1727. emitjmp(C_None,falselabel);
  1728. ungetiftemp(right.location.reference);
  1729. del_reference(right.location.reference);
  1730. end;
  1731. end
  1732. else
  1733. begin
  1734. {
  1735. if (right.nodetype=ordconstn) and
  1736. (op=A_CMP) and
  1737. (right.value=0) then
  1738. begin
  1739. emit_reg_reg(A_TEST,opsize,location.register,
  1740. location.register);
  1741. end
  1742. else if (right.nodetype=ordconstn) and
  1743. (op=A_IMUL) and
  1744. (ispowerof2(right.value,power)) then
  1745. begin
  1746. emit_const_reg(A_SHL,opsize,power,
  1747. location.register);
  1748. end
  1749. else
  1750. }
  1751. begin
  1752. if (right.location.loc=LOC_CREGISTER) then
  1753. begin
  1754. emit_reg_reg(op,S_L,right.location.registerlow,
  1755. location.registerlow);
  1756. emit_reg_reg(op2,S_L,right.location.registerhigh,
  1757. location.registerhigh);
  1758. end
  1759. else
  1760. begin
  1761. emit_ref_reg(op,S_L,newreference(
  1762. right.location.reference),location.registerlow);
  1763. hr:=newreference(right.location.reference);
  1764. inc(hr^.offset,4);
  1765. emit_ref_reg(op2,S_L,
  1766. hr,location.registerhigh);
  1767. ungetiftemp(right.location.reference);
  1768. del_reference(right.location.reference);
  1769. end;
  1770. end;
  1771. end;
  1772. end
  1773. else
  1774. begin
  1775. { when swapped another result register }
  1776. if (nodetype=subn) and (nf_swaped in flags) then
  1777. begin
  1778. emit_reg_reg(op,S_L,
  1779. location.registerlow,
  1780. right.location.registerlow);
  1781. emit_reg_reg(op2,S_L,
  1782. location.registerhigh,
  1783. right.location.registerhigh);
  1784. swap_location(location,right.location);
  1785. { newly swapped also set swapped flag }
  1786. { just to maintain ordering }
  1787. toggleflag(nf_swaped);
  1788. end
  1789. else if cmpop then
  1790. begin
  1791. emit_reg_reg(A_CMP,S_L,
  1792. right.location.registerhigh,
  1793. location.registerhigh);
  1794. firstjmp64bitcmp;
  1795. emit_reg_reg(A_CMP,S_L,
  1796. right.location.registerlow,
  1797. location.registerlow);
  1798. secondjmp64bitcmp;
  1799. end
  1800. else
  1801. begin
  1802. emit_reg_reg(op,S_L,
  1803. right.location.registerlow,
  1804. location.registerlow);
  1805. emit_reg_reg(op2,S_L,
  1806. right.location.registerhigh,
  1807. location.registerhigh);
  1808. end;
  1809. ungetregister32(right.location.registerlow);
  1810. ungetregister32(right.location.registerhigh);
  1811. end;
  1812. if cmpop then
  1813. begin
  1814. ungetregister32(location.registerlow);
  1815. ungetregister32(location.registerhigh);
  1816. end;
  1817. { only in case of overflow operations }
  1818. { produce overflow code }
  1819. { we must put it here directly, because sign of operation }
  1820. { is in unsigned VAR!! }
  1821. if mboverflow then
  1822. begin
  1823. if cs_check_overflow in aktlocalswitches then
  1824. begin
  1825. getlabel(hl4);
  1826. if unsigned then
  1827. emitjmp(C_NB,hl4)
  1828. else
  1829. emitjmp(C_NO,hl4);
  1830. emitcall('FPC_OVERFLOW');
  1831. emitlab(hl4);
  1832. end;
  1833. end;
  1834. { we have LOC_JUMP as result }
  1835. if cmpop then
  1836. begin
  1837. clear_location(location);
  1838. location.loc:=LOC_JUMP;
  1839. cmpop:=false;
  1840. end;
  1841. end;
  1842. end
  1843. else
  1844. { Floating point }
  1845. if (left.resulttype^.deftype=floatdef) and
  1846. (pfloatdef(left.resulttype)^.typ<>f32bit) then
  1847. begin
  1848. { real constants to the right, but only if it
  1849. isn't on the FPU stack, i.e. 1.0 or 0.0! }
  1850. if (left.nodetype=realconstn) and
  1851. (left.location.loc<>LOC_FPU) then
  1852. swapleftright;
  1853. cmpop:=false;
  1854. case nodetype of
  1855. addn : op:=A_FADDP;
  1856. muln : op:=A_FMULP;
  1857. subn : op:=A_FSUBP;
  1858. slashn : op:=A_FDIVP;
  1859. ltn,lten,gtn,gten,
  1860. equaln,unequaln : begin
  1861. op:=A_FCOMPP;
  1862. cmpop:=true;
  1863. end;
  1864. else CGMessage(type_e_mismatch);
  1865. end;
  1866. if (right.location.loc<>LOC_FPU) then
  1867. begin
  1868. if right.location.loc=LOC_CFPUREGISTER then
  1869. begin
  1870. emit_reg( A_FLD,S_NO,
  1871. correct_fpuregister(right.location.register,fpuvaroffset));
  1872. inc(fpuvaroffset);
  1873. end
  1874. else
  1875. floatload(pfloatdef(right.resulttype)^.typ,right.location.reference);
  1876. if (left.location.loc<>LOC_FPU) then
  1877. begin
  1878. if left.location.loc=LOC_CFPUREGISTER then
  1879. begin
  1880. emit_reg( A_FLD,S_NO,
  1881. correct_fpuregister(left.location.register,fpuvaroffset));
  1882. inc(fpuvaroffset);
  1883. end
  1884. else
  1885. floatload(pfloatdef(left.resulttype)^.typ,left.location.reference)
  1886. end
  1887. { left was on the stack => swap }
  1888. else
  1889. toggleflag(nf_swaped);
  1890. { releases the right reference }
  1891. del_reference(right.location.reference);
  1892. end
  1893. { the nominator in st0 }
  1894. else if (left.location.loc<>LOC_FPU) then
  1895. begin
  1896. if left.location.loc=LOC_CFPUREGISTER then
  1897. begin
  1898. emit_reg( A_FLD,S_NO,
  1899. correct_fpuregister(left.location.register,fpuvaroffset));
  1900. inc(fpuvaroffset);
  1901. end
  1902. else
  1903. floatload(pfloatdef(left.resulttype)^.typ,left.location.reference)
  1904. end
  1905. { fpu operands are always in the wrong order on the stack }
  1906. else
  1907. toggleflag(nf_swaped);
  1908. { releases the left reference }
  1909. if (left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  1910. del_reference(left.location.reference);
  1911. { if we swaped the tree nodes, then use the reverse operator }
  1912. if nf_swaped in flags then
  1913. begin
  1914. if (nodetype=slashn) then
  1915. op:=A_FDIVRP
  1916. else if (nodetype=subn) then
  1917. op:=A_FSUBRP;
  1918. end;
  1919. { to avoid the pentium bug
  1920. if (op=FDIVP) and (opt_processors=pentium) then
  1921. emitcall('EMUL_FDIVP')
  1922. else
  1923. }
  1924. { the Intel assemblers want operands }
  1925. if op<>A_FCOMPP then
  1926. begin
  1927. emit_reg_reg(op,S_NO,R_ST,R_ST1);
  1928. dec(fpuvaroffset);
  1929. end
  1930. else
  1931. begin
  1932. emit_none(op,S_NO);
  1933. dec(fpuvaroffset,2);
  1934. end;
  1935. { on comparison load flags }
  1936. if cmpop then
  1937. begin
  1938. if not(R_EAX in unused) then
  1939. begin
  1940. getexplicitregister32(R_EDI);
  1941. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  1942. end;
  1943. emit_reg(A_FNSTSW,S_NO,R_AX);
  1944. emit_none(A_SAHF,S_NO);
  1945. if not(R_EAX in unused) then
  1946. begin
  1947. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  1948. ungetregister32(R_EDI);
  1949. end;
  1950. if nf_swaped in flags then
  1951. begin
  1952. case nodetype of
  1953. equaln : resflags:=F_E;
  1954. unequaln : resflags:=F_NE;
  1955. ltn : resflags:=F_A;
  1956. lten : resflags:=F_AE;
  1957. gtn : resflags:=F_B;
  1958. gten : resflags:=F_BE;
  1959. end;
  1960. end
  1961. else
  1962. begin
  1963. case nodetype of
  1964. equaln : resflags:=F_E;
  1965. unequaln : resflags:=F_NE;
  1966. ltn : resflags:=F_B;
  1967. lten : resflags:=F_BE;
  1968. gtn : resflags:=F_A;
  1969. gten : resflags:=F_AE;
  1970. end;
  1971. end;
  1972. clear_location(location);
  1973. location.loc:=LOC_FLAGS;
  1974. location.resflags:=resflags;
  1975. cmpop:=false;
  1976. end
  1977. else
  1978. begin
  1979. clear_location(location);
  1980. location.loc:=LOC_FPU;
  1981. end;
  1982. end
  1983. {$ifdef SUPPORT_MMX}
  1984. else
  1985. { MMX Arrays }
  1986. if is_mmx_able_array(left.resulttype) then
  1987. begin
  1988. cmpop:=false;
  1989. mmxbase:=mmx_type(left.resulttype);
  1990. case nodetype of
  1991. addn : begin
  1992. if (cs_mmx_saturation in aktlocalswitches) then
  1993. begin
  1994. case mmxbase of
  1995. mmxs8bit:
  1996. op:=A_PADDSB;
  1997. mmxu8bit:
  1998. op:=A_PADDUSB;
  1999. mmxs16bit,mmxfixed16:
  2000. op:=A_PADDSB;
  2001. mmxu16bit:
  2002. op:=A_PADDUSW;
  2003. end;
  2004. end
  2005. else
  2006. begin
  2007. case mmxbase of
  2008. mmxs8bit,mmxu8bit:
  2009. op:=A_PADDB;
  2010. mmxs16bit,mmxu16bit,mmxfixed16:
  2011. op:=A_PADDW;
  2012. mmxs32bit,mmxu32bit:
  2013. op:=A_PADDD;
  2014. end;
  2015. end;
  2016. end;
  2017. muln : begin
  2018. case mmxbase of
  2019. mmxs16bit,mmxu16bit:
  2020. op:=A_PMULLW;
  2021. mmxfixed16:
  2022. op:=A_PMULHW;
  2023. end;
  2024. end;
  2025. subn : begin
  2026. if (cs_mmx_saturation in aktlocalswitches) then
  2027. begin
  2028. case mmxbase of
  2029. mmxs8bit:
  2030. op:=A_PSUBSB;
  2031. mmxu8bit:
  2032. op:=A_PSUBUSB;
  2033. mmxs16bit,mmxfixed16:
  2034. op:=A_PSUBSB;
  2035. mmxu16bit:
  2036. op:=A_PSUBUSW;
  2037. end;
  2038. end
  2039. else
  2040. begin
  2041. case mmxbase of
  2042. mmxs8bit,mmxu8bit:
  2043. op:=A_PSUBB;
  2044. mmxs16bit,mmxu16bit,mmxfixed16:
  2045. op:=A_PSUBW;
  2046. mmxs32bit,mmxu32bit:
  2047. op:=A_PSUBD;
  2048. end;
  2049. end;
  2050. end;
  2051. {
  2052. ltn,lten,gtn,gten,
  2053. equaln,unequaln :
  2054. begin
  2055. op:=A_CMP;
  2056. cmpop:=true;
  2057. end;
  2058. }
  2059. xorn:
  2060. op:=A_PXOR;
  2061. orn:
  2062. op:=A_POR;
  2063. andn:
  2064. op:=A_PAND;
  2065. else CGMessage(type_e_mismatch);
  2066. end;
  2067. { left and right no register? }
  2068. { then one must be demanded }
  2069. if (left.location.loc<>LOC_MMXREGISTER) and
  2070. (right.location.loc<>LOC_MMXREGISTER) then
  2071. begin
  2072. { register variable ? }
  2073. if (left.location.loc=LOC_CMMXREGISTER) then
  2074. begin
  2075. { it is OK if this is the destination }
  2076. if is_in_dest then
  2077. begin
  2078. hregister:=location.register;
  2079. emit_reg_reg(A_MOVQ,S_NO,left.location.register,
  2080. hregister);
  2081. end
  2082. else
  2083. begin
  2084. hregister:=getregistermmx;
  2085. emit_reg_reg(A_MOVQ,S_NO,left.location.register,
  2086. hregister);
  2087. end
  2088. end
  2089. else
  2090. begin
  2091. del_reference(left.location.reference);
  2092. if is_in_dest then
  2093. begin
  2094. hregister:=location.register;
  2095. emit_ref_reg(A_MOVQ,S_NO,
  2096. newreference(left.location.reference),hregister);
  2097. end
  2098. else
  2099. begin
  2100. hregister:=getregistermmx;
  2101. emit_ref_reg(A_MOVQ,S_NO,
  2102. newreference(left.location.reference),hregister);
  2103. end;
  2104. end;
  2105. clear_location(location);
  2106. location.loc:=LOC_MMXREGISTER;
  2107. location.register:=hregister;
  2108. end
  2109. else
  2110. { if on the right the register then swap }
  2111. if (right.location.loc=LOC_MMXREGISTER) then
  2112. begin
  2113. swap_location(location,right.location);
  2114. { newly swapped also set swapped flag }
  2115. toggleflag(nf_swaped);
  2116. end;
  2117. { at this point, location.loc should be LOC_MMXREGISTER }
  2118. { and location.register should be a valid register }
  2119. { containing the left result }
  2120. if right.location.loc<>LOC_MMXREGISTER then
  2121. begin
  2122. if (nodetype=subn) and (nf_swaped in flags) then
  2123. begin
  2124. if right.location.loc=LOC_CMMXREGISTER then
  2125. begin
  2126. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  2127. emit_reg_reg(op,S_NO,location.register,R_MM0);
  2128. emit_reg_reg(A_MOVQ,S_NO,R_MM7,location.register);
  2129. end
  2130. else
  2131. begin
  2132. emit_ref_reg(A_MOVQ,S_NO,
  2133. newreference(right.location.reference),R_MM7);
  2134. emit_reg_reg(op,S_NO,location.register,
  2135. R_MM7);
  2136. emit_reg_reg(A_MOVQ,S_NO,
  2137. R_MM7,location.register);
  2138. del_reference(right.location.reference);
  2139. end;
  2140. end
  2141. else
  2142. begin
  2143. if (right.location.loc=LOC_CREGISTER) then
  2144. begin
  2145. emit_reg_reg(op,S_NO,right.location.register,
  2146. location.register);
  2147. end
  2148. else
  2149. begin
  2150. emit_ref_reg(op,S_NO,newreference(
  2151. right.location.reference),location.register);
  2152. del_reference(right.location.reference);
  2153. end;
  2154. end;
  2155. end
  2156. else
  2157. begin
  2158. { when swapped another result register }
  2159. if (nodetype=subn) and (nf_swaped in flags) then
  2160. begin
  2161. emit_reg_reg(op,S_NO,
  2162. location.register,right.location.register);
  2163. swap_location(location,right.location);
  2164. { newly swapped also set swapped flag }
  2165. { just to maintain ordering }
  2166. toggleflag(nf_swaped);
  2167. end
  2168. else
  2169. begin
  2170. emit_reg_reg(op,S_NO,
  2171. right.location.register,
  2172. location.register);
  2173. end;
  2174. ungetregistermmx(right.location.register);
  2175. end;
  2176. end
  2177. {$endif SUPPORT_MMX}
  2178. else CGMessage(type_e_mismatch);
  2179. end;
  2180. SetResultLocation(cmpop,unsigned);
  2181. end;
  2182. begin
  2183. caddnode:=ti386addnode;
  2184. end.
  2185. {
  2186. $Log$
  2187. Revision 1.1 2000-10-15 09:33:31 peter
  2188. * moved n386*.pas to i386/ cpu_target dir
  2189. Revision 1.6 2000/10/14 10:14:47 peter
  2190. * moehrendorf oct 2000 rewrite
  2191. Revision 1.5 2000/09/30 16:08:45 peter
  2192. * more cg11 updates
  2193. Revision 1.4 2000/09/24 15:06:18 peter
  2194. * use defines.inc
  2195. Revision 1.3 2000/09/22 22:42:52 florian
  2196. * more fixes
  2197. Revision 1.2 2000/09/21 12:24:22 jonas
  2198. * small fix to my changes for full boolean evaluation support (moved
  2199. opsize determination for boolean operations back in boolean
  2200. processing block)
  2201. + full boolean evaluation support (from cg386add)
  2202. Revision 1.1 2000/09/20 21:23:32 florian
  2203. * initial revision
  2204. }