cg386add.pas 108 KB

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