cgi386ad.inc 55 KB

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