cgi386ad.inc 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  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. mmxbase : tmmxtype;
  368. begin
  369. if (p^.left^.resulttype^.deftype=stringdef) then
  370. begin
  371. secondaddstring(p);
  372. exit;
  373. end;
  374. unsigned:=false;
  375. is_in_dest:=false;
  376. extra_not:=false;
  377. opsize:=S_L;
  378. { calculate the operator which is more difficult }
  379. firstcomplex(p);
  380. { handling boolean expressions extra: }
  381. if ((p^.left^.resulttype^.deftype=orddef) and
  382. (porddef(p^.left^.resulttype)^.typ=bool8bit)) or
  383. ((p^.right^.resulttype^.deftype=orddef) and
  384. (porddef(p^.right^.resulttype)^.typ=bool8bit)) then
  385. begin
  386. if (p^.treetype=andn) or (p^.treetype=orn) then
  387. begin
  388. p^.location.loc:=LOC_JUMP;
  389. cmpop:=false;
  390. case p^.treetype of
  391. andn : begin
  392. otl:=truelabel;
  393. getlabel(truelabel);
  394. secondpass(p^.left);
  395. maketojumpbool(p^.left);
  396. emitl(A_LABEL,truelabel);
  397. truelabel:=otl;
  398. end;
  399. orn : begin
  400. ofl:=falselabel;
  401. getlabel(falselabel);
  402. secondpass(p^.left);
  403. maketojumpbool(p^.left);
  404. emitl(A_LABEL,falselabel);
  405. falselabel:=ofl;
  406. end;
  407. else Message(sym_e_type_mismatch);
  408. end;
  409. secondpass(p^.right);
  410. maketojumpbool(p^.right);
  411. end
  412. else if p^.treetype in [unequaln,equaln,xorn] then
  413. begin
  414. opsize:=S_B;
  415. if p^.left^.treetype=ordconstn then
  416. begin
  417. swapp:=p^.right;
  418. p^.right:=p^.left;
  419. p^.left:=swapp;
  420. p^.swaped:=not(p^.swaped);
  421. end;
  422. secondpass(p^.left);
  423. p^.location:=p^.left^.location;
  424. { are enough registers free ? }
  425. pushed:=maybe_push(p^.right^.registers32,p);
  426. secondpass(p^.right);
  427. if pushed then restore(p);
  428. goto do_normal;
  429. end
  430. else Message(sym_e_type_mismatch);
  431. end
  432. else
  433. if (p^.left^.resulttype^.deftype=setdef) and
  434. not(psetdef(p^.left^.resulttype)^.settype=smallset) then
  435. begin
  436. mboverflow:=false;
  437. secondpass(p^.left);
  438. set_location(p^.location,p^.left^.location);
  439. { are too few registers free? }
  440. pushed:=maybe_push(p^.right^.registers32,p);
  441. secondpass(p^.right);
  442. if pushed then restore(p);
  443. { not commutative }
  444. if p^.swaped then
  445. begin
  446. swapp:=p^.left;
  447. p^.left:=p^.right;
  448. p^.right:=swapp;
  449. { because of jump being produced by comparison }
  450. p^.swaped:=not(p^.swaped);
  451. end;
  452. case p^.treetype of
  453. equaln,unequaln:
  454. begin
  455. cmpop:=true;
  456. del_reference(p^.left^.location.reference);
  457. del_reference(p^.right^.location.reference);
  458. pushusedregisters(pushedregs,$ff);
  459. emitpushreferenceaddr(p^.right^.location.reference);
  460. emitpushreferenceaddr(p^.left^.location.reference);
  461. emitcall('SET_COMP_SETS',true);
  462. maybe_loadesi;
  463. popusedregisters(pushedregs);
  464. ungetiftemp(p^.left^.location.reference);
  465. ungetiftemp(p^.right^.location.reference);
  466. end;
  467. addn,symdifn,subn,muln:
  468. begin
  469. cmpop:=false;
  470. del_reference(p^.left^.location.reference);
  471. del_reference(p^.right^.location.reference);
  472. href.symbol:=nil;
  473. pushusedregisters(pushedregs,$ff);
  474. gettempofsizereference(32,href);
  475. emitpushreferenceaddr(href);
  476. { wrong place !! was hard to find out
  477. pushusedregisters(pushedregs,$ff);}
  478. emitpushreferenceaddr(p^.right^.location.reference);
  479. emitpushreferenceaddr(p^.left^.location.reference);
  480. case p^.treetype of
  481. subn:
  482. emitcall('SET_SUB_SETS',true);
  483. addn:
  484. emitcall('SET_ADD_SETS',true);
  485. symdifn:
  486. emitcall('SET_SYMDIF_SETS',true);
  487. muln:
  488. emitcall('SET_MUL_SETS',true);
  489. end;
  490. maybe_loadesi;
  491. popusedregisters(pushedregs);
  492. ungetiftemp(p^.left^.location.reference);
  493. ungetiftemp(p^.right^.location.reference);
  494. p^.location.loc:=LOC_MEM;
  495. stringdispose(p^.location.reference.symbol);
  496. p^.location.reference:=href;
  497. end;
  498. else Message(sym_e_type_mismatch);
  499. end;
  500. end
  501. else
  502. begin
  503. { in case of constant put it to the left }
  504. if p^.left^.treetype=ordconstn then
  505. begin
  506. swapp:=p^.right;
  507. p^.right:=p^.left;
  508. p^.left:=swapp;
  509. p^.swaped:=not(p^.swaped);
  510. end;
  511. secondpass(p^.left);
  512. { this will be complicated as
  513. a lot of code below assumes that
  514. p^.location and p^.left^.location are the same }
  515. {$ifdef test_dest_loc}
  516. if dest_loc_known and (dest_loc_tree=p) and
  517. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  518. begin
  519. set_location(p^.location,dest_loc);
  520. in_dest_loc:=true;
  521. is_in_dest:=true;
  522. end
  523. else
  524. {$endif test_dest_loc}
  525. set_location(p^.location,p^.left^.location);
  526. { are too few registers free? }
  527. pushed:=maybe_push(p^.right^.registers32,p);
  528. secondpass(p^.right);
  529. if pushed then restore(p);
  530. if (p^.left^.resulttype^.deftype=pointerdef) or
  531. (p^.right^.resulttype^.deftype=pointerdef) or
  532. ((p^.right^.resulttype^.deftype=objectdef) and
  533. pobjectdef(p^.right^.resulttype)^.isclass and
  534. (p^.left^.resulttype^.deftype=objectdef) and
  535. pobjectdef(p^.left^.resulttype)^.isclass
  536. ) or
  537. (p^.left^.resulttype^.deftype=classrefdef) or
  538. (p^.left^.resulttype^.deftype=procvardef) or
  539. (p^.left^.resulttype^.deftype=enumdef) or
  540. ((p^.left^.resulttype^.deftype=orddef) and
  541. (porddef(p^.left^.resulttype)^.typ=s32bit)) or
  542. ((p^.right^.resulttype^.deftype=orddef) and
  543. (porddef(p^.right^.resulttype)^.typ=s32bit)) or
  544. ((p^.left^.resulttype^.deftype=orddef) and
  545. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  546. ((p^.right^.resulttype^.deftype=orddef) and
  547. (porddef(p^.right^.resulttype)^.typ=u32bit)) or
  548. { as well as small sets }
  549. ((p^.left^.resulttype^.deftype=setdef) and
  550. (psetdef(p^.left^.resulttype)^.settype=smallset)
  551. ) then
  552. begin
  553. do_normal:
  554. mboverflow:=false;
  555. cmpop:=false;
  556. if (p^.left^.resulttype^.deftype=pointerdef) or
  557. (p^.right^.resulttype^.deftype=pointerdef) or
  558. ((p^.left^.resulttype^.deftype=orddef) and
  559. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  560. ((p^.right^.resulttype^.deftype=orddef) and
  561. (porddef(p^.right^.resulttype)^.typ=u32bit)) then
  562. unsigned:=true;
  563. is_set:=p^.resulttype^.deftype=setdef;
  564. case p^.treetype of
  565. addn : begin
  566. if is_set then
  567. begin
  568. op:=A_OR;
  569. mboverflow:=false;
  570. unsigned:=false;
  571. end
  572. else
  573. begin
  574. op:=A_ADD;
  575. mboverflow:=true;
  576. end;
  577. end;
  578. symdifn : begin
  579. { the symetric diff is only for sets }
  580. if is_set then
  581. begin
  582. op:=A_XOR;
  583. mboverflow:=false;
  584. unsigned:=false;
  585. end
  586. else
  587. begin
  588. Message(sym_e_type_mismatch);
  589. end;
  590. end;
  591. muln : begin
  592. if is_set then
  593. begin
  594. op:=A_AND;
  595. mboverflow:=false;
  596. unsigned:=false;
  597. end
  598. else
  599. begin
  600. if unsigned then
  601. op:=A_MUL
  602. else
  603. op:=A_IMUL;
  604. mboverflow:=true;
  605. end;
  606. end;
  607. subn : begin
  608. if is_set then
  609. begin
  610. op:=A_AND;
  611. mboverflow:=false;
  612. unsigned:=false;
  613. extra_not:=true;
  614. end
  615. else
  616. begin
  617. op:=A_SUB;
  618. mboverflow:=true;
  619. end;
  620. end;
  621. ltn,lten,gtn,gten,
  622. equaln,unequaln :
  623. begin
  624. op:=A_CMP;
  625. cmpop:=true;
  626. end;
  627. xorn : op:=A_XOR;
  628. orn : op:=A_OR;
  629. andn : op:=A_AND;
  630. else Message(sym_e_type_mismatch);
  631. end;
  632. { left and right no register? }
  633. { then one must be demanded }
  634. if (p^.left^.location.loc<>LOC_REGISTER) and
  635. (p^.right^.location.loc<>LOC_REGISTER) then
  636. begin
  637. { register variable ? }
  638. if (p^.left^.location.loc=LOC_CREGISTER) then
  639. begin
  640. { it is OK if this is the destination }
  641. if is_in_dest then
  642. begin
  643. hregister:=p^.location.register;
  644. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  645. hregister);
  646. end
  647. else
  648. if cmpop then
  649. begin
  650. { do not disturb the register }
  651. hregister:=p^.location.register;
  652. end
  653. else
  654. begin
  655. case opsize of
  656. S_L : hregister:=getregister32;
  657. S_B : hregister:=reg32toreg8(getregister32);
  658. end;
  659. emit_reg_reg(A_MOV,opsize,p^.left^.location.register,
  660. hregister);
  661. end
  662. end
  663. else
  664. begin
  665. del_reference(p^.left^.location.reference);
  666. if is_in_dest then
  667. begin
  668. hregister:=p^.location.register;
  669. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  670. newreference(p^.left^.location.reference),hregister)));
  671. end
  672. else
  673. begin
  674. { first give free, then demand new register }
  675. case opsize of
  676. S_L : hregister:=getregister32;
  677. S_B : hregister:=reg32toreg8(getregister32);
  678. end;
  679. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  680. newreference(p^.left^.location.reference),hregister)));
  681. end;
  682. end;
  683. p^.location.loc:=LOC_REGISTER;
  684. p^.location.register:=hregister;
  685. end
  686. else
  687. { if on the right the register then swap }
  688. if (p^.right^.location.loc=LOC_REGISTER) then
  689. begin
  690. swap_location(p^.location,p^.right^.location);
  691. { newly swapped also set swapped flag }
  692. p^.swaped:=not(p^.swaped);
  693. end;
  694. { at this point, p^.location.loc should be LOC_REGISTER }
  695. { and p^.location.register should be a valid register }
  696. { containing the left result }
  697. if p^.right^.location.loc<>LOC_REGISTER then
  698. begin
  699. if (p^.treetype=subn) and p^.swaped then
  700. begin
  701. if p^.right^.location.loc=LOC_CREGISTER then
  702. begin
  703. if extra_not then
  704. exprasmlist^.concat(new(pai386,op_reg(A_NOT,opsize,p^.location.register)));
  705. emit_reg_reg(A_MOV,opsize,p^.right^.location.register,R_EDI);
  706. emit_reg_reg(op,opsize,p^.location.register,R_EDI);
  707. emit_reg_reg(A_MOV,opsize,R_EDI,p^.location.register);
  708. end
  709. else
  710. begin
  711. if extra_not then
  712. exprasmlist^.concat(new(pai386,op_reg(A_NOT,opsize,p^.location.register)));
  713. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  714. newreference(p^.right^.location.reference),R_EDI)));
  715. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,p^.location.register,R_EDI)));
  716. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,R_EDI,p^.location.register)));
  717. del_reference(p^.right^.location.reference);
  718. end;
  719. end
  720. else
  721. begin
  722. if (p^.right^.treetype=ordconstn) and
  723. (op=A_CMP) and
  724. (p^.right^.value=0) then
  725. begin
  726. exprasmlist^.concat(new(pai386,op_reg_reg(A_TEST,opsize,p^.location.register,
  727. p^.location.register)));
  728. end
  729. else if (p^.right^.treetype=ordconstn) and
  730. (op=A_ADD) and
  731. (p^.right^.value=1) then
  732. begin
  733. exprasmlist^.concat(new(pai386,op_reg(A_INC,opsize,
  734. p^.location.register)));
  735. end
  736. else if (p^.right^.treetype=ordconstn) and
  737. (op=A_SUB) and
  738. (p^.right^.value=1) then
  739. begin
  740. exprasmlist^.concat(new(pai386,op_reg(A_DEC,opsize,
  741. p^.location.register)));
  742. end
  743. else if (p^.right^.treetype=ordconstn) and
  744. (op=A_IMUL) and
  745. (ispowerof2(p^.right^.value,power)) then
  746. begin
  747. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,opsize,power,
  748. p^.location.register)));
  749. end
  750. else
  751. begin
  752. if (p^.right^.location.loc=LOC_CREGISTER) then
  753. begin
  754. if extra_not then
  755. begin
  756. emit_reg_reg(A_MOV,S_L,p^.right^.location.register,R_EDI);
  757. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,R_EDI)));
  758. emit_reg_reg(A_AND,S_L,R_EDI,
  759. p^.location.register);
  760. end
  761. else
  762. begin
  763. emit_reg_reg(op,opsize,p^.right^.location.register,
  764. p^.location.register);
  765. end;
  766. end
  767. else
  768. begin
  769. if extra_not then
  770. begin
  771. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(
  772. p^.right^.location.reference),R_EDI)));
  773. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,R_EDI)));
  774. emit_reg_reg(A_AND,S_L,R_EDI,
  775. p^.location.register);
  776. end
  777. else
  778. begin
  779. exprasmlist^.concat(new(pai386,op_ref_reg(op,opsize,newreference(
  780. p^.right^.location.reference),p^.location.register)));
  781. end;
  782. del_reference(p^.right^.location.reference);
  783. end;
  784. end;
  785. end;
  786. end
  787. else
  788. begin
  789. { when swapped another result register }
  790. if (p^.treetype=subn) and p^.swaped then
  791. begin
  792. if extra_not then
  793. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,p^.location.register)));
  794. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  795. p^.location.register,p^.right^.location.register)));
  796. swap_location(p^.location,p^.right^.location);
  797. { newly swapped also set swapped flag }
  798. { just to maintain ordering }
  799. p^.swaped:=not(p^.swaped);
  800. end
  801. else
  802. begin
  803. if extra_not then
  804. exprasmlist^.concat(new(pai386,op_reg(A_NOT,S_L,p^.right^.location.register)));
  805. exprasmlist^.concat(new(pai386,op_reg_reg(op,opsize,
  806. p^.right^.location.register,
  807. p^.location.register)));
  808. end;
  809. case opsize of
  810. S_L : ungetregister32(p^.right^.location.register);
  811. S_B : ungetregister32(reg8toreg32(p^.right^.location.register));
  812. end;
  813. end;
  814. if cmpop then
  815. case opsize of
  816. S_L : ungetregister32(p^.location.register);
  817. S_B : ungetregister32(reg8toreg32(p^.location.register));
  818. end;
  819. { only in case of overflow operations }
  820. { produce overflow code }
  821. if mboverflow then
  822. { we must put it here directly, because sign of operation }
  823. { is in unsigned VAR!! }
  824. begin
  825. if cs_check_overflow in aktswitches then
  826. begin
  827. getlabel(hl4);
  828. if unsigned then
  829. emitl(A_JNB,hl4)
  830. else
  831. emitl(A_JNO,hl4);
  832. emitcall('RE_OVERFLOW',true);
  833. emitl(A_LABEL,hl4);
  834. end;
  835. end;
  836. end
  837. else if ((p^.left^.resulttype^.deftype=orddef) and
  838. (porddef(p^.left^.resulttype)^.typ=uchar)) then
  839. begin
  840. case p^.treetype of
  841. ltn,lten,gtn,gten,
  842. equaln,unequaln :
  843. cmpop:=true;
  844. else Message(sym_e_type_mismatch);
  845. end;
  846. unsigned:=true;
  847. { left and right no register? }
  848. { the one must be demanded }
  849. if (p^.location.loc<>LOC_REGISTER) and
  850. (p^.right^.location.loc<>LOC_REGISTER) then
  851. begin
  852. if p^.location.loc=LOC_CREGISTER then
  853. begin
  854. if cmpop then
  855. { do not disturb register }
  856. hregister:=p^.location.register
  857. else
  858. begin
  859. hregister:=reg32toreg8(getregister32);
  860. emit_reg_reg(A_MOV,S_B,p^.location.register,
  861. hregister);
  862. end;
  863. end
  864. else
  865. begin
  866. del_reference(p^.location.reference);
  867. { first give free then demand new register }
  868. hregister:=reg32toreg8(getregister32);
  869. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_B,newreference(p^.location.reference),
  870. hregister)));
  871. end;
  872. p^.location.loc:=LOC_REGISTER;
  873. p^.location.register:=hregister;
  874. end;
  875. { now p always a register }
  876. if (p^.right^.location.loc=LOC_REGISTER) and
  877. (p^.location.loc<>LOC_REGISTER) then
  878. begin
  879. swap_location(p^.location,p^.right^.location);
  880. { newly swapped also set swapped flag }
  881. p^.swaped:=not(p^.swaped);
  882. end;
  883. if p^.right^.location.loc<>LOC_REGISTER then
  884. begin
  885. if p^.right^.location.loc=LOC_CREGISTER then
  886. begin
  887. emit_reg_reg(A_CMP,S_B,
  888. p^.right^.location.register,p^.location.register);
  889. end
  890. else
  891. begin
  892. exprasmlist^.concat(new(pai386,op_ref_reg(A_CMP,S_B,newreference(
  893. p^.right^.location.reference),p^.location.register)));
  894. del_reference(p^.right^.location.reference);
  895. end;
  896. end
  897. else
  898. begin
  899. emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  900. p^.location.register);
  901. ungetregister32(reg8toreg32(p^.right^.location.register));
  902. end;
  903. ungetregister32(reg8toreg32(p^.location.register));
  904. end
  905. else if (p^.left^.resulttype^.deftype=floatdef) and
  906. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  907. begin
  908. { real constants to the left }
  909. if p^.left^.treetype=realconstn then
  910. begin
  911. swapp:=p^.right;
  912. p^.right:=p^.left;
  913. p^.left:=swapp;
  914. p^.swaped:=not(p^.swaped);
  915. end;
  916. cmpop:=false;
  917. case p^.treetype of
  918. addn : op:=A_FADDP;
  919. muln : op:=A_FMULP;
  920. subn : op:=A_FSUBP;
  921. slashn : op:=A_FDIVP;
  922. ltn,lten,gtn,gten,
  923. equaln,unequaln : begin
  924. op:=A_FCOMPP;
  925. cmpop:=true;
  926. end;
  927. else Message(sym_e_type_mismatch);
  928. end;
  929. if (p^.right^.location.loc<>LOC_FPU) then
  930. begin
  931. floatload(pfloatdef(p^.right^.resulttype)^.typ,p^.right^.location.reference);
  932. if (p^.left^.location.loc<>LOC_FPU) then
  933. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  934. { left was on the stack => swap }
  935. else
  936. p^.swaped:=not(p^.swaped);
  937. { releases the right reference }
  938. del_reference(p^.right^.location.reference);
  939. end
  940. { the nominator in st0 }
  941. else if (p^.left^.location.loc<>LOC_FPU) then
  942. floatload(pfloatdef(p^.left^.resulttype)^.typ,p^.left^.location.reference)
  943. { fpu operands are always in the wrong order on the stack }
  944. else
  945. p^.swaped:=not(p^.swaped);
  946. { releases the left reference }
  947. if (p^.left^.location.loc<>LOC_FPU) then
  948. del_reference(p^.left^.location.reference);
  949. { if we swaped the tree nodes, then use the reverse operator }
  950. if p^.swaped then
  951. begin
  952. if (p^.treetype=slashn) then
  953. op:=A_FDIVRP
  954. else if (p^.treetype=subn) then
  955. op:=A_FSUBRP;
  956. end;
  957. { to avoid the pentium bug
  958. if (op=FDIVP) and (opt_processors=pentium) then
  959. exprasmlist^.concat(new(pai386,op_CALL,S_NO,'EMUL_FDIVP')
  960. else
  961. }
  962. { the Intel assemblers want operands }
  963. if op<>A_FCOMPP then
  964. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,R_ST,R_ST1)))
  965. else
  966. exprasmlist^.concat(new(pai386,op_none(op,S_NO)));
  967. { on comparison load flags }
  968. if cmpop then
  969. begin
  970. if not(R_EAX in unused) then
  971. emit_reg_reg(A_MOV,S_L,R_EAX,R_EDI);
  972. exprasmlist^.concat(new(pai386,op_reg(A_FNSTSW,S_NO,R_AX)));
  973. exprasmlist^.concat(new(pai386,op_none(A_SAHF,S_NO)));
  974. if not(R_EAX in unused) then
  975. emit_reg_reg(A_MOV,S_L,R_EDI,R_EAX);
  976. if p^.swaped then
  977. case p^.treetype of
  978. equaln : flags:=F_E;
  979. unequaln : flags:=F_NE;
  980. ltn : flags:=F_A;
  981. lten : flags:=F_AE;
  982. gtn : flags:=F_B;
  983. gten : flags:=F_BE;
  984. end
  985. else
  986. case p^.treetype of
  987. equaln : flags:=F_E;
  988. unequaln : flags:=F_NE;
  989. ltn : flags:=F_B;
  990. lten : flags:=F_BE;
  991. gtn : flags:=F_A;
  992. gten : flags:=F_AE;
  993. end;
  994. p^.location.loc:=LOC_FLAGS;
  995. p^.location.resflags:=flags;
  996. cmpop:=false;
  997. end
  998. else
  999. p^.location.loc:=LOC_FPU;
  1000. end
  1001. {$ifdef SUPPORT_MMX}
  1002. else if is_mmx_able_array(p^.left^.resulttype) then
  1003. begin
  1004. cmpop:=false;
  1005. mmxbase:=mmx_type(p^.left^.resulttype);
  1006. case p^.treetype of
  1007. addn : begin
  1008. if (cs_mmx_saturation in aktswitches) then
  1009. begin
  1010. case mmxbase of
  1011. mmxs8bit:
  1012. op:=A_PADDSB;
  1013. mmxu8bit:
  1014. op:=A_PADDUSB;
  1015. mmxs16bit,mmxfixed16:
  1016. op:=A_PADDSB;
  1017. mmxu16bit:
  1018. op:=A_PADDUSW;
  1019. end;
  1020. end
  1021. else
  1022. begin
  1023. case mmxbase of
  1024. mmxs8bit,mmxu8bit:
  1025. op:=A_PADDB;
  1026. mmxs16bit,mmxu16bit,mmxfixed16:
  1027. op:=A_PADDW;
  1028. mmxs32bit,mmxu32bit:
  1029. op:=A_PADDD;
  1030. end;
  1031. end;
  1032. end;
  1033. muln : begin
  1034. case mmxbase of
  1035. mmxs16bit,mmxu16bit:
  1036. op:=A_PMULLW;
  1037. mmxfixed16:
  1038. op:=A_PMULHW;
  1039. end;
  1040. end;
  1041. subn : begin
  1042. if (cs_mmx_saturation in aktswitches) then
  1043. begin
  1044. case mmxbase of
  1045. mmxs8bit:
  1046. op:=A_PSUBSB;
  1047. mmxu8bit:
  1048. op:=A_PSUBUSB;
  1049. mmxs16bit,mmxfixed16:
  1050. op:=A_PSUBSB;
  1051. mmxu16bit:
  1052. op:=A_PSUBUSW;
  1053. end;
  1054. end
  1055. else
  1056. begin
  1057. case mmxbase of
  1058. mmxs8bit,mmxu8bit:
  1059. op:=A_PSUBB;
  1060. mmxs16bit,mmxu16bit,mmxfixed16:
  1061. op:=A_PSUBW;
  1062. mmxs32bit,mmxu32bit:
  1063. op:=A_PSUBD;
  1064. end;
  1065. end;
  1066. end;
  1067. {
  1068. ltn,lten,gtn,gten,
  1069. equaln,unequaln :
  1070. begin
  1071. op:=A_CMP;
  1072. cmpop:=true;
  1073. end;
  1074. }
  1075. xorn:
  1076. op:=A_PXOR;
  1077. orn:
  1078. op:=A_POR;
  1079. andn:
  1080. op:=A_PAND;
  1081. else Message(sym_e_type_mismatch);
  1082. end;
  1083. { left and right no register? }
  1084. { then one must be demanded }
  1085. if (p^.left^.location.loc<>LOC_MMXREGISTER) and
  1086. (p^.right^.location.loc<>LOC_MMXREGISTER) then
  1087. begin
  1088. { register variable ? }
  1089. if (p^.left^.location.loc=LOC_CMMXREGISTER) then
  1090. begin
  1091. { it is OK if this is the destination }
  1092. if is_in_dest then
  1093. begin
  1094. hregister:=p^.location.register;
  1095. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1096. hregister);
  1097. end
  1098. else
  1099. begin
  1100. hregister:=getregistermmx;
  1101. emit_reg_reg(A_MOVQ,S_NO,p^.left^.location.register,
  1102. hregister);
  1103. end
  1104. end
  1105. else
  1106. begin
  1107. del_reference(p^.left^.location.reference);
  1108. if is_in_dest then
  1109. begin
  1110. hregister:=p^.location.register;
  1111. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1112. newreference(p^.left^.location.reference),hregister)));
  1113. end
  1114. else
  1115. begin
  1116. hregister:=getregistermmx;
  1117. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1118. newreference(p^.left^.location.reference),hregister)));
  1119. end;
  1120. end;
  1121. p^.location.loc:=LOC_MMXREGISTER;
  1122. p^.location.register:=hregister;
  1123. end
  1124. else
  1125. { if on the right the register then swap }
  1126. if (p^.right^.location.loc=LOC_MMXREGISTER) then
  1127. begin
  1128. swap_location(p^.location,p^.right^.location);
  1129. { newly swapped also set swapped flag }
  1130. p^.swaped:=not(p^.swaped);
  1131. end;
  1132. { at this point, p^.location.loc should be LOC_MMXREGISTER }
  1133. { and p^.location.register should be a valid register }
  1134. { containing the left result }
  1135. if p^.right^.location.loc<>LOC_MMXREGISTER then
  1136. begin
  1137. if (p^.treetype=subn) and p^.swaped then
  1138. begin
  1139. if p^.right^.location.loc=LOC_CMMXREGISTER then
  1140. begin
  1141. emit_reg_reg(A_MOVQ,S_NO,p^.right^.location.register,R_MM7);
  1142. emit_reg_reg(op,S_NO,p^.location.register,R_EDI);
  1143. emit_reg_reg(A_MOVQ,S_NO,R_MM7,p^.location.register);
  1144. end
  1145. else
  1146. begin
  1147. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOVQ,S_NO,
  1148. newreference(p^.right^.location.reference),R_MM7)));
  1149. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,p^.location.register,
  1150. R_MM7)));
  1151. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVQ,S_NO,
  1152. R_MM7,p^.location.register)));
  1153. del_reference(p^.right^.location.reference);
  1154. end;
  1155. end
  1156. else
  1157. begin
  1158. if (p^.right^.location.loc=LOC_CREGISTER) then
  1159. begin
  1160. emit_reg_reg(op,S_NO,p^.right^.location.register,
  1161. p^.location.register);
  1162. end
  1163. else
  1164. begin
  1165. exprasmlist^.concat(new(pai386,op_ref_reg(op,S_NO,newreference(
  1166. p^.right^.location.reference),p^.location.register)));
  1167. del_reference(p^.right^.location.reference);
  1168. end;
  1169. end;
  1170. end
  1171. else
  1172. begin
  1173. { when swapped another result register }
  1174. if (p^.treetype=subn) and p^.swaped then
  1175. begin
  1176. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,
  1177. p^.location.register,p^.right^.location.register)));
  1178. swap_location(p^.location,p^.right^.location);
  1179. { newly swapped also set swapped flag }
  1180. { just to maintain ordering }
  1181. p^.swaped:=not(p^.swaped);
  1182. end
  1183. else
  1184. begin
  1185. exprasmlist^.concat(new(pai386,op_reg_reg(op,S_NO,
  1186. p^.right^.location.register,
  1187. p^.location.register)));
  1188. end;
  1189. ungetregistermmx(p^.right^.location.register);
  1190. end;
  1191. end
  1192. {$endif SUPPORT_MMX}
  1193. else Message(sym_e_type_mismatch);
  1194. end;
  1195. setaddresult(cmpop,unsigned,p);
  1196. end;
  1197. {
  1198. $Log$
  1199. Revision 1.7 1998-05-01 16:38:44 florian
  1200. * handling of private and protected fixed
  1201. + change_keywords_to_tp implemented to remove
  1202. keywords which aren't supported by tp
  1203. * break and continue are now symbols of the system unit
  1204. + widestring, longstring and ansistring type released
  1205. Revision 1.6 1998/04/30 15:59:40 pierre
  1206. * GDB works again better :
  1207. correct type info in one pass
  1208. + UseTokenInfo for better source position
  1209. * fixed one remaining bug in scanner for line counts
  1210. * several little fixes
  1211. Revision 1.5 1998/04/29 10:33:49 pierre
  1212. + added some code for ansistring (not complete nor working yet)
  1213. * corrected operator overloading
  1214. * corrected nasm output
  1215. + started inline procedures
  1216. + added starstarn : use ** for exponentiation (^ gave problems)
  1217. + started UseTokenInfo cond to get accurate positions
  1218. Revision 1.3 1998/04/08 11:34:22 peter
  1219. * nasm works (linux only tested)
  1220. Revision 1.2 1998/03/28 23:09:55 florian
  1221. * secondin bugfix (m68k and i386)
  1222. * overflow checking bugfix (m68k and i386) -- pretty useless in
  1223. secondadd, since everything is done using 32-bit
  1224. * loading pointer to routines hopefully fixed (m68k)
  1225. * flags problem with calls to RTL internal routines fixed (still strcmp
  1226. to fix) (m68k)
  1227. * #ELSE was still incorrect (didn't take care of the previous level)
  1228. * problem with filenames in the command line solved
  1229. * problem with mangledname solved
  1230. * linking name problem solved (was case insensitive)
  1231. * double id problem and potential crash solved
  1232. * stop after first error
  1233. * and=>test problem removed
  1234. * correct read for all float types
  1235. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1236. * push/pop is now correct optimized (=> mov (%esp),reg)
  1237. Revision 1.1.1.1 1998/03/25 11:18:12 root
  1238. * Restored version
  1239. Revision 1.15 1998/03/10 23:48:36 florian
  1240. * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
  1241. enough, it doesn't run
  1242. Revision 1.14 1998/03/10 01:17:18 peter
  1243. * all files have the same header
  1244. * messages are fully implemented, EXTDEBUG uses Comment()
  1245. + AG... files for the Assembler generation
  1246. Revision 1.13 1998/03/09 10:44:38 peter
  1247. + string='', string<>'', string:='', string:=char optimizes (the first 2
  1248. were already in cg68k2)
  1249. Revision 1.12 1998/03/06 00:52:16 peter
  1250. * replaced all old messages from errore.msg, only ExtDebug and some
  1251. Comment() calls are left
  1252. * fixed options.pas
  1253. Revision 1.11 1998/03/02 01:48:30 peter
  1254. * renamed target_DOS to target_GO32V1
  1255. + new verbose system, merged old errors and verbose units into one new
  1256. verbose.pas, so errors.pas is obsolete
  1257. Revision 1.10 1998/02/15 21:27:50 florian
  1258. *** empty log message ***
  1259. }