n386add.pas 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012
  1. {
  2. $Id$
  3. Copyright (c) 2000 by Florian Klaempfl
  4. Code generation for add nodes on the i386
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit n386add;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,nadd,cpubase;
  23. type
  24. ti386addnode = class(taddnode)
  25. procedure pass_2;override;
  26. function getresflags(unsigned : boolean) : tresflags;
  27. procedure SetResultLocation(cmpop,unsigned : boolean);
  28. protected
  29. function first_addstring : tnode; override;
  30. private
  31. procedure second_addstring;
  32. end;
  33. implementation
  34. uses
  35. globtype,systems,
  36. cutils,verbose,globals,widestr,
  37. symconst,symdef,aasm,types,htypechk,
  38. cgbase,temp_gen,pass_2,regvars,
  39. cpuasm,
  40. ncon,nset,
  41. tainst,cga,ncgutil,n386util,tgcpu;
  42. function ti386addnode.getresflags(unsigned : boolean) : tresflags;
  43. begin
  44. case nodetype of
  45. equaln : getresflags:=F_E;
  46. unequaln : getresflags:=F_NE;
  47. else
  48. if not(unsigned) then
  49. begin
  50. if nf_swaped in flags then
  51. case nodetype of
  52. ltn : getresflags:=F_G;
  53. lten : getresflags:=F_GE;
  54. gtn : getresflags:=F_L;
  55. gten : getresflags:=F_LE;
  56. end
  57. else
  58. case nodetype of
  59. ltn : getresflags:=F_L;
  60. lten : getresflags:=F_LE;
  61. gtn : getresflags:=F_G;
  62. gten : getresflags:=F_GE;
  63. end;
  64. end
  65. else
  66. begin
  67. if nf_swaped in flags then
  68. case nodetype of
  69. ltn : getresflags:=F_A;
  70. lten : getresflags:=F_AE;
  71. gtn : getresflags:=F_B;
  72. gten : getresflags:=F_BE;
  73. end
  74. else
  75. case nodetype of
  76. ltn : getresflags:=F_B;
  77. lten : getresflags:=F_BE;
  78. gtn : getresflags:=F_A;
  79. gten : getresflags:=F_AE;
  80. end;
  81. end;
  82. end;
  83. end;
  84. procedure ti386addnode.SetResultLocation(cmpop,unsigned : boolean);
  85. begin
  86. { remove temporary location if not a set or string }
  87. { that's a bad hack (FK) who did this ? }
  88. if (left.resulttype.def.deftype<>stringdef) and
  89. ((left.resulttype.def.deftype<>setdef) or (tsetdef(left.resulttype.def).settype=smallset)) and
  90. (left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  91. ungetiftemp(left.location.reference);
  92. if (right.resulttype.def.deftype<>stringdef) and
  93. ((right.resulttype.def.deftype<>setdef) or (tsetdef(right.resulttype.def).settype=smallset)) and
  94. (right.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  95. ungetiftemp(right.location.reference);
  96. { in case of comparison operation the put result in the flags }
  97. if cmpop then
  98. begin
  99. clear_location(location);
  100. location.loc:=LOC_FLAGS;
  101. location.resflags:=getresflags(unsigned);
  102. end;
  103. end;
  104. {*****************************************************************************
  105. Addstring
  106. *****************************************************************************}
  107. { note: if you implemented an fpc_shortstr_concat similar to the }
  108. { one in i386.inc, you have to override first_addstring like in }
  109. { ti386addnode.first_string and implement the shortstring concat }
  110. { manually! The generic routine is different from the i386 one (JM) }
  111. function ti386addnode.first_addstring : tnode;
  112. begin
  113. { special cases for shortstrings, handled in pass_2 (JM) }
  114. { can't handle fpc_shortstr_compare with compilerproc either because it }
  115. { returns its results in the flags instead of in eax }
  116. if (((nodetype = addn) and
  117. is_shortstring(resulttype.def)) or
  118. ((nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) and
  119. is_shortstring(left.resulttype.def))) then
  120. begin
  121. if nodetype = addn then
  122. location.loc := LOC_MEM
  123. else
  124. location.loc := LOC_FLAGS;
  125. calcregisters(self,0,0,0);
  126. result := nil;
  127. exit;
  128. end;
  129. { otherwise, use the generic code }
  130. result := inherited first_addstring;
  131. end;
  132. procedure ti386addnode.second_addstring;
  133. var
  134. pushedregs : tpushed;
  135. href : treference;
  136. pushed,
  137. cmpop : boolean;
  138. regstopush : byte;
  139. begin
  140. { string operations are not commutative }
  141. if nf_swaped in flags then
  142. swapleftright;
  143. case tstringdef(left.resulttype.def).string_typ of
  144. st_shortstring:
  145. begin
  146. case nodetype of
  147. addn:
  148. begin
  149. cmpop:=false;
  150. secondpass(left);
  151. { if str_concat is set in expr
  152. s:=s+ ... no need to create a temp string (PM) }
  153. { the tempstring can also come from a typeconversion }
  154. { or a function result, so simply check for a }
  155. { temp of 256 bytes(JM) }
  156. if not(istemp(left.location.reference) and
  157. (getsizeoftemp(left.location.reference) = 256)) and
  158. not(nf_use_strconcat in flags) then
  159. begin
  160. { can only reference be }
  161. { string in register would be funny }
  162. { therefore produce a temporary string }
  163. gettempofsizereference(256,href);
  164. copyshortstring(href,left.location.reference,255,false,true);
  165. { release the registers }
  166. { done by copyshortstring now (JM) }
  167. { del_reference(left.location.reference); }
  168. ungetiftemp(left.location.reference);
  169. { does not hurt: }
  170. clear_location(left.location);
  171. left.location.loc:=LOC_MEM;
  172. left.location.reference:=href;
  173. end;
  174. secondpass(right);
  175. { on the right we do not need the register anymore too }
  176. { Instead of releasing them already, simply do not }
  177. { push them (so the release is in the right place, }
  178. { because emitpushreferenceaddr doesn't need extra }
  179. { registers) (JM) }
  180. regstopush := $ff;
  181. remove_non_regvars_from_loc(right.location,
  182. regstopush);
  183. pushusedregisters(pushedregs,regstopush);
  184. { push the maximum possible length of the result }
  185. emitpushreferenceaddr(left.location.reference);
  186. { the optimizer can more easily put the }
  187. { deallocations in the right place if it happens }
  188. { too early than when it happens too late (if }
  189. { the pushref needs a "lea (..),edi; push edi") }
  190. del_reference(right.location.reference);
  191. emitpushreferenceaddr(right.location.reference);
  192. saveregvars(regstopush);
  193. emitcall('FPC_SHORTSTR_CONCAT');
  194. ungetiftemp(right.location.reference);
  195. maybe_loadself;
  196. popusedregisters(pushedregs);
  197. set_location(location,left.location);
  198. end;
  199. ltn,lten,gtn,gten,equaln,unequaln :
  200. begin
  201. cmpop := true;
  202. pushusedregisters(pushedregs,$ff);
  203. secondpass(left);
  204. emitpushreferenceaddr(left.location.reference);
  205. del_reference(left.location.reference);
  206. secondpass(right);
  207. emitpushreferenceaddr(right.location.reference);
  208. del_reference(right.location.reference);
  209. saveregvars($ff);
  210. emitcall('FPC_SHORTSTR_COMPARE');
  211. maybe_loadself;
  212. popusedregisters(pushedregs);
  213. ungetiftemp(left.location.reference);
  214. ungetiftemp(right.location.reference);
  215. end;
  216. end;
  217. SetResultLocation(cmpop,true);
  218. end;
  219. else
  220. { rest should be handled in first pass (JM) }
  221. internalerror(200108303);
  222. end;
  223. end;
  224. {*****************************************************************************
  225. pass_2
  226. *****************************************************************************}
  227. procedure ti386addnode.pass_2;
  228. { is also being used for xor, and "mul", "sub, or and comparative }
  229. { operators }
  230. label do_normal;
  231. var
  232. unusedregisters : tregisterset;
  233. usablecount : byte;
  234. hregister,hregister2 : tregister;
  235. noswap,popeax,popedx,
  236. pushed,pushedfpu,
  237. mboverflow,cmpop : boolean;
  238. op,op2 : tasmop;
  239. resflags : tresflags;
  240. otl,ofl : tasmlabel;
  241. power : longint;
  242. opsize : topsize;
  243. hl4: tasmlabel;
  244. hr : preference;
  245. { true, if unsigned types are compared }
  246. unsigned : boolean;
  247. { true, if a small set is handled with the longint code }
  248. is_set : boolean;
  249. { is_in_dest if the result is put directly into }
  250. { the resulting refernce or varregister }
  251. is_in_dest : boolean;
  252. { true, if for sets subtractions the extra not should generated }
  253. extra_not : boolean;
  254. {$ifdef SUPPORT_MMX}
  255. mmxbase : tmmxtype;
  256. {$endif SUPPORT_MMX}
  257. pushedreg : tpushed;
  258. regstopush: byte;
  259. procedure firstjmp64bitcmp;
  260. var
  261. oldnodetype : tnodetype;
  262. begin
  263. load_all_regvars(exprasmlist);
  264. { the jump the sequence is a little bit hairy }
  265. case nodetype of
  266. ltn,gtn:
  267. begin
  268. emitjmp(flags_to_cond(getresflags(unsigned)),truelabel);
  269. { cheat a little bit for the negative test }
  270. toggleflag(nf_swaped);
  271. emitjmp(flags_to_cond(getresflags(unsigned)),falselabel);
  272. toggleflag(nf_swaped);
  273. end;
  274. lten,gten:
  275. begin
  276. oldnodetype:=nodetype;
  277. if nodetype=lten then
  278. nodetype:=ltn
  279. else
  280. nodetype:=gtn;
  281. emitjmp(flags_to_cond(getresflags(unsigned)),truelabel);
  282. { cheat for the negative test }
  283. if nodetype=ltn then
  284. nodetype:=gtn
  285. else
  286. nodetype:=ltn;
  287. emitjmp(flags_to_cond(getresflags(unsigned)),falselabel);
  288. nodetype:=oldnodetype;
  289. end;
  290. equaln:
  291. emitjmp(C_NE,falselabel);
  292. unequaln:
  293. emitjmp(C_NE,truelabel);
  294. end;
  295. end;
  296. procedure secondjmp64bitcmp;
  297. begin
  298. { the jump the sequence is a little bit hairy }
  299. case nodetype of
  300. ltn,gtn,lten,gten:
  301. begin
  302. { the comparisaion of the low dword have to be }
  303. { always unsigned! }
  304. emitjmp(flags_to_cond(getresflags(true)),truelabel);
  305. emitjmp(C_None,falselabel);
  306. end;
  307. equaln:
  308. begin
  309. emitjmp(C_NE,falselabel);
  310. emitjmp(C_None,truelabel);
  311. end;
  312. unequaln:
  313. begin
  314. emitjmp(C_NE,truelabel);
  315. emitjmp(C_None,falselabel);
  316. end;
  317. end;
  318. end;
  319. begin
  320. { to make it more readable, string and set (not smallset!) have their
  321. own procedures }
  322. case left.resulttype.def.deftype of
  323. stringdef : begin
  324. second_addstring;
  325. exit;
  326. end;
  327. setdef : begin
  328. { normalsets are handled separate }
  329. if not(tsetdef(left.resulttype.def).settype=smallset) then
  330. begin
  331. { should be handled in pass 1 (JM) }
  332. internalerror(200109041);
  333. end;
  334. end;
  335. end;
  336. { defaults }
  337. unsigned:=false;
  338. is_in_dest:=false;
  339. extra_not:=false;
  340. noswap:=false;
  341. opsize:=S_L;
  342. { are we a (small)set, must be set here because the side can be
  343. swapped ! (PFV) }
  344. is_set:=(left.resulttype.def.deftype=setdef);
  345. { calculate the operator which is more difficult }
  346. firstcomplex(self);
  347. { handling boolean expressions extra: }
  348. if is_boolean(left.resulttype.def) and
  349. is_boolean(right.resulttype.def) then
  350. begin
  351. if (torddef(left.resulttype.def).typ=bool8bit) or
  352. (torddef(right.resulttype.def).typ=bool8bit) then
  353. opsize:=S_B
  354. else
  355. if (torddef(left.resulttype.def).typ=bool16bit) or
  356. (torddef(right.resulttype.def).typ=bool16bit) then
  357. opsize:=S_W
  358. else
  359. opsize:=S_L;
  360. if (cs_full_boolean_eval in aktlocalswitches) or
  361. (nodetype in
  362. [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  363. begin
  364. if left.nodetype in [ordconstn,realconstn] then
  365. swapleftright;
  366. if left.location.loc=LOC_JUMP then
  367. begin
  368. otl:=truelabel;
  369. getlabel(truelabel);
  370. ofl:=falselabel;
  371. getlabel(falselabel);
  372. end;
  373. secondpass(left);
  374. { if in flags then copy first to register, because the
  375. flags can be destroyed }
  376. case left.location.loc of
  377. LOC_FLAGS:
  378. locflags2reg(left.location,opsize);
  379. LOC_JUMP:
  380. locjump2reg(left.location,opsize, otl, ofl);
  381. end;
  382. set_location(location,left.location);
  383. pushed:=maybe_push(right.registers32,self,false);
  384. if right.location.loc=LOC_JUMP then
  385. begin
  386. otl:=truelabel;
  387. getlabel(truelabel);
  388. ofl:=falselabel;
  389. getlabel(falselabel);
  390. end;
  391. secondpass(right);
  392. if pushed then
  393. begin
  394. restore(self,false);
  395. set_location(left.location,location);
  396. end;
  397. case right.location.loc of
  398. LOC_FLAGS:
  399. locflags2reg(right.location,opsize);
  400. LOC_JUMP:
  401. locjump2reg(right.location,opsize,otl,ofl);
  402. end;
  403. goto do_normal;
  404. end;
  405. case nodetype of
  406. andn,
  407. orn : begin
  408. clear_location(location);
  409. location.loc:=LOC_JUMP;
  410. cmpop:=false;
  411. case nodetype of
  412. andn : begin
  413. otl:=truelabel;
  414. getlabel(truelabel);
  415. secondpass(left);
  416. maketojumpbool(left,lr_load_regvars);
  417. emitlab(truelabel);
  418. truelabel:=otl;
  419. end;
  420. orn : begin
  421. ofl:=falselabel;
  422. getlabel(falselabel);
  423. secondpass(left);
  424. maketojumpbool(left,lr_load_regvars);
  425. emitlab(falselabel);
  426. falselabel:=ofl;
  427. end;
  428. else
  429. CGMessage(type_e_mismatch);
  430. end;
  431. secondpass(right);
  432. maketojumpbool(right,lr_load_regvars);
  433. end;
  434. else
  435. CGMessage(type_e_mismatch);
  436. end
  437. end
  438. else
  439. begin
  440. { in case of constant put it to the left }
  441. if (left.nodetype=ordconstn) then
  442. swapleftright;
  443. secondpass(left);
  444. { this will be complicated as
  445. a lot of code below assumes that
  446. location and left.location are the same }
  447. {$ifdef test_dest_loc}
  448. if dest_loc_known and (dest_loc_tree=p) and
  449. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  450. begin
  451. set_location(location,dest_loc);
  452. in_dest_loc:=true;
  453. is_in_dest:=true;
  454. end
  455. else
  456. {$endif test_dest_loc}
  457. set_location(location,left.location);
  458. { are too few registers free? }
  459. pushed:=maybe_push(right.registers32,self,is_64bitint(left.resulttype.def));
  460. if location.loc=LOC_FPU then
  461. pushedfpu:=maybe_pushfpu(right.registersfpu,self)
  462. else
  463. pushedfpu:=false;
  464. secondpass(right);
  465. if pushed then
  466. begin
  467. restore(self,is_64bitint(left.resulttype.def));
  468. set_location(left.location,location);
  469. end;
  470. if (left.resulttype.def.deftype=pointerdef) or
  471. (right.resulttype.def.deftype=pointerdef) or
  472. (is_class_or_interface(right.resulttype.def) and is_class_or_interface(left.resulttype.def)) or
  473. (left.resulttype.def.deftype=classrefdef) or
  474. (left.resulttype.def.deftype=procvardef) or
  475. ((left.resulttype.def.deftype=enumdef) and
  476. (left.resulttype.def.size=4)) or
  477. ((left.resulttype.def.deftype=orddef) and
  478. (torddef(left.resulttype.def).typ=s32bit)) or
  479. ((right.resulttype.def.deftype=orddef) and
  480. (torddef(right.resulttype.def).typ=s32bit)) or
  481. ((left.resulttype.def.deftype=orddef) and
  482. (torddef(left.resulttype.def).typ=u32bit)) or
  483. ((right.resulttype.def.deftype=orddef) and
  484. (torddef(right.resulttype.def).typ=u32bit)) or
  485. { as well as small sets }
  486. is_set then
  487. begin
  488. do_normal:
  489. mboverflow:=false;
  490. cmpop:=false;
  491. unsigned := not(is_signed(left.resulttype.def)) or
  492. not(is_signed(right.resulttype.def));
  493. case nodetype of
  494. addn : begin
  495. { this is a really ugly hack!!!!!!!!!! }
  496. { this could be done later using EDI }
  497. { as it is done for subn }
  498. { instead of two registers!!!! }
  499. if is_set then
  500. begin
  501. { adding elements is not commutative }
  502. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  503. swapleftright;
  504. { are we adding set elements ? }
  505. if right.nodetype=setelementn then
  506. begin
  507. { no range support for smallsets! }
  508. if assigned(tsetelementnode(right).right) then
  509. internalerror(43244);
  510. { bts requires both elements to be registers }
  511. if left.location.loc in [LOC_MEM,LOC_REFERENCE] then
  512. begin
  513. ungetiftemp(left.location.reference);
  514. del_location(left.location);
  515. {!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!}
  516. hregister:=getregisterint;
  517. emit_ref_reg(A_MOV,opsize,
  518. newreference(left.location.reference),hregister);
  519. clear_location(left.location);
  520. left.location.loc:=LOC_REGISTER;
  521. left.location.register:=hregister;
  522. set_location(location,left.location);
  523. end;
  524. if right.location.loc in [LOC_MEM,LOC_REFERENCE] then
  525. begin
  526. ungetiftemp(right.location.reference);
  527. del_location(right.location);
  528. hregister:=getregisterint;
  529. emit_ref_reg(A_MOV,opsize,
  530. newreference(right.location.reference),hregister);
  531. clear_location(right.location);
  532. right.location.loc:=LOC_REGISTER;
  533. right.location.register:=hregister;
  534. end;
  535. op:=A_BTS;
  536. noswap:=true;
  537. end
  538. else
  539. op:=A_OR;
  540. mboverflow:=false;
  541. unsigned:=false;
  542. end
  543. else
  544. begin
  545. op:=A_ADD;
  546. mboverflow:=true;
  547. end;
  548. end;
  549. symdifn : begin
  550. { the symetric diff is only for sets }
  551. if is_set then
  552. begin
  553. op:=A_XOR;
  554. mboverflow:=false;
  555. unsigned:=false;
  556. end
  557. else
  558. CGMessage(type_e_mismatch);
  559. end;
  560. muln : begin
  561. if is_set then
  562. begin
  563. op:=A_AND;
  564. mboverflow:=false;
  565. unsigned:=false;
  566. end
  567. else
  568. begin
  569. if unsigned then
  570. op:=A_MUL
  571. else
  572. op:=A_IMUL;
  573. mboverflow:=true;
  574. end;
  575. end;
  576. subn : begin
  577. if is_set then
  578. begin
  579. op:=A_AND;
  580. mboverflow:=false;
  581. unsigned:=false;
  582. If (not (nf_swaped in flags)) and
  583. (right.nodetype = setconstn) then
  584. right.location.reference.offset := not(right.location.reference.offset)
  585. Else If (nf_swaped in flags) and
  586. (left.nodetype = setconstn) then
  587. left.location.reference.offset := not(left.location.reference.offset)
  588. Else
  589. extra_not:=true;
  590. end
  591. else
  592. begin
  593. op:=A_SUB;
  594. mboverflow:=true;
  595. end;
  596. end;
  597. ltn,lten,
  598. gtn,gten,
  599. equaln,unequaln : begin
  600. If is_set Then
  601. Case nodetype of
  602. lten,gten:
  603. Begin
  604. If nodetype = lten then
  605. swapleftright;
  606. if left.location.loc in [LOC_MEM,LOC_REFERENCE] then
  607. begin
  608. ungetiftemp(left.location.reference);
  609. del_reference(left.location.reference);
  610. hregister:=getregisterint;
  611. emit_ref_reg(A_MOV,opsize,
  612. newreference(left.location.reference),hregister);
  613. clear_location(left.location);
  614. left.location.loc:=LOC_REGISTER;
  615. left.location.register:=hregister;
  616. set_location(location,left.location);
  617. end
  618. else
  619. if left.location.loc = LOC_CREGISTER Then
  620. {save the register var in a temp register, because
  621. its value is going to be modified}
  622. begin
  623. hregister := getregisterint;
  624. emit_reg_reg(A_MOV,opsize,
  625. left.location.register,hregister);
  626. clear_location(left.location);
  627. left.location.loc:=LOC_REGISTER;
  628. left.location.register:=hregister;
  629. set_location(location,left.location);
  630. end;
  631. {here, left.location should be LOC_REGISTER}
  632. If right.location.loc in [LOC_MEM,LOC_REFERENCE] Then
  633. emit_ref_reg(A_AND,opsize,
  634. newreference(right.location.reference),left.location.register)
  635. Else
  636. emit_reg_reg(A_AND,opsize,
  637. right.location.register,left.location.register);
  638. {warning: ugly hack ahead: we need a "jne" after the cmp, so
  639. change the nodetype from lten/gten to equaln}
  640. nodetype := equaln
  641. End;
  642. {no < or > support for sets}
  643. ltn,gtn: CGMessage(type_e_mismatch);
  644. End;
  645. op:=A_CMP;
  646. cmpop:=true;
  647. end;
  648. xorn : op:=A_XOR;
  649. orn : op:=A_OR;
  650. andn : op:=A_AND;
  651. else
  652. CGMessage(type_e_mismatch);
  653. end;
  654. { filter MUL, which requires special handling }
  655. if op=A_MUL then
  656. begin
  657. popeax:=false;
  658. popedx:=false;
  659. { here you need to free the symbol first }
  660. { left.location and right.location must }
  661. { only be freed when they are really released, }
  662. { because the optimizer NEEDS correct regalloc }
  663. { info!!! (JM) }
  664. clear_location(location);
  665. { the location.register will be filled in later (JM) }
  666. location.loc:=LOC_REGISTER;
  667. {$IfNDef NoShlMul}
  668. if right.nodetype=ordconstn then
  669. swapleftright;
  670. If (left.nodetype = ordconstn) and
  671. ispowerof2(tordconstnode(left).value, power) and
  672. not(cs_check_overflow in aktlocalswitches) then
  673. Begin
  674. { This release will be moved after the next }
  675. { instruction by the optimizer. No need to }
  676. { release left.location, since it's a }
  677. { constant (JM) }
  678. release_loc(right.location);
  679. location.register := getregisterint;
  680. emitloadord2reg(right.location,torddef(u32bittype.def),location.register,false);
  681. emit_const_reg(A_SHL,S_L,power,location.register)
  682. End
  683. Else
  684. Begin
  685. {$EndIf NoShlMul}
  686. regstopush := $ff;
  687. remove_non_regvars_from_loc(right.location,regstopush);
  688. remove_non_regvars_from_loc(left.location,regstopush);
  689. { now, regstopush does NOT contain EAX and/or EDX if they are }
  690. { used in either the left or the right location, excepts if }
  691. {they are regvars. It DOES contain them if they are used in }
  692. { another location (JM) }
  693. if not(R_EAX in unused) and ((regstopush and ($80 shr byte(R_EAX))) <> 0) then
  694. begin
  695. emit_reg(A_PUSH,S_L,R_EAX);
  696. popeax:=true;
  697. end;
  698. if not(R_EDX in unused) and ((regstopush and ($80 shr byte(R_EDX))) <> 0) then
  699. begin
  700. emit_reg(A_PUSH,S_L,R_EDX);
  701. popedx:=true;
  702. end;
  703. { left.location can be R_EAX !!! }
  704. getexplicitregister32(R_EDI);
  705. { load the left value }
  706. emitloadord2reg(left.location,torddef(u32bittype.def),R_EDI,true);
  707. release_loc(left.location);
  708. { allocate EAX }
  709. if R_EAX in unused then
  710. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  711. { load he right value }
  712. emitloadord2reg(right.location,torddef(u32bittype.def),R_EAX,true);
  713. release_loc(right.location);
  714. { allocate EAX if it isn't yet allocated (JM) }
  715. if (R_EAX in unused) then
  716. exprasmList.concat(Tairegalloc.Alloc(R_EAX));
  717. { also allocate EDX, since it is also modified by }
  718. { a mul (JM) }
  719. if R_EDX in unused then
  720. exprasmList.concat(Tairegalloc.Alloc(R_EDX));
  721. emit_reg(A_MUL,S_L,R_EDI);
  722. ungetregister32(R_EDI);
  723. if R_EDX in unused then
  724. exprasmList.concat(Tairegalloc.DeAlloc(R_EDX));
  725. if R_EAX in unused then
  726. exprasmList.concat(Tairegalloc.DeAlloc(R_EAX));
  727. location.register := getregisterint;
  728. emit_reg_reg(A_MOV,S_L,R_EAX,location.register);
  729. if popedx then
  730. emit_reg(A_POP,S_L,R_EDX);
  731. if popeax then
  732. emit_reg(A_POP,S_L,R_EAX);
  733. {$IfNDef NoShlMul}
  734. End;
  735. {$endif NoShlMul}
  736. SetResultLocation(false,true);
  737. exit;
  738. end;
  739. { Convert flags to register first }
  740. if (left.location.loc=LOC_FLAGS) then
  741. locflags2reg(left.location,opsize);
  742. if (right.location.loc=LOC_FLAGS) then
  743. locflags2reg(right.location,opsize);
  744. { left and right no register? }
  745. { then one must be demanded }
  746. if (left.location.loc<>LOC_REGISTER) and
  747. (right.location.loc<>LOC_REGISTER) then
  748. begin
  749. { register variable ? }
  750. if (left.location.loc=LOC_CREGISTER) then
  751. begin
  752. { it is OK if this is the destination }
  753. if is_in_dest then
  754. begin
  755. hregister:=location.register;
  756. emit_reg_reg(A_MOV,opsize,left.location.register,
  757. hregister);
  758. end
  759. else
  760. if cmpop then
  761. begin
  762. { do not disturb the register }
  763. hregister:=location.register;
  764. end
  765. else
  766. begin
  767. case opsize of
  768. S_L : hregister:=getregisterint;
  769. S_B : hregister:=reg32toreg8(getregisterint);
  770. end;
  771. emit_reg_reg(A_MOV,opsize,left.location.register,
  772. hregister);
  773. end
  774. end
  775. else
  776. begin
  777. ungetiftemp(left.location.reference);
  778. del_reference(left.location.reference);
  779. if is_in_dest then
  780. begin
  781. hregister:=location.register;
  782. emit_ref_reg(A_MOV,opsize,
  783. newreference(left.location.reference),hregister);
  784. end
  785. else
  786. begin
  787. { first give free, then demand new register }
  788. case opsize of
  789. S_L : hregister:=getregisterint;
  790. S_W : hregister:=reg32toreg16(getregisterint);
  791. S_B : hregister:=reg32toreg8(getregisterint);
  792. end;
  793. emit_ref_reg(A_MOV,opsize,
  794. newreference(left.location.reference),hregister);
  795. end;
  796. end;
  797. clear_location(location);
  798. location.loc:=LOC_REGISTER;
  799. location.register:=hregister;
  800. end
  801. else
  802. { if on the right the register then swap }
  803. if not(noswap) and (right.location.loc=LOC_REGISTER) then
  804. begin
  805. swap_location(location,right.location);
  806. { newly swapped also set swapped flag }
  807. toggleflag(nf_swaped);
  808. end;
  809. { at this point, location.loc should be LOC_REGISTER }
  810. { and location.register should be a valid register }
  811. { containing the left result }
  812. if right.location.loc<>LOC_REGISTER then
  813. begin
  814. if (nodetype=subn) and (nf_swaped in flags) then
  815. begin
  816. if right.location.loc=LOC_CREGISTER then
  817. begin
  818. if extra_not then
  819. emit_reg(A_NOT,opsize,location.register);
  820. getexplicitregister32(R_EDI);
  821. emit_reg_reg(A_MOV,opsize,right.location.register,R_EDI);
  822. emit_reg_reg(op,opsize,location.register,R_EDI);
  823. emit_reg_reg(A_MOV,opsize,R_EDI,location.register);
  824. ungetregister32(R_EDI);
  825. end
  826. else
  827. begin
  828. if extra_not then
  829. emit_reg(A_NOT,opsize,location.register);
  830. getexplicitregister32(R_EDI);
  831. emit_ref_reg(A_MOV,opsize,
  832. newreference(right.location.reference),R_EDI);
  833. emit_reg_reg(op,opsize,location.register,R_EDI);
  834. emit_reg_reg(A_MOV,opsize,R_EDI,location.register);
  835. ungetregister32(R_EDI);
  836. ungetiftemp(right.location.reference);
  837. del_reference(right.location.reference);
  838. end;
  839. end
  840. else
  841. begin
  842. if (right.nodetype=ordconstn) and
  843. (op=A_CMP) and
  844. (tordconstnode(right).value=0) then
  845. begin
  846. emit_reg_reg(A_TEST,opsize,location.register,
  847. location.register);
  848. end
  849. else if (right.nodetype=ordconstn) and
  850. (op=A_ADD) and
  851. (tordconstnode(right).value=1) and
  852. not(cs_check_overflow in aktlocalswitches) then
  853. begin
  854. emit_reg(A_INC,opsize,
  855. location.register);
  856. end
  857. else if (right.nodetype=ordconstn) and
  858. (op=A_SUB) and
  859. (tordconstnode(right).value=1) and
  860. not(cs_check_overflow in aktlocalswitches) then
  861. begin
  862. emit_reg(A_DEC,opsize,
  863. location.register);
  864. end
  865. else if (right.nodetype=ordconstn) and
  866. (op=A_IMUL) and
  867. (ispowerof2(tordconstnode(right).value,power)) and
  868. not(cs_check_overflow in aktlocalswitches) then
  869. begin
  870. emit_const_reg(A_SHL,opsize,power,
  871. location.register);
  872. end
  873. else
  874. begin
  875. if (right.location.loc=LOC_CREGISTER) then
  876. begin
  877. if extra_not then
  878. begin
  879. getexplicitregister32(R_EDI);
  880. emit_reg_reg(A_MOV,S_L,right.location.register,R_EDI);
  881. emit_reg(A_NOT,S_L,R_EDI);
  882. emit_reg_reg(A_AND,S_L,R_EDI,
  883. location.register);
  884. ungetregister32(R_EDI);
  885. end
  886. else
  887. begin
  888. emit_reg_reg(op,opsize,right.location.register,
  889. location.register);
  890. end;
  891. end
  892. else
  893. begin
  894. if extra_not then
  895. begin
  896. getexplicitregister32(R_EDI);
  897. emit_ref_reg(A_MOV,S_L,newreference(
  898. right.location.reference),R_EDI);
  899. emit_reg(A_NOT,S_L,R_EDI);
  900. emit_reg_reg(A_AND,S_L,R_EDI,
  901. location.register);
  902. ungetregister32(R_EDI);
  903. end
  904. else
  905. begin
  906. emit_ref_reg(op,opsize,newreference(
  907. right.location.reference),location.register);
  908. end;
  909. ungetiftemp(right.location.reference);
  910. del_reference(right.location.reference);
  911. end;
  912. end;
  913. end;
  914. end
  915. else
  916. begin
  917. { when swapped another result register }
  918. if (nodetype=subn) and (nf_swaped in flags) then
  919. begin
  920. if extra_not then
  921. emit_reg(A_NOT,S_L,location.register);
  922. emit_reg_reg(op,opsize,
  923. location.register,right.location.register);
  924. swap_location(location,right.location);
  925. { newly swapped also set swapped flag }
  926. { just to maintain ordering }
  927. toggleflag(nf_swaped);
  928. end
  929. else
  930. begin
  931. if extra_not then
  932. emit_reg(A_NOT,S_L,right.location.register);
  933. emit_reg_reg(op,opsize,
  934. right.location.register,
  935. location.register);
  936. end;
  937. case opsize of
  938. S_L : ungetregister32(right.location.register);
  939. S_B : ungetregister32(reg8toreg32(right.location.register));
  940. end;
  941. end;
  942. if cmpop then
  943. case opsize of
  944. S_L : ungetregister32(location.register);
  945. S_B : ungetregister32(reg8toreg32(location.register));
  946. end;
  947. { only in case of overflow operations }
  948. { produce overflow code }
  949. { we must put it here directly, because sign of operation }
  950. { is in unsigned VAR!! }
  951. if mboverflow then
  952. begin
  953. if cs_check_overflow in aktlocalswitches then
  954. begin
  955. getlabel(hl4);
  956. if unsigned then
  957. emitjmp(C_NB,hl4)
  958. else
  959. emitjmp(C_NO,hl4);
  960. emitcall('FPC_OVERFLOW');
  961. emitlab(hl4);
  962. end;
  963. end;
  964. end
  965. else
  966. { Char type }
  967. if ((left.resulttype.def.deftype=orddef) and
  968. (torddef(left.resulttype.def).typ=uchar)) or
  969. { enumeration type 16 bit }
  970. ((left.resulttype.def.deftype=enumdef) and
  971. (left.resulttype.def.size=1)) then
  972. begin
  973. case nodetype of
  974. ltn,lten,gtn,gten,
  975. equaln,unequaln :
  976. cmpop:=true;
  977. else CGMessage(type_e_mismatch);
  978. end;
  979. unsigned:=true;
  980. { left and right no register? }
  981. { the one must be demanded }
  982. if (location.loc<>LOC_REGISTER) and
  983. (right.location.loc<>LOC_REGISTER) then
  984. begin
  985. if location.loc=LOC_CREGISTER then
  986. begin
  987. if cmpop then
  988. { do not disturb register }
  989. hregister:=location.register
  990. else
  991. begin
  992. hregister:=reg32toreg8(getregisterint);
  993. emit_reg_reg(A_MOV,S_B,location.register,
  994. hregister);
  995. end;
  996. end
  997. else
  998. begin
  999. del_reference(location.reference);
  1000. { first give free then demand new register }
  1001. hregister:=reg32toreg8(getregisterint);
  1002. emit_ref_reg(A_MOV,S_B,newreference(location.reference),
  1003. hregister);
  1004. end;
  1005. clear_location(location);
  1006. location.loc:=LOC_REGISTER;
  1007. location.register:=hregister;
  1008. end;
  1009. { now p always a register }
  1010. if (right.location.loc=LOC_REGISTER) and
  1011. (location.loc<>LOC_REGISTER) then
  1012. begin
  1013. swap_location(location,right.location);
  1014. { newly swapped also set swapped flag }
  1015. toggleflag(nf_swaped);
  1016. end;
  1017. if right.location.loc<>LOC_REGISTER then
  1018. begin
  1019. if right.location.loc=LOC_CREGISTER then
  1020. begin
  1021. emit_reg_reg(A_CMP,S_B,
  1022. right.location.register,location.register);
  1023. end
  1024. else
  1025. begin
  1026. emit_ref_reg(A_CMP,S_B,newreference(
  1027. right.location.reference),location.register);
  1028. del_reference(right.location.reference);
  1029. end;
  1030. end
  1031. else
  1032. begin
  1033. emit_reg_reg(A_CMP,S_B,right.location.register,
  1034. location.register);
  1035. ungetregister32(reg8toreg32(right.location.register));
  1036. end;
  1037. ungetregister32(reg8toreg32(location.register));
  1038. end
  1039. else
  1040. { 16 bit enumeration type }
  1041. if ((left.resulttype.def.deftype=enumdef) and
  1042. (left.resulttype.def.size=2)) then
  1043. begin
  1044. case nodetype of
  1045. ltn,lten,gtn,gten,
  1046. equaln,unequaln :
  1047. cmpop:=true;
  1048. else CGMessage(type_e_mismatch);
  1049. end;
  1050. unsigned:=true;
  1051. { left and right no register? }
  1052. { the one must be demanded }
  1053. if (location.loc<>LOC_REGISTER) and
  1054. (right.location.loc<>LOC_REGISTER) then
  1055. begin
  1056. if location.loc=LOC_CREGISTER then
  1057. begin
  1058. if cmpop then
  1059. { do not disturb register }
  1060. hregister:=location.register
  1061. else
  1062. begin
  1063. hregister:=reg32toreg16(getregisterint);
  1064. emit_reg_reg(A_MOV,S_W,location.register,
  1065. hregister);
  1066. end;
  1067. end
  1068. else
  1069. begin
  1070. del_reference(location.reference);
  1071. { first give free then demand new register }
  1072. hregister:=reg32toreg16(getregisterint);
  1073. emit_ref_reg(A_MOV,S_W,newreference(location.reference),
  1074. hregister);
  1075. end;
  1076. clear_location(location);
  1077. location.loc:=LOC_REGISTER;
  1078. location.register:=hregister;
  1079. end;
  1080. { now p always a register }
  1081. if (right.location.loc=LOC_REGISTER) and
  1082. (location.loc<>LOC_REGISTER) then
  1083. begin
  1084. swap_location(location,right.location);
  1085. { newly swapped also set swapped flag }
  1086. toggleflag(nf_swaped);
  1087. end;
  1088. if right.location.loc<>LOC_REGISTER then
  1089. begin
  1090. if right.location.loc=LOC_CREGISTER then
  1091. begin
  1092. emit_reg_reg(A_CMP,S_W,
  1093. right.location.register,location.register);
  1094. end
  1095. else
  1096. begin
  1097. emit_ref_reg(A_CMP,S_W,newreference(
  1098. right.location.reference),location.register);
  1099. del_reference(right.location.reference);
  1100. end;
  1101. end
  1102. else
  1103. begin
  1104. emit_reg_reg(A_CMP,S_W,right.location.register,
  1105. location.register);
  1106. ungetregister32(reg16toreg32(right.location.register));
  1107. end;
  1108. ungetregister32(reg16toreg32(location.register));
  1109. end
  1110. else
  1111. { 64 bit types }
  1112. if is_64bitint(left.resulttype.def) then
  1113. begin
  1114. mboverflow:=false;
  1115. cmpop:=false;
  1116. unsigned:=((left.resulttype.def.deftype=orddef) and
  1117. (torddef(left.resulttype.def).typ=u64bit)) or
  1118. ((right.resulttype.def.deftype=orddef) and
  1119. (torddef(right.resulttype.def).typ=u64bit));
  1120. case nodetype of
  1121. addn : begin
  1122. begin
  1123. op:=A_ADD;
  1124. op2:=A_ADC;
  1125. mboverflow:=true;
  1126. end;
  1127. end;
  1128. subn : begin
  1129. op:=A_SUB;
  1130. op2:=A_SBB;
  1131. mboverflow:=true;
  1132. end;
  1133. ltn,lten,
  1134. gtn,gten,
  1135. equaln,unequaln:
  1136. begin
  1137. op:=A_CMP;
  1138. op2:=A_CMP;
  1139. cmpop:=true;
  1140. end;
  1141. xorn:
  1142. begin
  1143. op:=A_XOR;
  1144. op2:=A_XOR;
  1145. end;
  1146. orn:
  1147. begin
  1148. op:=A_OR;
  1149. op2:=A_OR;
  1150. end;
  1151. andn:
  1152. begin
  1153. op:=A_AND;
  1154. op2:=A_AND;
  1155. end;
  1156. muln:
  1157. ;
  1158. else
  1159. CGMessage(type_e_mismatch);
  1160. end;
  1161. if nodetype=muln then
  1162. begin
  1163. { should be handled in pass_1 (JM) }
  1164. internalerror(200109051);
  1165. end
  1166. else
  1167. begin
  1168. { left and right no register? }
  1169. { then one must be demanded }
  1170. if (left.location.loc<>LOC_REGISTER) and
  1171. (right.location.loc<>LOC_REGISTER) then
  1172. begin
  1173. { register variable ? }
  1174. if (left.location.loc=LOC_CREGISTER) then
  1175. begin
  1176. { it is OK if this is the destination }
  1177. if is_in_dest then
  1178. begin
  1179. hregister:=location.registerlow;
  1180. hregister2:=location.registerhigh;
  1181. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  1182. hregister);
  1183. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  1184. hregister2);
  1185. end
  1186. else
  1187. if cmpop then
  1188. begin
  1189. { do not disturb the register }
  1190. hregister:=location.registerlow;
  1191. hregister2:=location.registerhigh;
  1192. end
  1193. else
  1194. begin
  1195. hregister:=getregisterint;
  1196. hregister2:=getregisterint;
  1197. emit_reg_reg(A_MOV,S_L,left.location.registerlow,
  1198. hregister);
  1199. emit_reg_reg(A_MOV,S_L,left.location.registerhigh,
  1200. hregister2);
  1201. end
  1202. end
  1203. else
  1204. begin
  1205. ungetiftemp(left.location.reference);
  1206. del_reference(left.location.reference);
  1207. if is_in_dest then
  1208. begin
  1209. hregister:=location.registerlow;
  1210. hregister2:=location.registerhigh;
  1211. emit_mov_ref_reg64(left.location.reference,hregister,hregister2);
  1212. end
  1213. else
  1214. begin
  1215. hregister:=getregisterint;
  1216. hregister2:=getregisterint;
  1217. emit_mov_ref_reg64(left.location.reference,hregister,hregister2);
  1218. end;
  1219. end;
  1220. clear_location(location);
  1221. location.loc:=LOC_REGISTER;
  1222. location.registerlow:=hregister;
  1223. location.registerhigh:=hregister2;
  1224. end
  1225. else
  1226. { if on the right the register then swap }
  1227. if not(noswap) and (right.location.loc=LOC_REGISTER) then
  1228. begin
  1229. swap_location(location,right.location);
  1230. { newly swapped also set swapped flag }
  1231. toggleflag(nf_swaped);
  1232. end;
  1233. { at this point, location.loc should be LOC_REGISTER }
  1234. { and location.register should be a valid register }
  1235. { containing the left result }
  1236. if right.location.loc<>LOC_REGISTER then
  1237. begin
  1238. if (nodetype=subn) and (nf_swaped in flags) then
  1239. begin
  1240. if right.location.loc=LOC_CREGISTER then
  1241. begin
  1242. getexplicitregister32(R_EDI);
  1243. emit_reg_reg(A_MOV,opsize,right.location.register,R_EDI);
  1244. emit_reg_reg(op,opsize,location.register,R_EDI);
  1245. emit_reg_reg(A_MOV,opsize,R_EDI,location.register);
  1246. ungetregister32(R_EDI);
  1247. getexplicitregister32(R_EDI);
  1248. emit_reg_reg(A_MOV,opsize,right.location.registerhigh,R_EDI);
  1249. { the carry flag is still ok }
  1250. emit_reg_reg(op2,opsize,location.registerhigh,R_EDI);
  1251. emit_reg_reg(A_MOV,opsize,R_EDI,location.registerhigh);
  1252. ungetregister32(R_EDI);
  1253. end
  1254. else
  1255. begin
  1256. getexplicitregister32(R_EDI);
  1257. emit_ref_reg(A_MOV,opsize,
  1258. newreference(right.location.reference),R_EDI);
  1259. emit_reg_reg(op,opsize,location.registerlow,R_EDI);
  1260. emit_reg_reg(A_MOV,opsize,R_EDI,location.registerlow);
  1261. ungetregister32(R_EDI);
  1262. getexplicitregister32(R_EDI);
  1263. hr:=newreference(right.location.reference);
  1264. inc(hr^.offset,4);
  1265. emit_ref_reg(A_MOV,opsize,
  1266. hr,R_EDI);
  1267. { here the carry flag is still preserved }
  1268. emit_reg_reg(op2,opsize,location.registerhigh,R_EDI);
  1269. emit_reg_reg(A_MOV,opsize,R_EDI,
  1270. location.registerhigh);
  1271. ungetregister32(R_EDI);
  1272. ungetiftemp(right.location.reference);
  1273. del_reference(right.location.reference);
  1274. end;
  1275. end
  1276. else if cmpop then
  1277. begin
  1278. if (right.location.loc=LOC_CREGISTER) then
  1279. begin
  1280. emit_reg_reg(A_CMP,S_L,right.location.registerhigh,
  1281. location.registerhigh);
  1282. firstjmp64bitcmp;
  1283. emit_reg_reg(A_CMP,S_L,right.location.registerlow,
  1284. location.registerlow);
  1285. secondjmp64bitcmp;
  1286. end
  1287. else
  1288. begin
  1289. hr:=newreference(right.location.reference);
  1290. inc(hr^.offset,4);
  1291. emit_ref_reg(A_CMP,S_L,
  1292. hr,location.registerhigh);
  1293. firstjmp64bitcmp;
  1294. emit_ref_reg(A_CMP,S_L,newreference(
  1295. right.location.reference),location.registerlow);
  1296. secondjmp64bitcmp;
  1297. emitjmp(C_None,falselabel);
  1298. ungetiftemp(right.location.reference);
  1299. del_reference(right.location.reference);
  1300. end;
  1301. end
  1302. else
  1303. begin
  1304. {
  1305. if (right.nodetype=ordconstn) and
  1306. (op=A_CMP) and
  1307. (right.value=0) then
  1308. begin
  1309. emit_reg_reg(A_TEST,opsize,location.register,
  1310. location.register);
  1311. end
  1312. else if (right.nodetype=ordconstn) and
  1313. (op=A_IMUL) and
  1314. (ispowerof2(right.value,power)) then
  1315. begin
  1316. emit_const_reg(A_SHL,opsize,power,
  1317. location.register);
  1318. end
  1319. else
  1320. }
  1321. begin
  1322. if (right.location.loc=LOC_CREGISTER) then
  1323. begin
  1324. emit_reg_reg(op,S_L,right.location.registerlow,
  1325. location.registerlow);
  1326. emit_reg_reg(op2,S_L,right.location.registerhigh,
  1327. location.registerhigh);
  1328. end
  1329. else
  1330. begin
  1331. emit_ref_reg(op,S_L,newreference(
  1332. right.location.reference),location.registerlow);
  1333. hr:=newreference(right.location.reference);
  1334. inc(hr^.offset,4);
  1335. emit_ref_reg(op2,S_L,
  1336. hr,location.registerhigh);
  1337. ungetiftemp(right.location.reference);
  1338. del_reference(right.location.reference);
  1339. end;
  1340. end;
  1341. end;
  1342. end
  1343. else
  1344. begin
  1345. { when swapped another result register }
  1346. if (nodetype=subn) and (nf_swaped in flags) then
  1347. begin
  1348. emit_reg_reg(op,S_L,
  1349. location.registerlow,
  1350. right.location.registerlow);
  1351. emit_reg_reg(op2,S_L,
  1352. location.registerhigh,
  1353. right.location.registerhigh);
  1354. swap_location(location,right.location);
  1355. { newly swapped also set swapped flag }
  1356. { just to maintain ordering }
  1357. toggleflag(nf_swaped);
  1358. end
  1359. else if cmpop then
  1360. begin
  1361. emit_reg_reg(A_CMP,S_L,
  1362. right.location.registerhigh,
  1363. location.registerhigh);
  1364. firstjmp64bitcmp;
  1365. emit_reg_reg(A_CMP,S_L,
  1366. right.location.registerlow,
  1367. location.registerlow);
  1368. secondjmp64bitcmp;
  1369. end
  1370. else
  1371. begin
  1372. emit_reg_reg(op,S_L,
  1373. right.location.registerlow,
  1374. location.registerlow);
  1375. emit_reg_reg(op2,S_L,
  1376. right.location.registerhigh,
  1377. location.registerhigh);
  1378. end;
  1379. ungetregister32(right.location.registerlow);
  1380. ungetregister32(right.location.registerhigh);
  1381. end;
  1382. if cmpop then
  1383. begin
  1384. ungetregister32(location.registerlow);
  1385. ungetregister32(location.registerhigh);
  1386. end;
  1387. { only in case of overflow operations }
  1388. { produce overflow code }
  1389. { we must put it here directly, because sign of operation }
  1390. { is in unsigned VAR!! }
  1391. if mboverflow then
  1392. begin
  1393. if cs_check_overflow in aktlocalswitches then
  1394. begin
  1395. getlabel(hl4);
  1396. if unsigned then
  1397. emitjmp(C_NB,hl4)
  1398. else
  1399. emitjmp(C_NO,hl4);
  1400. emitcall('FPC_OVERFLOW');
  1401. emitlab(hl4);
  1402. end;
  1403. end;
  1404. { we have LOC_JUMP as result }
  1405. if cmpop then
  1406. begin
  1407. clear_location(location);
  1408. location.loc:=LOC_JUMP;
  1409. cmpop:=false;
  1410. end;
  1411. end;
  1412. end
  1413. else
  1414. { Floating point }
  1415. if (left.resulttype.def.deftype=floatdef) then
  1416. begin
  1417. { real constants to the right, but only if it
  1418. isn't on the FPU stack, i.e. 1.0 or 0.0!
  1419. if (left.nodetype=realconstn) and
  1420. (left.location.loc<>LOC_FPU) then
  1421. swapleftright; obsolete, already swaped above PM }
  1422. cmpop:=false;
  1423. case nodetype of
  1424. addn : op:=A_FADDP;
  1425. muln : op:=A_FMULP;
  1426. subn : op:=A_FSUBP;
  1427. slashn : op:=A_FDIVP;
  1428. ltn,lten,gtn,gten,
  1429. equaln,unequaln : begin
  1430. op:=A_FCOMPP;
  1431. cmpop:=true;
  1432. end;
  1433. else CGMessage(type_e_mismatch);
  1434. end;
  1435. if (right.location.loc<>LOC_FPU) then
  1436. begin
  1437. if right.location.loc=LOC_CFPUREGISTER then
  1438. begin
  1439. emit_reg( A_FLD,S_NO,
  1440. correct_fpuregister(right.location.register,fpuvaroffset));
  1441. inc(fpuvaroffset);
  1442. end
  1443. else
  1444. begin
  1445. floatload(tfloatdef(right.resulttype.def).typ,right.location.reference);
  1446. if pushedfpu then
  1447. ungetiftemp(right.location.reference);
  1448. end;
  1449. if (left.location.loc<>LOC_FPU) then
  1450. begin
  1451. if left.location.loc=LOC_CFPUREGISTER then
  1452. begin
  1453. emit_reg( A_FLD,S_NO,
  1454. correct_fpuregister(left.location.register,fpuvaroffset));
  1455. inc(fpuvaroffset);
  1456. end
  1457. else
  1458. begin
  1459. floatload(tfloatdef(left.resulttype.def).typ,left.location.reference);
  1460. if pushedfpu then
  1461. ungetiftemp(left.location.reference);
  1462. end;
  1463. end
  1464. { left was on the stack => swap }
  1465. else
  1466. toggleflag(nf_swaped);
  1467. { releases the right reference }
  1468. del_reference(right.location.reference);
  1469. end
  1470. { the nominator in st0 }
  1471. else if (left.location.loc<>LOC_FPU) then
  1472. begin
  1473. if left.location.loc=LOC_CFPUREGISTER then
  1474. begin
  1475. emit_reg( A_FLD,S_NO,
  1476. correct_fpuregister(left.location.register,fpuvaroffset));
  1477. inc(fpuvaroffset);
  1478. end
  1479. else
  1480. begin
  1481. floatload(tfloatdef(left.resulttype.def).typ,left.location.reference);
  1482. if pushedfpu then
  1483. ungetiftemp(left.location.reference);
  1484. end;
  1485. end
  1486. { fpu operands are always in the wrong order on the stack }
  1487. else
  1488. toggleflag(nf_swaped);
  1489. { releases the left reference }
  1490. if (left.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  1491. del_reference(left.location.reference);
  1492. { if we swaped the tree nodes, then use the reverse operator }
  1493. if nf_swaped in flags then
  1494. begin
  1495. if (nodetype=slashn) then
  1496. op:=A_FDIVRP
  1497. else if (nodetype=subn) then
  1498. op:=A_FSUBRP;
  1499. end;
  1500. { to avoid the pentium bug
  1501. if (op=FDIVP) and (opt_processors=pentium) then
  1502. emitcall('EMUL_FDIVP')
  1503. else
  1504. }
  1505. { the Intel assemblers want operands }
  1506. if op<>A_FCOMPP then
  1507. begin
  1508. emit_reg_reg(op,S_NO,R_ST,R_ST1);
  1509. dec(fpuvaroffset);
  1510. end
  1511. else
  1512. begin
  1513. emit_none(op,S_NO);
  1514. dec(fpuvaroffset,2);
  1515. end;
  1516. { on comparison load flags }
  1517. if cmpop then
  1518. begin
  1519. if not(R_EAX in unused) then
  1520. begin
  1521. getexplicitregister32(R_EDI);
  1522. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  1523. end;
  1524. emit_reg(A_FNSTSW,S_NO,R_AX);
  1525. emit_none(A_SAHF,S_NO);
  1526. if not(R_EAX in unused) then
  1527. begin
  1528. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  1529. ungetregister32(R_EDI);
  1530. end;
  1531. if nf_swaped in flags then
  1532. begin
  1533. case nodetype of
  1534. equaln : resflags:=F_E;
  1535. unequaln : resflags:=F_NE;
  1536. ltn : resflags:=F_A;
  1537. lten : resflags:=F_AE;
  1538. gtn : resflags:=F_B;
  1539. gten : resflags:=F_BE;
  1540. end;
  1541. end
  1542. else
  1543. begin
  1544. case nodetype of
  1545. equaln : resflags:=F_E;
  1546. unequaln : resflags:=F_NE;
  1547. ltn : resflags:=F_B;
  1548. lten : resflags:=F_BE;
  1549. gtn : resflags:=F_A;
  1550. gten : resflags:=F_AE;
  1551. end;
  1552. end;
  1553. clear_location(location);
  1554. location.loc:=LOC_FLAGS;
  1555. location.resflags:=resflags;
  1556. cmpop:=false;
  1557. end
  1558. else
  1559. begin
  1560. clear_location(location);
  1561. location.loc:=LOC_FPU;
  1562. end;
  1563. end
  1564. {$ifdef SUPPORT_MMX}
  1565. else
  1566. { MMX Arrays }
  1567. if is_mmx_able_array(left.resulttype.def) then
  1568. begin
  1569. cmpop:=false;
  1570. mmxbase:=mmx_type(left.resulttype.def);
  1571. case nodetype of
  1572. addn : begin
  1573. if (cs_mmx_saturation in aktlocalswitches) then
  1574. begin
  1575. case mmxbase of
  1576. mmxs8bit:
  1577. op:=A_PADDSB;
  1578. mmxu8bit:
  1579. op:=A_PADDUSB;
  1580. mmxs16bit,mmxfixed16:
  1581. op:=A_PADDSB;
  1582. mmxu16bit:
  1583. op:=A_PADDUSW;
  1584. end;
  1585. end
  1586. else
  1587. begin
  1588. case mmxbase of
  1589. mmxs8bit,mmxu8bit:
  1590. op:=A_PADDB;
  1591. mmxs16bit,mmxu16bit,mmxfixed16:
  1592. op:=A_PADDW;
  1593. mmxs32bit,mmxu32bit:
  1594. op:=A_PADDD;
  1595. end;
  1596. end;
  1597. end;
  1598. muln : begin
  1599. case mmxbase of
  1600. mmxs16bit,mmxu16bit:
  1601. op:=A_PMULLW;
  1602. mmxfixed16:
  1603. op:=A_PMULHW;
  1604. end;
  1605. end;
  1606. subn : begin
  1607. if (cs_mmx_saturation in aktlocalswitches) then
  1608. begin
  1609. case mmxbase of
  1610. mmxs8bit:
  1611. op:=A_PSUBSB;
  1612. mmxu8bit:
  1613. op:=A_PSUBUSB;
  1614. mmxs16bit,mmxfixed16:
  1615. op:=A_PSUBSB;
  1616. mmxu16bit:
  1617. op:=A_PSUBUSW;
  1618. end;
  1619. end
  1620. else
  1621. begin
  1622. case mmxbase of
  1623. mmxs8bit,mmxu8bit:
  1624. op:=A_PSUBB;
  1625. mmxs16bit,mmxu16bit,mmxfixed16:
  1626. op:=A_PSUBW;
  1627. mmxs32bit,mmxu32bit:
  1628. op:=A_PSUBD;
  1629. end;
  1630. end;
  1631. end;
  1632. {
  1633. ltn,lten,gtn,gten,
  1634. equaln,unequaln :
  1635. begin
  1636. op:=A_CMP;
  1637. cmpop:=true;
  1638. end;
  1639. }
  1640. xorn:
  1641. op:=A_PXOR;
  1642. orn:
  1643. op:=A_POR;
  1644. andn:
  1645. op:=A_PAND;
  1646. else CGMessage(type_e_mismatch);
  1647. end;
  1648. { left and right no register? }
  1649. { then one must be demanded }
  1650. if (left.location.loc<>LOC_MMXREGISTER) and
  1651. (right.location.loc<>LOC_MMXREGISTER) then
  1652. begin
  1653. { register variable ? }
  1654. if (left.location.loc=LOC_CMMXREGISTER) then
  1655. begin
  1656. { it is OK if this is the destination }
  1657. if is_in_dest then
  1658. begin
  1659. hregister:=location.register;
  1660. emit_reg_reg(A_MOVQ,S_NO,left.location.register,
  1661. hregister);
  1662. end
  1663. else
  1664. begin
  1665. hregister:=getregistermmx;
  1666. emit_reg_reg(A_MOVQ,S_NO,left.location.register,
  1667. hregister);
  1668. end
  1669. end
  1670. else
  1671. begin
  1672. del_reference(left.location.reference);
  1673. if is_in_dest then
  1674. begin
  1675. hregister:=location.register;
  1676. emit_ref_reg(A_MOVQ,S_NO,
  1677. newreference(left.location.reference),hregister);
  1678. end
  1679. else
  1680. begin
  1681. hregister:=getregistermmx;
  1682. emit_ref_reg(A_MOVQ,S_NO,
  1683. newreference(left.location.reference),hregister);
  1684. end;
  1685. end;
  1686. clear_location(location);
  1687. location.loc:=LOC_MMXREGISTER;
  1688. location.register:=hregister;
  1689. end
  1690. else
  1691. { if on the right the register then swap }
  1692. if (right.location.loc=LOC_MMXREGISTER) then
  1693. begin
  1694. swap_location(location,right.location);
  1695. { newly swapped also set swapped flag }
  1696. toggleflag(nf_swaped);
  1697. end;
  1698. { at this point, location.loc should be LOC_MMXREGISTER }
  1699. { and location.register should be a valid register }
  1700. { containing the left result }
  1701. if right.location.loc<>LOC_MMXREGISTER then
  1702. begin
  1703. if (nodetype=subn) and (nf_swaped in flags) then
  1704. begin
  1705. if right.location.loc=LOC_CMMXREGISTER then
  1706. begin
  1707. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1708. emit_reg_reg(op,S_NO,location.register,R_MM0);
  1709. emit_reg_reg(A_MOVQ,S_NO,R_MM7,location.register);
  1710. end
  1711. else
  1712. begin
  1713. emit_ref_reg(A_MOVQ,S_NO,
  1714. newreference(right.location.reference),R_MM7);
  1715. emit_reg_reg(op,S_NO,location.register,
  1716. R_MM7);
  1717. emit_reg_reg(A_MOVQ,S_NO,
  1718. R_MM7,location.register);
  1719. del_reference(right.location.reference);
  1720. end;
  1721. end
  1722. else
  1723. begin
  1724. if (right.location.loc=LOC_CREGISTER) then
  1725. begin
  1726. emit_reg_reg(op,S_NO,right.location.register,
  1727. location.register);
  1728. end
  1729. else
  1730. begin
  1731. emit_ref_reg(op,S_NO,newreference(
  1732. right.location.reference),location.register);
  1733. del_reference(right.location.reference);
  1734. end;
  1735. end;
  1736. end
  1737. else
  1738. begin
  1739. { when swapped another result register }
  1740. if (nodetype=subn) and (nf_swaped in flags) then
  1741. begin
  1742. emit_reg_reg(op,S_NO,
  1743. location.register,right.location.register);
  1744. swap_location(location,right.location);
  1745. { newly swapped also set swapped flag }
  1746. { just to maintain ordering }
  1747. toggleflag(nf_swaped);
  1748. end
  1749. else
  1750. begin
  1751. emit_reg_reg(op,S_NO,
  1752. right.location.register,
  1753. location.register);
  1754. end;
  1755. ungetregistermmx(right.location.register);
  1756. end;
  1757. end
  1758. {$endif SUPPORT_MMX}
  1759. else CGMessage(type_e_mismatch);
  1760. end;
  1761. SetResultLocation(cmpop,unsigned);
  1762. end;
  1763. begin
  1764. caddnode:=ti386addnode;
  1765. end.
  1766. {
  1767. $Log$
  1768. Revision 1.28 2001-12-30 17:24:46 jonas
  1769. * range checking is now processor independent (part in cgobj, part in cg64f32) and should work correctly again (it needed some changes after the changes of the low and high of tordef's to int64) * maketojumpbool() is now processor independent (in ncgutil) * getregister32 is now called getregisterint
  1770. Revision 1.27 2001/12/29 15:29:58 jonas
  1771. * powerpc/cgcpu.pas compiles :)
  1772. * several powerpc-related fixes
  1773. * cpuasm unit is now based on common tainst unit
  1774. + nppcmat unit for powerpc (almost complete)
  1775. Revision 1.25 2001/10/12 13:51:51 jonas
  1776. * fixed internalerror(10) due to previous fpu overflow fixes ("merged")
  1777. * fixed bug in n386add (introduced after compilerproc changes for string
  1778. operations) where calcregisters wasn't called for shortstring addnodes
  1779. * NOTE: from now on, the location of a binary node must now always be set
  1780. before you call calcregisters() for it
  1781. Revision 1.24 2001/09/17 21:29:13 peter
  1782. * merged netbsd, fpu-overflow from fixes branch
  1783. Revision 1.23 2001/09/05 15:22:09 jonas
  1784. * made multiplying, dividing and mod'ing of int64 and qword processor
  1785. independent with compilerprocs (+ small optimizations by using shift/and
  1786. where possible)
  1787. Revision 1.22 2001/09/04 11:38:55 jonas
  1788. + searchsystype() and searchsystype() functions in symtable
  1789. * changed ninl and nadd to use these functions
  1790. * i386 set comparison functions now return their results in al instead
  1791. of in the flags so that they can be sued as compilerprocs
  1792. - removed all processor specific code from n386add.pas that has to do
  1793. with set handling, it's now all done in nadd.pas
  1794. * fixed fpc_set_contains_sets in genset.inc
  1795. * fpc_set_in_byte is now coded inline in n386set.pas and doesn't use a
  1796. helper anymore
  1797. * some small fixes in compproc.inc/set.inc regarding the declaration of
  1798. internal helper types (fpc_small_set and fpc_normal_set)
  1799. Revision 1.21 2001/09/03 13:27:42 jonas
  1800. * compilerproc implementation of set addition/substraction/...
  1801. * changed the declaration of some set helpers somewhat to accomodate the
  1802. above change
  1803. * i386 still uses the old code for comparisons of sets, because its
  1804. helpers return the results in the flags
  1805. * dummy tc_normal_2_small_set type conversion because I need the original
  1806. resulttype of the set add nodes
  1807. NOTE: you have to start a cycle with 1.0.5!
  1808. Revision 1.20 2001/08/30 15:43:14 jonas
  1809. * converted adding/comparing of strings to compileproc. Note that due
  1810. to the way the shortstring helpers for i386 are written, they are
  1811. still handled by the old code (reason: fpc_shortstr_compare returns
  1812. results in the flags instead of in eax and fpc_shortstr_concat
  1813. has wierd parameter conventions). The compilerproc stuff should work
  1814. fine with the generic implementations though.
  1815. * removed some nested comments warnings
  1816. Revision 1.19 2001/08/29 17:50:45 jonas
  1817. * removed unused var
  1818. Revision 1.18 2001/08/29 12:03:23 jonas
  1819. * fixed wrong regalloc info around FPC_MUL/DIV/MOD_INT64/QWORD calls
  1820. * fixed partial result overwriting with the above calls too
  1821. Revision 1.17 2001/08/26 13:36:55 florian
  1822. * some cg reorganisation
  1823. * some PPC updates
  1824. Revision 1.16 2001/07/08 21:00:16 peter
  1825. * various widestring updates, it works now mostly without charset
  1826. mapping supported
  1827. Revision 1.15 2001/06/25 14:11:37 jonas
  1828. * fixed set bug discovered by Carl (merged)
  1829. Revision 1.14 2001/06/18 20:36:25 peter
  1830. * -Ur switch (merged)
  1831. * masm fixes (merged)
  1832. * quoted filenames for go32v2 and win32
  1833. Revision 1.13 2001/05/27 14:30:56 florian
  1834. + some widestring stuff added
  1835. Revision 1.12 2001/05/06 17:12:14 jonas
  1836. * fixed an IE10 and another bug with [var1..var2] construct
  1837. Revision 1.11 2001/04/13 01:22:18 peter
  1838. * symtable change to classes
  1839. * range check generation and errors fixed, make cycle DEBUG=1 works
  1840. * memory leaks fixed
  1841. Revision 1.10 2001/04/02 21:20:36 peter
  1842. * resulttype rewrite
  1843. Revision 1.9 2000/12/31 11:14:11 jonas
  1844. + implemented/fixed docompare() mathods for all nodes (not tested)
  1845. + nopt.pas, nadd.pas, i386/n386opt.pas: optimized nodes for adding strings
  1846. and constant strings/chars together
  1847. * n386add.pas: don't copy temp strings (of size 256) to another temp string
  1848. when adding
  1849. Revision 1.8 2000/12/25 00:07:32 peter
  1850. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1851. tlinkedlist objects)
  1852. Revision 1.7 2000/12/16 15:56:18 jonas
  1853. - removed all ifdef cardinalmulfix code
  1854. Revision 1.6 2000/12/05 11:44:32 jonas
  1855. + new integer regvar handling, should be much more efficient
  1856. Revision 1.5 2000/11/29 00:30:45 florian
  1857. * unused units removed from uses clause
  1858. * some changes for widestrings
  1859. Revision 1.4 2000/11/13 11:30:56 florian
  1860. * some bugs with interfaces and NIL fixed
  1861. Revision 1.3 2000/11/04 14:25:23 florian
  1862. + merged Attila's changes for interfaces, not tested yet
  1863. Revision 1.2 2000/10/31 22:02:56 peter
  1864. * symtable splitted, no real code changes
  1865. Revision 1.1 2000/10/15 09:33:31 peter
  1866. * moved n386*.pas to i386/ cpu_target dir
  1867. Revision 1.6 2000/10/14 10:14:47 peter
  1868. * moehrendorf oct 2000 rewrite
  1869. Revision 1.5 2000/09/30 16:08:45 peter
  1870. * more cg11 updates
  1871. Revision 1.4 2000/09/24 15:06:18 peter
  1872. * use defines.inc
  1873. Revision 1.3 2000/09/22 22:42:52 florian
  1874. * more fixes
  1875. Revision 1.2 2000/09/21 12:24:22 jonas
  1876. * small fix to my changes for full boolean evaluation support (moved
  1877. opsize determination for boolean operations back in boolean
  1878. processing block)
  1879. + full boolean evaluation support (from cg386add)
  1880. Revision 1.1 2000/09/20 21:23:32 florian
  1881. * initial revision
  1882. }