cg386add.pas 59 KB

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