cg386add.pas 108 KB

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