cg386add.pas 69 KB

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