cg386add.pas 107 KB

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