cg386add.pas 108 KB

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