cgi386ad.inc 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338
  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.6 1998-04-30 15:59:40 pierre
  1200. * GDB works again better :
  1201. correct type info in one pass
  1202. + UseTokenInfo for better source position
  1203. * fixed one remaining bug in scanner for line counts
  1204. * several little fixes
  1205. Revision 1.5 1998/04/29 10:33:49 pierre
  1206. + added some code for ansistring (not complete nor working yet)
  1207. * corrected operator overloading
  1208. * corrected nasm output
  1209. + started inline procedures
  1210. + added starstarn : use ** for exponentiation (^ gave problems)
  1211. + started UseTokenInfo cond to get accurate positions
  1212. Revision 1.3 1998/04/08 11:34:22 peter
  1213. * nasm works (linux only tested)
  1214. Revision 1.2 1998/03/28 23:09:55 florian
  1215. * secondin bugfix (m68k and i386)
  1216. * overflow checking bugfix (m68k and i386) -- pretty useless in
  1217. secondadd, since everything is done using 32-bit
  1218. * loading pointer to routines hopefully fixed (m68k)
  1219. * flags problem with calls to RTL internal routines fixed (still strcmp
  1220. to fix) (m68k)
  1221. * #ELSE was still incorrect (didn't take care of the previous level)
  1222. * problem with filenames in the command line solved
  1223. * problem with mangledname solved
  1224. * linking name problem solved (was case insensitive)
  1225. * double id problem and potential crash solved
  1226. * stop after first error
  1227. * and=>test problem removed
  1228. * correct read for all float types
  1229. * 2 sigsegv fixes and a cosmetic fix for Internal Error
  1230. * push/pop is now correct optimized (=> mov (%esp),reg)
  1231. Revision 1.1.1.1 1998/03/25 11:18:12 root
  1232. * Restored version
  1233. Revision 1.15 1998/03/10 23:48:36 florian
  1234. * a couple of bug fixes to get the compiler with -OGaxz compiler, sadly
  1235. enough, it doesn't run
  1236. Revision 1.14 1998/03/10 01:17:18 peter
  1237. * all files have the same header
  1238. * messages are fully implemented, EXTDEBUG uses Comment()
  1239. + AG... files for the Assembler generation
  1240. Revision 1.13 1998/03/09 10:44:38 peter
  1241. + string='', string<>'', string:='', string:=char optimizes (the first 2
  1242. were already in cg68k2)
  1243. Revision 1.12 1998/03/06 00:52:16 peter
  1244. * replaced all old messages from errore.msg, only ExtDebug and some
  1245. Comment() calls are left
  1246. * fixed options.pas
  1247. Revision 1.11 1998/03/02 01:48:30 peter
  1248. * renamed target_DOS to target_GO32V1
  1249. + new verbose system, merged old errors and verbose units into one new
  1250. verbose.pas, so errors.pas is obsolete
  1251. Revision 1.10 1998/02/15 21:27:50 florian
  1252. *** empty log message ***
  1253. }