cg386add.pas 68 KB

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