cgi386ad.inc 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. This include file generates i386+ assembler from the parse tree
  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. procedure secondas(var p : ptree);
  19. var
  20. pushed : tpushed;
  21. begin
  22. secondpass(p^.left);
  23. { save all used registers }
  24. pushusedregisters(pushed,$ff);
  25. { push instance to check: }
  26. case p^.left^.location.loc of
  27. LOC_REGISTER,LOC_CREGISTER:
  28. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  29. S_L,p^.left^.location.register)));
  30. LOC_MEM,LOC_REFERENCE:
  31. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  32. S_L,newreference(p^.left^.location.reference))));
  33. else internalerror(100);
  34. end;
  35. { we doesn't modifiy the left side, we check only the type }
  36. set_location(p^.location,p^.left^.location);
  37. { generate type checking }
  38. secondpass(p^.right);
  39. case p^.right^.location.loc of
  40. LOC_REGISTER,LOC_CREGISTER:
  41. begin
  42. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  43. S_L,p^.right^.location.register)));
  44. ungetregister32(p^.right^.location.register);
  45. end;
  46. LOC_MEM,LOC_REFERENCE:
  47. begin
  48. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  49. S_L,newreference(p^.right^.location.reference))));
  50. del_reference(p^.right^.location.reference);
  51. end;
  52. else internalerror(100);
  53. end;
  54. emitcall('DO_AS',true);
  55. { restore register, this restores automatically the }
  56. { result }
  57. popusedregisters(pushed);
  58. end;
  59. procedure secondloadvmt(var p : ptree);
  60. begin
  61. p^.location.register:=getregister32;
  62. exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,
  63. S_L,newcsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname,0),
  64. p^.location.register)));
  65. end;
  66. procedure secondis(var p : ptree);
  67. var
  68. pushed : tpushed;
  69. begin
  70. { save all used registers }
  71. pushusedregisters(pushed,$ff);
  72. secondpass(p^.left);
  73. p^.location.loc:=LOC_FLAGS;
  74. p^.location.resflags:=F_NE;
  75. { push instance to check: }
  76. case p^.left^.location.loc of
  77. LOC_REGISTER,LOC_CREGISTER:
  78. begin
  79. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  80. S_L,p^.left^.location.register)));
  81. ungetregister32(p^.left^.location.register);
  82. end;
  83. LOC_MEM,LOC_REFERENCE:
  84. begin
  85. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  86. S_L,newreference(p^.left^.location.reference))));
  87. del_reference(p^.left^.location.reference);
  88. end;
  89. else internalerror(100);
  90. end;
  91. { generate type checking }
  92. secondpass(p^.right);
  93. case p^.right^.location.loc of
  94. LOC_REGISTER,LOC_CREGISTER:
  95. begin
  96. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,
  97. S_L,p^.right^.location.register)));
  98. ungetregister32(p^.right^.location.register);
  99. end;
  100. LOC_MEM,LOC_REFERENCE:
  101. begin
  102. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,
  103. S_L,newreference(p^.right^.location.reference))));
  104. del_reference(p^.right^.location.reference);
  105. end;
  106. else internalerror(100);
  107. end;
  108. emitcall('DO_IS',true);
  109. exprasmlist^.concat(new(pai386,op_reg_reg(A_OR,S_B,R_AL,R_AL)));
  110. popusedregisters(pushed);
  111. end;
  112. procedure setaddresult(cmpop,unsigned : boolean;var p :ptree);
  113. var
  114. flags : tresflags;
  115. begin
  116. if (p^.left^.resulttype^.deftype<>stringdef) and
  117. ((p^.left^.resulttype^.deftype<>setdef) or
  118. (psetdef(p^.left^.resulttype)^.settype=smallset)) then
  119. if (p^.left^.location.loc=LOC_REFERENCE) or
  120. (p^.left^.location.loc=LOC_MEM) then
  121. ungetiftemp(p^.left^.location.reference);
  122. if (p^.right^.resulttype^.deftype<>stringdef) and
  123. ((p^.right^.resulttype^.deftype<>setdef) or
  124. (psetdef(p^.right^.resulttype)^.settype=smallset)) then
  125. { this can be useful if for instance length(string) is called }
  126. if (p^.right^.location.loc=LOC_REFERENCE) or
  127. (p^.right^.location.loc=LOC_MEM) then
  128. ungetiftemp(p^.right^.location.reference);
  129. { in case of comparison operation the put result in the flags }
  130. if cmpop then
  131. begin
  132. if not(unsigned) then
  133. begin
  134. if p^.swaped then
  135. case p^.treetype of
  136. equaln : flags:=F_E;
  137. unequaln : flags:=F_NE;
  138. ltn : flags:=F_G;
  139. lten : flags:=F_GE;
  140. gtn : flags:=F_L;
  141. gten : flags:=F_LE;
  142. end
  143. else
  144. case p^.treetype of
  145. equaln : flags:=F_E;
  146. unequaln : flags:=F_NE;
  147. ltn : flags:=F_L;
  148. lten : flags:=F_LE;
  149. gtn : flags:=F_G;
  150. gten : flags:=F_GE;
  151. end;
  152. end
  153. else
  154. begin
  155. if p^.swaped then
  156. case p^.treetype of
  157. equaln : flags:=F_E;
  158. unequaln : flags:=F_NE;
  159. ltn : flags:=F_A;
  160. lten : flags:=F_AE;
  161. gtn : flags:=F_B;
  162. gten : flags:=F_BE;
  163. end
  164. else
  165. case p^.treetype of
  166. equaln : flags:=F_E;
  167. unequaln : flags:=F_NE;
  168. ltn : flags:=F_B;
  169. lten : flags:=F_BE;
  170. gtn : flags:=F_A;
  171. gten : flags:=F_AE;
  172. end;
  173. end;
  174. p^.location.loc:=LOC_FLAGS;
  175. p^.location.resflags:=flags;
  176. end;
  177. end;
  178. procedure secondaddstring(var p : ptree);
  179. var
  180. swapp : ptree;
  181. pushedregs : tpushed;
  182. href : treference;
  183. pushed,cmpop : boolean;
  184. begin
  185. { string operations are not commutative }
  186. if p^.swaped then
  187. begin
  188. swapp:=p^.left;
  189. p^.left:=p^.right;
  190. p^.right:=swapp;
  191. { because of jump being produced at comparison below: }
  192. p^.swaped:=not(p^.swaped);
  193. end;
  194. {$ifdef UseAnsiString}
  195. if is_ansistring(p^.left^.resulttype) then
  196. begin
  197. case p^.treetype of
  198. addn :
  199. begin
  200. { we do not need destination anymore }
  201. del_reference(p^.left^.location.reference);
  202. del_reference(p^.right^.location.reference);
  203. { concatansistring(p); }
  204. end;
  205. ltn,lten,gtn,gten,
  206. equaln,unequaln :
  207. begin
  208. pushusedregisters(pushedregs,$ff);
  209. secondpass(p^.left);
  210. del_reference(p^.left^.location.reference);
  211. emitpushreferenceaddr(p^.left^.location.reference);
  212. secondpass(p^.right);
  213. del_reference(p^.right^.location.reference);
  214. emitpushreferenceaddr(p^.right^.location.reference);
  215. emitcall('ANSISTRCMP',true);
  216. maybe_loadesi;
  217. popusedregisters(pushedregs);
  218. end;
  219. end;
  220. end
  221. else
  222. {$endif UseAnsiString}
  223. case p^.treetype of
  224. addn :
  225. begin
  226. cmpop:=false;
  227. secondpass(p^.left);
  228. { if str_concat is set in expr
  229. s:=s+ ... no need to create a temp string (PM) }
  230. if (p^.left^.treetype<>addn) and not (p^.use_strconcat) then
  231. begin
  232. { can only reference be }
  233. { string in register would be funny }
  234. { therefore produce a temporary string }
  235. { release the registers }
  236. del_reference(p^.left^.location.reference);
  237. gettempofsizereference(256,href);
  238. copystring(href,p^.left^.location.reference,255);
  239. ungetiftemp(p^.left^.location.reference);
  240. { does not hurt: }
  241. p^.left^.location.loc:=LOC_MEM;
  242. p^.left^.location.reference:=href;
  243. end;
  244. secondpass(p^.right);
  245. { on the right we do not need the register anymore too }
  246. del_reference(p^.right^.location.reference);
  247. { if p^.right^.resulttype^.deftype=orddef then
  248. begin
  249. pushusedregisters(pushedregs,$ff);
  250. exprasmlist^.concat(new(pai386,op_ref_reg(
  251. A_LEA,S_L,newreference(p^.left^.location.reference),R_EDI)));
  252. exprasmlist^.concat(new(pai386,op_reg_reg(
  253. A_XOR,S_L,R_EBX,R_EBX)));
  254. reset_reference(href);
  255. href.base:=R_EDI;
  256. exprasmlist^.concat(new(pai386,op_ref_reg(
  257. A_MOV,S_B,newreference(href),R_BL)));
  258. exprasmlist^.concat(new(pai386,op_reg(
  259. A_INC,S_L,R_EBX)));
  260. exprasmlist^.concat(new(pai386,op_reg_ref(
  261. A_MOV,S_B,R_BL,newreference(href))));
  262. href.index:=R_EBX;
  263. if p^.right^.treetype=ordconstn then
  264. exprasmlist^.concat(new(pai386,op_const_ref(
  265. A_MOV,S_L,p^.right^.value,newreference(href))))
  266. else
  267. begin
  268. if p^.right^.location.loc in [LOC_CREGISTER,LOC_REGISTER] then
  269. exprasmlist^.concat(new(pai386,op_reg_ref(
  270. A_MOV,S_B,p^.right^.location.register,newreference(href))))
  271. else
  272. begin
  273. exprasmlist^.concat(new(pai386,op_ref_reg(
  274. A_MOV,S_L,newreference(p^.right^.location.reference),R_EAX)));
  275. exprasmlist^.concat(new(pai386,op_reg_ref(
  276. A_MOV,S_B,R_AL,newreference(href))));
  277. end;
  278. end;
  279. popusedregisters(pushedregs);
  280. end
  281. else }
  282. begin
  283. if p^.use_strconcat then
  284. pushusedregisters(pushedregs,pstringdef(p^.left^.resulttype)^.len)
  285. else
  286. pushusedregisters(pushedregs,$ff);
  287. emitpushreferenceaddr(p^.left^.location.reference);
  288. emitpushreferenceaddr(p^.right^.location.reference);
  289. emitcall('STRCONCAT',true);
  290. maybe_loadesi;
  291. popusedregisters(pushedregs);
  292. end;
  293. set_location(p^.location,p^.left^.location);
  294. ungetiftemp(p^.right^.location.reference);
  295. end;
  296. ltn,lten,gtn,gten,
  297. equaln,unequaln :
  298. begin
  299. cmpop:=true;
  300. { generate better code for s='' and s<>'' }
  301. if (p^.treetype in [equaln,unequaln]) and
  302. (((p^.left^.treetype=stringconstn) and (p^.left^.values^='')) or
  303. ((p^.right^.treetype=stringconstn) and (p^.right^.values^=''))) then
  304. begin
  305. secondpass(p^.left);
  306. { are too few registers free? }
  307. pushed:=maybe_push(p^.right^.registers32,p);
  308. secondpass(p^.right);
  309. if pushed then restore(p);
  310. del_reference(p^.right^.location.reference);
  311. del_reference(p^.left^.location.reference);
  312. { only one node can be stringconstn }
  313. { else pass 1 would have evaluted }
  314. { this node }
  315. if p^.left^.treetype=stringconstn then
  316. exprasmlist^.concat(new(pai386,op_const_ref(
  317. A_CMP,S_B,0,newreference(p^.right^.location.reference))))
  318. else
  319. exprasmlist^.concat(new(pai386,op_const_ref(
  320. A_CMP,S_B,0,newreference(p^.left^.location.reference))));
  321. end
  322. else
  323. begin
  324. pushusedregisters(pushedregs,$ff);
  325. secondpass(p^.left);
  326. del_reference(p^.left^.location.reference);
  327. emitpushreferenceaddr(p^.left^.location.reference);
  328. secondpass(p^.right);
  329. del_reference(p^.right^.location.reference);
  330. emitpushreferenceaddr(p^.right^.location.reference);
  331. emitcall('STRCMP',true);
  332. maybe_loadesi;
  333. popusedregisters(pushedregs);
  334. end;
  335. ungetiftemp(p^.left^.location.reference);
  336. ungetiftemp(p^.right^.location.reference);
  337. end;
  338. else Message(sym_e_type_mismatch);
  339. end;
  340. setaddresult(cmpop,true,p);
  341. end;
  342. procedure secondadd(var p : ptree);
  343. { is also being used for xor, and "mul", "sub, or and comparative }
  344. { operators }
  345. label do_normal;
  346. var
  347. swapp : ptree;
  348. hregister : tregister;
  349. pushed,mboverflow,cmpop : boolean;
  350. op : tasmop;
  351. pushedregs : tpushed;
  352. flags : tresflags;
  353. otl,ofl : plabel;
  354. power : longint;
  355. href : treference;
  356. opsize : topsize;
  357. hl4: plabel;
  358. { true, if unsigned types are compared }
  359. unsigned : boolean;
  360. { is_in_dest if the result is put directly into }
  361. { the resulting refernce or varregister }
  362. { true, if a small set is handled with the longint code }
  363. is_set : boolean;
  364. is_in_dest : boolean;
  365. { true, if for sets subtractions the extra not should generated }
  366. extra_not : boolean;
  367. {$ifdef SUPPORT_MMX}
  368. mmxbase : tmmxtype;
  369. {$endif SUPPORT_MMX}
  370. begin
  371. if (p^.left^.resulttype^.deftype=stringdef) then
  372. begin
  373. secondaddstring(p);
  374. exit;
  375. end;
  376. unsigned:=false;
  377. is_in_dest:=false;
  378. extra_not:=false;
  379. opsize:=S_L;
  380. { calculate the operator which is more difficult }
  381. firstcomplex(p);
  382. { handling boolean expressions extra: }
  383. if ((p^.left^.resulttype^.deftype=orddef) and
  384. (porddef(p^.left^.resulttype)^.typ=bool8bit)) or
  385. ((p^.right^.resulttype^.deftype=orddef) and
  386. (porddef(p^.right^.resulttype)^.typ=bool8bit)) then
  387. begin
  388. if (p^.treetype=andn) or (p^.treetype=orn) then
  389. begin
  390. p^.location.loc:=LOC_JUMP;
  391. cmpop:=false;
  392. case p^.treetype of
  393. andn : begin
  394. otl:=truelabel;
  395. getlabel(truelabel);
  396. secondpass(p^.left);
  397. maketojumpbool(p^.left);
  398. emitl(A_LABEL,truelabel);
  399. truelabel:=otl;
  400. end;
  401. orn : begin
  402. ofl:=falselabel;
  403. getlabel(falselabel);
  404. secondpass(p^.left);
  405. maketojumpbool(p^.left);
  406. emitl(A_LABEL,falselabel);
  407. falselabel:=ofl;
  408. end;
  409. else Message(sym_e_type_mismatch);
  410. end;
  411. secondpass(p^.right);
  412. maketojumpbool(p^.right);
  413. end
  414. else if p^.treetype in [unequaln,equaln,xorn] then
  415. begin
  416. opsize:=S_B;
  417. if p^.left^.treetype=ordconstn then
  418. begin
  419. swapp:=p^.right;
  420. p^.right:=p^.left;
  421. p^.left:=swapp;
  422. p^.swaped:=not(p^.swaped);
  423. end;
  424. secondpass(p^.left);
  425. p^.location:=p^.left^.location;
  426. { are enough registers free ? }
  427. pushed:=maybe_push(p^.right^.registers32,p);
  428. secondpass(p^.right);
  429. if pushed then restore(p);
  430. goto do_normal;
  431. end
  432. else Message(sym_e_type_mismatch);
  433. end
  434. else
  435. if (p^.left^.resulttype^.deftype=setdef) and
  436. not(psetdef(p^.left^.resulttype)^.settype=smallset) then
  437. begin
  438. mboverflow:=false;
  439. secondpass(p^.left);
  440. set_location(p^.location,p^.left^.location);
  441. { are too few registers free? }
  442. pushed:=maybe_push(p^.right^.registers32,p);
  443. secondpass(p^.right);
  444. if pushed then restore(p);
  445. { not commutative }
  446. if p^.swaped then
  447. begin
  448. swapp:=p^.left;
  449. p^.left:=p^.right;
  450. p^.right:=swapp;
  451. { because of jump being produced by comparison }
  452. p^.swaped:=not(p^.swaped);
  453. end;
  454. case p^.treetype of
  455. equaln,unequaln:
  456. begin
  457. cmpop:=true;
  458. del_reference(p^.left^.location.reference);
  459. del_reference(p^.right^.location.reference);
  460. pushusedregisters(pushedregs,$ff);
  461. emitpushreferenceaddr(p^.right^.location.reference);
  462. emitpushreferenceaddr(p^.left^.location.reference);
  463. emitcall('SET_COMP_SETS',true);
  464. maybe_loadesi;
  465. popusedregisters(pushedregs);
  466. ungetiftemp(p^.left^.location.reference);
  467. ungetiftemp(p^.right^.location.reference);
  468. end;
  469. addn,symdifn,subn,muln:
  470. begin
  471. cmpop:=false;
  472. del_reference(p^.left^.location.reference);
  473. del_reference(p^.right^.location.reference);
  474. href.symbol:=nil;
  475. pushusedregisters(pushedregs,$ff);
  476. gettempofsizereference(32,href);
  477. emitpushreferenceaddr(href);
  478. { wrong place !! was hard to find out
  479. pushusedregisters(pushedregs,$ff);}
  480. emitpushreferenceaddr(p^.right^.location.reference);
  481. emitpushreferenceaddr(p^.left^.location.reference);
  482. case p^.treetype of
  483. subn:
  484. emitcall('SET_SUB_SETS',true);
  485. addn:
  486. emitcall('SET_ADD_SETS',true);
  487. symdifn:
  488. emitcall('SET_SYMDIF_SETS',true);
  489. muln:
  490. emitcall('SET_MUL_SETS',true);
  491. end;
  492. maybe_loadesi;
  493. popusedregisters(pushedregs);
  494. ungetiftemp(p^.left^.location.reference);
  495. ungetiftemp(p^.right^.location.reference);
  496. p^.location.loc:=LOC_MEM;
  497. stringdispose(p^.location.reference.symbol);
  498. p^.location.reference:=href;
  499. end;
  500. else Message(sym_e_type_mismatch);
  501. end;
  502. end
  503. else
  504. begin
  505. { in case of constant put it to the left }
  506. if p^.left^.treetype=ordconstn then
  507. begin
  508. swapp:=p^.right;
  509. p^.right:=p^.left;
  510. p^.left:=swapp;
  511. p^.swaped:=not(p^.swaped);
  512. end;
  513. secondpass(p^.left);
  514. { this will be complicated as
  515. a lot of code below assumes that
  516. p^.location and p^.left^.location are the same }
  517. {$ifdef test_dest_loc}
  518. if dest_loc_known and (dest_loc_tree=p) and
  519. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  520. begin
  521. set_location(p^.location,dest_loc);
  522. in_dest_loc:=true;
  523. is_in_dest:=true;
  524. end
  525. else
  526. {$endif test_dest_loc}
  527. set_location(p^.location,p^.left^.location);
  528. { are too few registers free? }
  529. pushed:=maybe_push(p^.right^.registers32,p);
  530. secondpass(p^.right);
  531. if pushed then restore(p);
  532. if (p^.left^.resulttype^.deftype=pointerdef) or
  533. (p^.right^.resulttype^.deftype=pointerdef) or
  534. ((p^.right^.resulttype^.deftype=objectdef) and
  535. pobjectdef(p^.right^.resulttype)^.isclass and
  536. (p^.left^.resulttype^.deftype=objectdef) and
  537. pobjectdef(p^.left^.resulttype)^.isclass
  538. ) or
  539. (p^.left^.resulttype^.deftype=classrefdef) or
  540. (p^.left^.resulttype^.deftype=procvardef) or
  541. (p^.left^.resulttype^.deftype=enumdef) or
  542. ((p^.left^.resulttype^.deftype=orddef) and
  543. (porddef(p^.left^.resulttype)^.typ=s32bit)) or
  544. ((p^.right^.resulttype^.deftype=orddef) and
  545. (porddef(p^.right^.resulttype)^.typ=s32bit)) or
  546. ((p^.left^.resulttype^.deftype=orddef) and
  547. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  548. ((p^.right^.resulttype^.deftype=orddef) and
  549. (porddef(p^.right^.resulttype)^.typ=u32bit)) or
  550. { as well as small sets }
  551. ((p^.left^.resulttype^.deftype=setdef) and
  552. (psetdef(p^.left^.resulttype)^.settype=smallset)
  553. ) then
  554. begin
  555. do_normal:
  556. mboverflow:=false;
  557. cmpop:=false;
  558. if (p^.left^.resulttype^.deftype=pointerdef) or
  559. (p^.right^.resulttype^.deftype=pointerdef) or
  560. ((p^.left^.resulttype^.deftype=orddef) and
  561. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  562. ((p^.right^.resulttype^.deftype=orddef) and
  563. (porddef(p^.right^.resulttype)^.typ=u32bit)) then
  564. unsigned:=true;
  565. is_set:=p^.resulttype^.deftype=setdef;
  566. case p^.treetype of
  567. addn : begin
  568. if is_set then
  569. begin
  570. op:=A_OR;
  571. mboverflow:=false;
  572. unsigned:=false;
  573. end
  574. else
  575. begin
  576. op:=A_ADD;
  577. mboverflow:=true;
  578. end;
  579. end;
  580. symdifn : begin
  581. { the symetric diff is only for sets }
  582. if is_set then
  583. begin
  584. op:=A_XOR;
  585. mboverflow:=false;
  586. unsigned:=false;
  587. end
  588. else
  589. begin
  590. Message(sym_e_type_mismatch);
  591. end;
  592. end;
  593. muln : begin
  594. if is_set then
  595. begin
  596. op:=A_AND;
  597. mboverflow:=false;
  598. unsigned:=false;
  599. end
  600. else
  601. begin
  602. if unsigned then
  603. op:=A_MUL
  604. else
  605. op:=A_IMUL;
  606. mboverflow:=true;
  607. end;
  608. end;
  609. subn : begin
  610. if is_set then
  611. begin
  612. op:=A_AND;
  613. mboverflow:=false;
  614. unsigned:=false;
  615. extra_not:=true;
  616. end
  617. else
  618. begin
  619. op:=A_SUB;
  620. mboverflow:=true;
  621. end;
  622. end;
  623. ltn,lten,gtn,gten,
  624. equaln,unequaln :
  625. begin
  626. op:=A_CMP;
  627. cmpop:=true;
  628. end;
  629. xorn : op:=A_XOR;
  630. orn : op:=A_OR;
  631. andn : op:=A_AND;
  632. else Message(sym_e_type_mismatch);
  633. end;
  634. { left and right no register? }
  635. { then one must be demanded }
  636. if (p^.left^.location.loc<>LOC_REGISTER) and
  637. (p^.right^.location.loc<>LOC_REGISTER) then
  638. begin
  639. { register variable ? }
  640. if (p^.left^.location.loc=LOC_CREGISTER) then
  641. begin
  642. { it is OK if this is the destination }
  643. if is_in_dest then
  644. begin
  645. hregister:=p^.location.register;
  646. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  647. hregister);
  648. end
  649. else
  650. if cmpop then
  651. begin
  652. { do not disturb the register }
  653. hregister:=p^.location.register;
  654. end
  655. else
  656. begin
  657. case opsize of
  658. S_L : hregister:=getregister32;
  659. S_B : hregister:=reg32toreg8(getregister32);
  660. end;
  661. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  662. hregister);
  663. end
  664. end
  665. else
  666. begin
  667. del_reference(p^.left^.location.reference);
  668. if is_in_dest then
  669. begin
  670. hregister:=p^.location.register;
  671. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  672. newreference(p^.left^.location.reference),hregister)));
  673. end
  674. else
  675. begin
  676. { first give free, then demand new register }
  677. case opsize of
  678. S_L : hregister:=getregister32;
  679. S_B : hregister:=reg32toreg8(getregister32);
  680. end;
  681. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  682. newreference(p^.left^.location.reference),hregister)));
  683. end;
  684. end;
  685. p^.location.loc:=LOC_REGISTER;
  686. p^.location.register:=hregister;
  687. end
  688. else
  689. { if on the right the register then swap }
  690. if (p^.right^.location.loc=LOC_REGISTER) then
  691. begin
  692. swap_location(p^.location,p^.right^.location);
  693. { newly swapped also set swapped flag }
  694. p^.swaped:=not(p^.swaped);
  695. end;
  696. { at this point, p^.location.loc should be LOC_REGISTER }
  697. { and p^.location.register should be a valid register }
  698. { containing the left result }
  699. if p^.right^.location.loc<>LOC_REGISTER then
  700. begin
  701. if (p^.treetype=subn) and p^.swaped then
  702. begin
  703. if p^.right^.location.loc=LOC_CREGISTER then
  704. begin
  705. if extra_not then
  706. exprasmlist^.concat(new(pai386,op_reg(A_NOT,opsize,p^.location.register)));
  707. emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  708. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  709. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  710. end
  711. else
  712. begin
  713. if extra_not then
  714. exprasmlist^.concat(new(pai386,op_reg(A_NOT,opsize,p^.location.register)));
  715. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  716. newreference(p^.right^.location.reference),R_EDI)));
  717. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.register,R_EDI)));
  718. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,R_EDI,p^.location.register)));
  719. del_reference(p^.right^.location.reference);
  720. end;
  721. end
  722. else
  723. begin
  724. if (p^.right^.treetype=ordconstn) and
  725. (op=A_CMP) and
  726. (p^.right^.value=0) then
  727. begin
  728. exprasmlist^.concat(new(pai386,op_reg_reg(A_TEST,opsize,p^.location.register,
  729. p^.location.register)));
  730. end
  731. else if (p^.right^.treetype=ordconstn) and
  732. (op=A_ADD) and
  733. (p^.right^.value=1) then
  734. begin
  735. exprasmlist^.concat(new(pai386,op_reg(A_INC,opsize,
  736. p^.location.register)));
  737. end
  738. else if (p^.right^.treetype=ordconstn) and
  739. (op=A_SUB) and
  740. (p^.right^.value=1) then
  741. begin
  742. exprasmlist^.concat(new(pai386,op_reg(A_DEC,opsize,
  743. p^.location.register)));
  744. end
  745. else if (p^.right^.treetype=ordconstn) and
  746. (op=A_IMUL) and
  747. (ispowerof2(p^.right^.value,power)) then
  748. begin
  749. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,opsize,power,
  750. p^.location.register)));
  751. end
  752. else
  753. begin
  754. if (p^.right^.location.loc=LOC_CREGISTER) then
  755. begin
  756. if extra_not then
  757. begin
  758. emit_reg_reg(A_MOV,S_L,p^.right^.location.register,R_EDI);
  759. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,R_EDI)));
  760. emit_reg_reg(A_AND,S_L,R_EDI,
  761. p^.location.register);
  762. end
  763. else
  764. begin
  765. emit_reg_reg(op,opsize,p^.right^.location.register,
  766. p^.location.register);
  767. end;
  768. end
  769. else
  770. begin
  771. if extra_not then
  772. begin
  773. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  774. p^.right^.location.reference),R_EDI)));
  775. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,R_EDI)));
  776. emit_reg_reg(A_AND,S_L,R_EDI,
  777. p^.location.register);
  778. end
  779. else
  780. begin
  781. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,newreference(
  782. p^.right^.location.reference),p^.location.register)));
  783. end;
  784. del_reference(p^.right^.location.reference);
  785. end;
  786. end;
  787. end;
  788. end
  789. else
  790. begin
  791. { when swapped another result register }
  792. if (p^.treetype=subn) and p^.swaped then
  793. begin
  794. if extra_not then
  795. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,p^.location.register)));
  796. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  797. p^.location.register,p^.right^.location.register)));
  798. swap_location(p^.location,p^.right^.location);
  799. { newly swapped also set swapped flag }
  800. { just to maintain ordering }
  801. p^.swaped:=not(p^.swaped);
  802. end
  803. else
  804. begin
  805. if extra_not then
  806. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,p^.right^.location.register)));
  807. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  808. p^.right^.location.register,
  809. p^.location.register)));
  810. end;
  811. case opsize of
  812. S_L : ungetregister32(p^.right^.location.register);
  813. S_B : ungetregister32(reg8toreg32(p^.right^.location.register));
  814. end;
  815. end;
  816. if cmpop then
  817. case opsize of
  818. S_L : ungetregister32(p^.location.register);
  819. S_B : ungetregister32(reg8toreg32(p^.location.register));
  820. end;
  821. { only in case of overflow operations }
  822. { produce overflow code }
  823. if mboverflow then
  824. { we must put it here directly, because sign of operation }
  825. { is in unsigned VAR!! }
  826. begin
  827. if cs_check_overflow in aktswitches then
  828. begin
  829. getlabel(hl4);
  830. if unsigned then
  831. emitl(A_JNB,hl4)
  832. else
  833. emitl(A_JNO,hl4);
  834. emitcall('RE_OVERFLOW',true);
  835. emitl(A_LABEL,hl4);
  836. end;
  837. end;
  838. end
  839. else if ((p^.left^.resulttype^.deftype=orddef) and
  840. (porddef(p^.left^.resulttype)^.typ=uchar)) then
  841. begin
  842. case p^.treetype of
  843. ltn,lten,gtn,gten,
  844. equaln,unequaln :
  845. cmpop:=true;
  846. else Message(sym_e_type_mismatch);
  847. end;
  848. unsigned:=true;
  849. { left and right no register? }
  850. { the one must be demanded }
  851. if (p^.location.loc<>LOC_REGISTER) and
  852. (p^.right^.location.loc<>LOC_REGISTER) then
  853. begin
  854. if p^.location.loc=LOC_CREGISTER then
  855. begin
  856. if cmpop then
  857. { do not disturb register }
  858. hregister:=p^.location.register
  859. else
  860. begin
  861. hregister:=reg32toreg8(getregister32);
  862. emit_reg_reg(A_MOV,S_B,p^.location.register,
  863. hregister);
  864. end;
  865. end
  866. else
  867. begin
  868. del_reference(p^.location.reference);
  869. { first give free then demand new register }
  870. hregister:=reg32toreg8(getregister32);
  871. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_B,newreference(p^.location.reference),
  872. hregister)));
  873. end;
  874. p^.location.loc:=LOC_REGISTER;
  875. p^.location.register:=hregister;
  876. end;
  877. { now p always a register }
  878. if (p^.right^.location.loc=LOC_REGISTER) and
  879. (p^.location.loc<>LOC_REGISTER) then
  880. begin
  881. swap_location(p^.location,p^.right^.location);
  882. { newly swapped also set swapped flag }
  883. p^.swaped:=not(p^.swaped);
  884. end;
  885. if p^.right^.location.loc<>LOC_REGISTER then
  886. begin
  887. if p^.right^.location.loc=LOC_CREGISTER then
  888. begin
  889. emit_reg_reg(A_CMP,S_B,
  890. p^.right^.location.register,p^.location.register);
  891. end
  892. else
  893. begin
  894. exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,S_B,newreference(
  895. p^.right^.location.reference),p^.location.register)));
  896. del_reference(p^.right^.location.reference);
  897. end;
  898. end
  899. else
  900. begin
  901. emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  902. p^.location.register);
  903. ungetregister32(reg8toreg32(p^.right^.location.register));
  904. end;
  905. ungetregister32(reg8toreg32(p^.location.register));
  906. end
  907. else if (p^.left^.resulttype^.deftype=floatdef) and
  908. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  909. begin
  910. { real constants to the left }
  911. if p^.left^.treetype=realconstn then
  912. begin
  913. swapp:=p^.right;
  914. p^.right:=p^.left;
  915. p^.left:=swapp;
  916. p^.swaped:=not(p^.swaped);
  917. end;
  918. cmpop:=false;
  919. case p^.treetype of
  920. addn : op:=A_FADDP;
  921. muln : op:=A_FMULP;
  922. subn : op:=A_FSUBP;
  923. slashn : op:=A_FDIVP;
  924. ltn,lten,gtn,gten,
  925. equaln,unequaln : begin
  926. op:=A_FCOMPP;
  927. cmpop:=true;
  928. end;
  929. else Message(sym_e_type_mismatch);
  930. end;
  931. if (p^.right^.location.loc<>LOC_FPU) then
  932. begin
  933. floatload(pfloatdef(p^.right^.resulttype)^.typ,p^.right^.location.reference);
  934. if (p^.left^.location.loc<>LOC_FPU) then
  935. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  936. { left was on the stack => swap }
  937. else
  938. p^.swaped:=not(p^.swaped);
  939. { releases the right reference }
  940. del_reference(p^.right^.location.reference);
  941. end
  942. { the nominator in st0 }
  943. else if (p^.left^.location.loc<>LOC_FPU) then
  944. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  945. { fpu operands are always in the wrong order on the stack }
  946. else
  947. p^.swaped:=not(p^.swaped);
  948. { releases the left reference }
  949. if (p^.left^.location.loc<>LOC_FPU) then
  950. del_reference(p^.left^.location.reference);
  951. { if we swaped the tree nodes, then use the reverse operator }
  952. if p^.swaped then
  953. begin
  954. if (p^.treetype=slashn) then
  955. op:=A_FDIVRP
  956. else if (p^.treetype=subn) then
  957. op:=A_FSUBRP;
  958. end;
  959. { to avoid the pentium bug
  960. if (op=FDIVP) and (opt_processors=pentium) then
  961. exprasmlist^.concat(new(pai386,op_CALL,S_NO,'EMUL_FDIVP')
  962. else
  963. }
  964. { the Intel assemblers want operands }
  965. if op<>A_FCOMPP then
  966. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,R_ST,R_ST1)))
  967. else
  968. exprasmlist^.concat(new(pai386,op_none(op,S_NO)));
  969. { on comparison load flags }
  970. if cmpop then
  971. begin
  972. if not(R_EAX in unused) then
  973. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  974. exprasmlist^.concat(new(pai386,op_reg(A_FNSTSW,S_NO,R_AX)));
  975. exprasmlist^.concat(new(pai386,op_none(A_SAHF,S_NO)));
  976. if not(R_EAX in unused) then
  977. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  978. if p^.swaped then
  979. case p^.treetype of
  980. equaln : flags:=F_E;
  981. unequaln : flags:=F_NE;
  982. ltn : flags:=F_A;
  983. lten : flags:=F_AE;
  984. gtn : flags:=F_B;
  985. gten : flags:=F_BE;
  986. end
  987. else
  988. case p^.treetype of
  989. equaln : flags:=F_E;
  990. unequaln : flags:=F_NE;
  991. ltn : flags:=F_B;
  992. lten : flags:=F_BE;
  993. gtn : flags:=F_A;
  994. gten : flags:=F_AE;
  995. end;
  996. p^.location.loc:=LOC_FLAGS;
  997. p^.location.resflags:=flags;
  998. cmpop:=false;
  999. end
  1000. else
  1001. p^.location.loc:=LOC_FPU;
  1002. end
  1003. {$ifdef SUPPORT_MMX}
  1004. else if is_mmx_able_array(p^.left^.resulttype) then
  1005. begin
  1006. cmpop:=false;
  1007. mmxbase:=mmx_type(p^.left^.resulttype);
  1008. case p^.treetype of
  1009. addn : begin
  1010. if (cs_mmx_saturation in aktswitches) then
  1011. begin
  1012. case mmxbase of
  1013. mmxs8bit:
  1014. op:=A_PADDSB;
  1015. mmxu8bit:
  1016. op:=A_PADDUSB;
  1017. mmxs16bit,mmxfixed16:
  1018. op:=A_PADDSB;
  1019. mmxu16bit:
  1020. op:=A_PADDUSW;
  1021. end;
  1022. end
  1023. else
  1024. begin
  1025. case mmxbase of
  1026. mmxs8bit,mmxu8bit:
  1027. op:=A_PADDB;
  1028. mmxs16bit,mmxu16bit,mmxfixed16:
  1029. op:=A_PADDW;
  1030. mmxs32bit,mmxu32bit:
  1031. op:=A_PADDD;
  1032. end;
  1033. end;
  1034. end;
  1035. muln : begin
  1036. case mmxbase of
  1037. mmxs16bit,mmxu16bit:
  1038. op:=A_PMULLW;
  1039. mmxfixed16:
  1040. op:=A_PMULHW;
  1041. end;
  1042. end;
  1043. subn : begin
  1044. if (cs_mmx_saturation in aktswitches) then
  1045. begin
  1046. case mmxbase of
  1047. mmxs8bit:
  1048. op:=A_PSUBSB;
  1049. mmxu8bit:
  1050. op:=A_PSUBUSB;
  1051. mmxs16bit,mmxfixed16:
  1052. op:=A_PSUBSB;
  1053. mmxu16bit:
  1054. op:=A_PSUBUSW;
  1055. end;
  1056. end
  1057. else
  1058. begin
  1059. case mmxbase of
  1060. mmxs8bit,mmxu8bit:
  1061. op:=A_PSUBB;
  1062. mmxs16bit,mmxu16bit,mmxfixed16:
  1063. op:=A_PSUBW;
  1064. mmxs32bit,mmxu32bit:
  1065. op:=A_PSUBD;
  1066. end;
  1067. end;
  1068. end;
  1069. {
  1070. ltn,lten,gtn,gten,
  1071. equaln,unequaln :
  1072. begin
  1073. op:=A_CMP;
  1074. cmpop:=true;
  1075. end;
  1076. }
  1077. xorn:
  1078. op:=A_PXOR;
  1079. orn:
  1080. op:=A_POR;
  1081. andn:
  1082. op:=A_PAND;
  1083. else Message(sym_e_type_mismatch);
  1084. end;
  1085. { left and right no register? }
  1086. { then one must be demanded }
  1087. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  1088. (p^.right^.location.loc<>LOC_MMXREGISTER) then
  1089. begin
  1090. { register variable ? }
  1091. if (p^.left^.location.loc=LOC_CMMXREGISTER) then
  1092. begin
  1093. { it is OK if this is the destination }
  1094. if is_in_dest then
  1095. begin
  1096. hregister:=p^.location.register;
  1097. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1098. hregister);
  1099. end
  1100. else
  1101. begin
  1102. hregister:=getregistermmx;
  1103. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1104. hregister);
  1105. end
  1106. end
  1107. else
  1108. begin
  1109. del_reference(p^.left^.location.reference);
  1110. if is_in_dest then
  1111. begin
  1112. hregister:=p^.location.register;
  1113. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1114. newreference(p^.left^.location.reference),hregister)));
  1115. end
  1116. else
  1117. begin
  1118. hregister:=getregistermmx;
  1119. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1120. newreference(p^.left^.location.reference),hregister)));
  1121. end;
  1122. end;
  1123. p^.location.loc:=LOC_MMXREGISTER;
  1124. p^.location.register:=hregister;
  1125. end
  1126. else
  1127. { if on the right the register then swap }
  1128. if (p^.right^.location.loc=LOC_MMXREGISTER) then
  1129. begin
  1130. swap_location(p^.location,p^.right^.location);
  1131. { newly swapped also set swapped flag }
  1132. p^.swaped:=not(p^.swaped);
  1133. end;
  1134. { at this point, p^.location.loc should be LOC_MMXREGISTER }
  1135. { and p^.location.register should be a valid register }
  1136. { containing the left result }
  1137. if p^.right^.location.loc<>LOC_MMXREGISTER then
  1138. begin
  1139. if (p^.treetype=subn) and p^.swaped then
  1140. begin
  1141. if p^.right^.location.loc=LOC_CMMXREGISTER then
  1142. begin
  1143. emit_reg_reg(A_MOVQ,S_NO,p^.right^.location.register,R_MM7);
  1144. emit_reg_reg(op,S_NO,p^.location.register,R_EDI);
  1145. emit_reg_reg(A_MOVQ,S_NO,R_MM7,p^.location.register);
  1146. end
  1147. else
  1148. begin
  1149. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1150. newreference(p^.right^.location.reference),R_MM7)));
  1151. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,p^.location.register,
  1152. R_MM7)));
  1153. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVQ,S_NO,
  1154. R_MM7,p^.location.register)));
  1155. del_reference(p^.right^.location.reference);
  1156. end;
  1157. end
  1158. else
  1159. begin
  1160. if (p^.right^.location.loc=LOC_CREGISTER) then
  1161. begin
  1162. emit_reg_reg(op,S_NO,p^.right^.location.register,
  1163. p^.location.register);
  1164. end
  1165. else
  1166. begin
  1167. exprasmlist^.concat(new(pai386,op_ref_reg(op,S_NO,newreference(
  1168. p^.right^.location.reference),p^.location.register)));
  1169. del_reference(p^.right^.location.reference);
  1170. end;
  1171. end;
  1172. end
  1173. else
  1174. begin
  1175. { when swapped another result register }
  1176. if (p^.treetype=subn) and p^.swaped then
  1177. begin
  1178. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,
  1179. p^.location.register,p^.right^.location.register)));
  1180. swap_location(p^.location,p^.right^.location);
  1181. { newly swapped also set swapped flag }
  1182. { just to maintain ordering }
  1183. p^.swaped:=not(p^.swaped);
  1184. end
  1185. else
  1186. begin
  1187. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,
  1188. p^.right^.location.register,
  1189. p^.location.register)));
  1190. end;
  1191. ungetregistermmx(p^.right^.location.register);
  1192. end;
  1193. end
  1194. {$endif SUPPORT_MMX}
  1195. else Message(sym_e_type_mismatch);
  1196. end;
  1197. setaddresult(cmpop,unsigned,p);
  1198. end;
  1199. {
  1200. $Log$
  1201. Revision 1.8 1998-05-11 13:07:53 peter
  1202. + $ifdef NEWPPU for the new ppuformat
  1203. + $define GDB not longer required
  1204. * removed all warnings and stripped some log comments
  1205. * no findfirst/findnext anymore to remove smartlink *.o files
  1206. Revision 1.7 1998/05/01 16:38:44 florian
  1207. * handling of private and protected fixed
  1208. + change_keywords_to_tp implemented to remove
  1209. keywords which aren't supported by tp
  1210. * break and continue are now symbols of the system unit
  1211. + widestring, longstring and ansistring type released
  1212. Revision 1.6 1998/04/30 15:59:40 pierre
  1213. * GDB works again better :
  1214. correct type info in one pass
  1215. + UseTokenInfo for better source position
  1216. * fixed one remaining bug in scanner for line counts
  1217. * several little fixes
  1218. Revision 1.5 1998/04/29 10:33:49 pierre
  1219. + added some code for ansistring (not complete nor working yet)
  1220. * corrected operator overloading
  1221. * corrected nasm output
  1222. + started inline procedures
  1223. + added starstarn : use ** for exponentiation (^ gave problems)
  1224. + started UseTokenInfo cond to get accurate positions
  1225. Revision 1.3 1998/04/08 11:34:22 peter
  1226. * nasm works (linux only tested)
  1227. }