cg386add.pas 59 KB

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