cg68kadd.pas 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 by Florian Klaempfl
  4. Generate m68k assembler for 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 cg68kadd;
  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. temp_gen,hcodegen,pass_2,
  28. m68k,cga68k,tgen68k;
  29. {*****************************************************************************
  30. Helpers
  31. *****************************************************************************}
  32. procedure processcc(p: ptree);
  33. const
  34. { process condition codes bit definitions }
  35. CARRY_FLAG = $01;
  36. OVFL_FLAG = $02;
  37. ZERO_FLAG = $04;
  38. NEG_FLAG = $08;
  39. var
  40. label1,label2: plabel;
  41. (*************************************************************************)
  42. (* Description: This routine handles the conversion of Floating point *)
  43. (* condition codes to normal cpu condition codes. *)
  44. (*************************************************************************)
  45. begin
  46. getlabel(label1);
  47. getlabel(label2);
  48. case p^.treetype of
  49. equaln,unequaln: begin
  50. { not equal clear zero flag }
  51. emitl(A_FBEQ,label1);
  52. exprasmlist^.concat(new(pai68k, op_const_reg(
  53. A_AND, S_B, NOT ZERO_FLAG, R_CCR)));
  54. emitl(A_BRA,label2);
  55. emitl(A_LABEL,label1);
  56. { equal - set zero flag }
  57. exprasmlist^.concat(new(pai68k, op_const_reg(
  58. A_OR,S_B, ZERO_FLAG, R_CCR)));
  59. emitl(A_LABEL,label2);
  60. end;
  61. ltn: begin
  62. emitl(A_FBLT,label1);
  63. { not less than }
  64. { clear N and V flags }
  65. exprasmlist^.concat(new(pai68k, op_const_reg(
  66. A_AND, S_B, NOT (NEG_FLAG OR OVFL_FLAG), R_CCR)));
  67. emitl(A_BRA,label2);
  68. emitl(A_LABEL,label1);
  69. { less than }
  70. exprasmlist^.concat(new(pai68k, op_const_reg(
  71. A_OR,S_B, NEG_FLAG, R_CCR)));
  72. exprasmlist^.concat(new(pai68k, op_const_reg(
  73. A_AND,S_B, NOT OVFL_FLAG, R_CCR)));
  74. emitl(A_LABEL,label2);
  75. end;
  76. gtn: begin
  77. emitl(A_FBGT,label1);
  78. { not greater than }
  79. { set Z flag }
  80. exprasmlist^.concat(new(pai68k, op_const_reg(
  81. A_OR, S_B, ZERO_FLAG, R_CCR)));
  82. emitl(A_BRA,label2);
  83. emitl(A_LABEL,label1);
  84. { greater than }
  85. { set N and V flags }
  86. exprasmlist^.concat(new(pai68k, op_const_reg(
  87. A_OR,S_B, NEG_FLAG OR OVFL_FLAG , R_CCR)));
  88. emitl(A_LABEL,label2);
  89. end;
  90. gten: begin
  91. emitl(A_FBGE,label1);
  92. { not greater or equal }
  93. { set N and clear V }
  94. exprasmlist^.concat(new(pai68k, op_const_reg(
  95. A_AND, S_B, NOT OVFL_FLAG, R_CCR)));
  96. exprasmlist^.concat(new(pai68k, op_const_reg(
  97. A_OR,S_B, NEG_FLAG, R_CCR)));
  98. emitl(A_BRA,label2);
  99. emitl(A_LABEL,label1);
  100. { greater or equal }
  101. { clear V and N flags }
  102. exprasmlist^.concat(new(pai68k, op_const_reg(
  103. A_AND, S_B, NOT (OVFL_FLAG OR NEG_FLAG), R_CCR)));
  104. emitl(A_LABEL,label2);
  105. end;
  106. lten: begin
  107. emitl(A_FBLE,label1);
  108. { not less or equal }
  109. { clear Z, N and V }
  110. exprasmlist^.concat(new(pai68k, op_const_reg(
  111. A_AND, S_B, NOT (ZERO_FLAG OR NEG_FLAG OR OVFL_FLAG), R_CCR)));
  112. emitl(A_BRA,label2);
  113. emitl(A_LABEL,label1);
  114. { less or equal }
  115. { set Z and N }
  116. { and clear V }
  117. exprasmlist^.concat(new(pai68k, op_const_reg(
  118. A_OR,S_B, ZERO_FLAG OR NEG_FLAG, R_CCR)));
  119. exprasmlist^.concat(new(pai68k, op_const_reg(
  120. A_AND,S_B, NOT OVFL_FLAG, R_CCR)));
  121. emitl(A_LABEL,label2);
  122. end;
  123. else
  124. begin
  125. InternalError(34);
  126. end;
  127. end; { end case }
  128. end;
  129. procedure SetResultLocation(cmpop,unsigned:boolean;var p :ptree);
  130. var
  131. flags : tresflags;
  132. begin
  133. { remove temporary location if not a set or string }
  134. if (p^.left^.resulttype^.deftype<>stringdef) and
  135. ((p^.left^.resulttype^.deftype<>setdef) or (psetdef(p^.left^.resulttype)^.settype=smallset)) and
  136. (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  137. ungetiftemp(p^.left^.location.reference);
  138. if (p^.right^.resulttype^.deftype<>stringdef) and
  139. ((p^.right^.resulttype^.deftype<>setdef) or (psetdef(p^.right^.resulttype)^.settype=smallset)) and
  140. (p^.right^.location.loc in [LOC_MEM,LOC_REFERENCE]) then
  141. ungetiftemp(p^.right^.location.reference);
  142. { in case of comparison operation the put result in the flags }
  143. if cmpop then
  144. begin
  145. if not(unsigned) then
  146. begin
  147. if p^.swaped then
  148. case p^.treetype of
  149. equaln : flags:=F_E;
  150. unequaln : flags:=F_NE;
  151. ltn : flags:=F_G;
  152. lten : flags:=F_GE;
  153. gtn : flags:=F_L;
  154. gten : flags:=F_LE;
  155. end
  156. else
  157. case p^.treetype of
  158. equaln : flags:=F_E;
  159. unequaln : flags:=F_NE;
  160. ltn : flags:=F_L;
  161. lten : flags:=F_LE;
  162. gtn : flags:=F_G;
  163. gten : flags:=F_GE;
  164. end;
  165. end
  166. else
  167. begin
  168. if p^.swaped then
  169. case p^.treetype of
  170. equaln : flags:=F_E;
  171. unequaln : flags:=F_NE;
  172. ltn : flags:=F_A;
  173. lten : flags:=F_AE;
  174. gtn : flags:=F_B;
  175. gten : flags:=F_BE;
  176. end
  177. else
  178. case p^.treetype of
  179. equaln : flags:=F_E;
  180. unequaln : flags:=F_NE;
  181. ltn : flags:=F_B;
  182. lten : flags:=F_BE;
  183. gtn : flags:=F_A;
  184. gten : flags:=F_AE;
  185. end;
  186. end;
  187. clear_location(p^.location);
  188. p^.location.loc:=LOC_FLAGS;
  189. p^.location.resflags:=flags;
  190. end;
  191. end;
  192. {*****************************************************************************
  193. Addstring
  194. *****************************************************************************}
  195. procedure addstring(var p : ptree);
  196. var
  197. pushedregs : tpushed;
  198. href : treference;
  199. pushed,
  200. cmpop : boolean;
  201. begin
  202. { string operations are not commutative }
  203. if p^.swaped then
  204. swaptree(p);
  205. {$ifdef UseAnsiString}
  206. if is_ansistring(p^.left^.resulttype) then
  207. begin
  208. case p^.treetype of
  209. addn :
  210. begin
  211. { we do not need destination anymore }
  212. del_reference(p^.left^.location.reference);
  213. del_reference(p^.right^.location.reference);
  214. { concatansistring(p); }
  215. end;
  216. ltn,lten,gtn,gten,
  217. equaln,unequaln :
  218. begin
  219. pushusedregisters(pushedregs,$ff);
  220. secondpass(p^.left);
  221. del_reference(p^.left^.location.reference);
  222. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  223. secondpass(p^.right);
  224. del_reference(p^.right^.location.reference);
  225. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  226. emitcall('FPC_ANSISTRCMP',true);
  227. maybe_loada5;
  228. popusedregisters(pushedregs);
  229. end;
  230. end;
  231. end
  232. else
  233. {$endif UseAnsiString}
  234. case p^.treetype of
  235. addn : begin
  236. cmpop:=false;
  237. secondpass(p^.left);
  238. if (p^.left^.treetype<>addn) then
  239. begin
  240. { can only reference be }
  241. { string in register would be funny }
  242. { therefore produce a temporary string }
  243. { release the registers }
  244. del_reference(p^.left^.location.reference);
  245. gettempofsizereference(256,href);
  246. copystring(href,p^.left^.location.reference,255);
  247. ungetiftemp(p^.left^.location.reference);
  248. { does not hurt: }
  249. clear_location(p^.left^.location);
  250. p^.left^.location.loc:=LOC_MEM;
  251. p^.left^.location.reference:=href;
  252. end;
  253. secondpass(p^.right);
  254. { on the right we do not need the register anymore too }
  255. del_reference(p^.right^.location.reference);
  256. pushusedregisters(pushedregs,$ffff);
  257. { WE INVERSE THE PARAMETERS!!! }
  258. { Because parameters are inversed in the rtl }
  259. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  260. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  261. emitcall('FPC_STRCONCAT',true);
  262. maybe_loadA5;
  263. popusedregisters(pushedregs);
  264. set_location(p^.location,p^.left^.location);
  265. ungetiftemp(p^.right^.location.reference);
  266. end; { this case }
  267. ltn,lten,gtn,gten,
  268. equaln,unequaln :
  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. cmpop:=true;
  276. del_reference(p^.right^.location.reference);
  277. del_reference(p^.left^.location.reference);
  278. { generates better code }
  279. { s='' and s<>'' }
  280. if (p^.treetype in [equaln,unequaln]) and
  281. (
  282. ((p^.left^.treetype=stringconstn) and
  283. (str_length(p^.left)=0)) or
  284. ((p^.right^.treetype=stringconstn) and
  285. (str_length(p^.right)=0))
  286. ) then
  287. begin
  288. { only one node can be stringconstn }
  289. { else pass 1 would have evaluted }
  290. { this node }
  291. if p^.left^.treetype=stringconstn then
  292. exprasmlist^.concat(new(pai68k,op_ref(
  293. A_TST,S_B,newreference(p^.right^.location.reference))))
  294. else
  295. exprasmlist^.concat(new(pai68k,op_ref(
  296. A_TST,S_B,newreference(p^.left^.location.reference))));
  297. end
  298. else
  299. begin
  300. pushusedregisters(pushedregs,$ffff);
  301. { parameters are directly passed via registers }
  302. { this has several advantages, no loss of the flags }
  303. { on exit ,and MUCH faster on m68k machines }
  304. { speed difference (68000) }
  305. { normal routine: entry, exit code + push = 124 }
  306. { (best case) }
  307. { assembler routine: param setup (worst case) = 48 }
  308. exprasmlist^.concat(new(pai68k,op_ref_reg(
  309. A_LEA,S_L,newreference(p^.left^.location.reference),R_A0)));
  310. exprasmlist^.concat(new(pai68k,op_ref_reg(
  311. A_LEA,S_L,newreference(p^.right^.location.reference),R_A1)));
  312. {
  313. emitpushreferenceaddr(p^.left^.location.reference);
  314. emitpushreferenceaddr(p^.right^.location.reference); }
  315. emitcall('FPC_STRCMP',true);
  316. maybe_loada5;
  317. popusedregisters(pushedregs);
  318. end;
  319. ungetiftemp(p^.left^.location.reference);
  320. ungetiftemp(p^.right^.location.reference);
  321. end; { end this case }
  322. else CGMessage(type_e_mismatch);
  323. end; { end case }
  324. SetResultLocation(cmpop,true,p);
  325. end;
  326. {*****************************************************************************
  327. Addset
  328. *****************************************************************************}
  329. procedure addset(var p : ptree);
  330. var
  331. cmpop,
  332. pushed : boolean;
  333. href : treference;
  334. pushedregs : tpushed;
  335. begin
  336. cmpop:=false;
  337. { not commutative }
  338. if p^.swaped then
  339. swaptree(p);
  340. secondpass(p^.left);
  341. { are too few registers free? }
  342. pushed:=maybe_push(p^.right^.registers32,p);
  343. secondpass(p^.right);
  344. if codegenerror then
  345. exit;
  346. if pushed then
  347. restore(p);
  348. set_location(p^.location,p^.left^.location);
  349. { handle operations }
  350. case p^.treetype of
  351. equaln,
  352. unequaln : begin
  353. cmpop:=true;
  354. del_reference(p^.left^.location.reference);
  355. del_reference(p^.right^.location.reference);
  356. pushusedregisters(pushedregs,$ff);
  357. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  358. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  359. emitcall('FPC_SET_COMP_SETS',true);
  360. maybe_loada5;
  361. popusedregisters(pushedregs);
  362. ungetiftemp(p^.left^.location.reference);
  363. ungetiftemp(p^.right^.location.reference);
  364. end;
  365. addn : begin
  366. { add can be an other SET or Range or Element ! }
  367. del_reference(p^.left^.location.reference);
  368. del_reference(p^.right^.location.reference);
  369. pushusedregisters(pushedregs,$ff);
  370. href.symbol:=nil;
  371. gettempofsizereference(32,href);
  372. { add a range or a single element? }
  373. if p^.right^.treetype=setelementn then
  374. begin
  375. concatcopy(p^.left^.location.reference,href,32,false);
  376. if assigned(p^.right^.right) then
  377. begin
  378. loadsetelement(p^.right^.right);
  379. loadsetelement(p^.right^.left);
  380. emitpushreferenceaddr(exprasmlist,href);
  381. emitcall('FPC_SET_SET_RANGE',true);
  382. end
  383. else
  384. begin
  385. loadsetelement(p^.right^.left);
  386. emitpushreferenceaddr(exprasmlist,href);
  387. emitcall('FPC_SET_SET_BYTE',true);
  388. end;
  389. end
  390. else
  391. begin
  392. { must be an other set }
  393. emitpushreferenceaddr(exprasmlist,href);
  394. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  395. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  396. emitcall('FPC_SET_ADD_SETS',true);
  397. end;
  398. maybe_loada5;
  399. popusedregisters(pushedregs);
  400. ungetiftemp(p^.left^.location.reference);
  401. ungetiftemp(p^.right^.location.reference);
  402. p^.location.loc:=LOC_MEM;
  403. stringdispose(p^.location.reference.symbol);
  404. p^.location.reference:=href;
  405. end;
  406. subn,
  407. symdifn,
  408. muln : begin
  409. del_reference(p^.left^.location.reference);
  410. del_reference(p^.right^.location.reference);
  411. href.symbol:=nil;
  412. pushusedregisters(pushedregs,$ff);
  413. gettempofsizereference(32,href);
  414. emitpushreferenceaddr(exprasmlist,href);
  415. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  416. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  417. case p^.treetype of
  418. subn : emitcall('FPC_SET_SUB_SETS',true);
  419. symdifn : emitcall('FPC_SET_SYMDIF_SETS',true);
  420. muln : emitcall('FPC_SET_MUL_SETS',true);
  421. end;
  422. maybe_loada5;
  423. popusedregisters(pushedregs);
  424. ungetiftemp(p^.left^.location.reference);
  425. ungetiftemp(p^.right^.location.reference);
  426. p^.location.loc:=LOC_MEM;
  427. stringdispose(p^.location.reference.symbol);
  428. p^.location.reference:=href;
  429. end;
  430. else
  431. CGMessage(type_e_mismatch);
  432. end;
  433. SetResultLocation(cmpop,true,p);
  434. end;
  435. {*****************************************************************************
  436. SecondAdd
  437. *****************************************************************************}
  438. procedure secondadd(var p : ptree);
  439. { is also being used for xor, and "mul", "sub, or and comparative }
  440. { operators }
  441. label do_normal;
  442. var
  443. hregister : tregister;
  444. noswap,
  445. pushed,mboverflow,cmpop : boolean;
  446. op : tasmop;
  447. flags : tresflags;
  448. otl,ofl : plabel;
  449. power : longint;
  450. opsize : topsize;
  451. hl4: plabel;
  452. tmpref : treference;
  453. { true, if unsigned types are compared }
  454. unsigned : boolean;
  455. { true, if a small set is handled with the longint code }
  456. is_set : boolean;
  457. { is_in_dest if the result is put directly into }
  458. { the resulting refernce or varregister }
  459. is_in_dest : boolean;
  460. { true, if for sets subtractions the extra not should generated }
  461. extra_not : boolean;
  462. begin
  463. { to make it more readable, string and set (not smallset!) have their
  464. own procedures }
  465. case p^.left^.resulttype^.deftype of
  466. stringdef : begin
  467. addstring(p);
  468. exit;
  469. end;
  470. setdef : begin
  471. { normalsets are handled separate }
  472. if not(psetdef(p^.left^.resulttype)^.settype=smallset) then
  473. begin
  474. addset(p);
  475. exit;
  476. end;
  477. end;
  478. end;
  479. { defaults }
  480. unsigned:=false;
  481. is_in_dest:=false;
  482. extra_not:=false;
  483. noswap:=false;
  484. opsize:=S_L;
  485. { are we a (small)set, must be set here because the side can be
  486. swapped ! (PFV) }
  487. is_set:=(p^.left^.resulttype^.deftype=setdef);
  488. { calculate the operator which is more difficult }
  489. firstcomplex(p);
  490. { handling boolean expressions extra: }
  491. if ((p^.left^.resulttype^.deftype=orddef) and
  492. (porddef(p^.left^.resulttype)^.typ in [bool8bit,bool16bit,bool32bit])) or
  493. ((p^.right^.resulttype^.deftype=orddef) and
  494. (porddef(p^.right^.resulttype)^.typ in [bool8bit,bool16bit,bool32bit])) then
  495. begin
  496. if (porddef(p^.left^.resulttype)^.typ=bool8bit) or
  497. (porddef(p^.right^.resulttype)^.typ=bool8bit) then
  498. opsize:=S_B
  499. else
  500. if (porddef(p^.left^.resulttype)^.typ=bool16bit) or
  501. (porddef(p^.right^.resulttype)^.typ=bool16bit) then
  502. opsize:=S_W
  503. else
  504. opsize:=S_L;
  505. case p^.treetype of
  506. andn,
  507. orn : begin
  508. clear_location(p^.location);
  509. p^.location.loc:=LOC_JUMP;
  510. cmpop:=false;
  511. case p^.treetype of
  512. andn : begin
  513. otl:=truelabel;
  514. getlabel(truelabel);
  515. secondpass(p^.left);
  516. maketojumpbool(p^.left);
  517. emitl(A_LABEL,truelabel);
  518. truelabel:=otl;
  519. end;
  520. orn : begin
  521. ofl:=falselabel;
  522. getlabel(falselabel);
  523. secondpass(p^.left);
  524. maketojumpbool(p^.left);
  525. emitl(A_LABEL,falselabel);
  526. falselabel:=ofl;
  527. end;
  528. else
  529. CGMessage(type_e_mismatch);
  530. end;
  531. secondpass(p^.right);
  532. maketojumpbool(p^.right);
  533. end;
  534. unequaln,
  535. equaln,xorn : begin
  536. if p^.left^.treetype=ordconstn then
  537. swaptree(p);
  538. secondpass(p^.left);
  539. p^.location:=p^.left^.location;
  540. { are enough registers free ? }
  541. pushed:=maybe_push(p^.right^.registers32,p);
  542. secondpass(p^.right);
  543. if pushed then restore(p);
  544. goto do_normal;
  545. end
  546. else
  547. CGMessage(type_e_mismatch);
  548. end
  549. end
  550. else
  551. begin
  552. { in case of constant put it to the left }
  553. if (p^.left^.treetype=ordconstn) then
  554. swaptree(p);
  555. secondpass(p^.left);
  556. { this will be complicated as
  557. a lot of code below assumes that
  558. p^.location and p^.left^.location are the same }
  559. {$ifdef test_dest_loc}
  560. if dest_loc_known and (dest_loc_tree=p) and
  561. ((dest_loc.loc=LOC_REGISTER) or (dest_loc.loc=LOC_CREGISTER)) then
  562. begin
  563. set_location(p^.location,dest_loc);
  564. in_dest_loc:=true;
  565. is_in_dest:=true;
  566. end
  567. else
  568. {$endif test_dest_loc}
  569. set_location(p^.location,p^.left^.location);
  570. { are too few registers free? }
  571. pushed:=maybe_push(p^.right^.registers32,p);
  572. secondpass(p^.right);
  573. if pushed then
  574. restore(p);
  575. if (p^.left^.resulttype^.deftype=pointerdef) or
  576. (p^.right^.resulttype^.deftype=pointerdef) or
  577. ((p^.right^.resulttype^.deftype=objectdef) and
  578. pobjectdef(p^.right^.resulttype)^.isclass and
  579. (p^.left^.resulttype^.deftype=objectdef) and
  580. pobjectdef(p^.left^.resulttype)^.isclass
  581. ) or
  582. (p^.left^.resulttype^.deftype=classrefdef) or
  583. (p^.left^.resulttype^.deftype=procvardef) or
  584. (p^.left^.resulttype^.deftype=enumdef) or
  585. ((p^.left^.resulttype^.deftype=orddef) and
  586. (porddef(p^.left^.resulttype)^.typ=s32bit)) or
  587. ((p^.right^.resulttype^.deftype=orddef) and
  588. (porddef(p^.right^.resulttype)^.typ=s32bit)) or
  589. ((p^.left^.resulttype^.deftype=orddef) and
  590. (porddef(p^.left^.resulttype)^.typ=u32bit)) or
  591. ((p^.right^.resulttype^.deftype=orddef) and
  592. (porddef(p^.right^.resulttype)^.typ=u32bit)) or
  593. { as well as small sets }
  594. is_set then
  595. begin
  596. do_normal:
  597. mboverflow:=false;
  598. cmpop:=false;
  599. if (p^.left^.resulttype^.deftype=pointerdef) or
  600. (p^.right^.resulttype^.deftype=pointerdef) 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)) then
  605. unsigned:=true;
  606. case p^.treetype of
  607. addn : begin
  608. if is_set then
  609. begin
  610. { adding elements is not commutative }
  611. if p^.swaped and (p^.left^.treetype=setelementn) then
  612. swaptree(p);
  613. { are we adding set elements ? }
  614. if p^.right^.treetype=setelementn then
  615. begin
  616. { no range support for smallsets! }
  617. if assigned(p^.right^.right) then
  618. internalerror(43244);
  619. { Not supported for m68k}
  620. Comment(V_Fatal,'No smallsets for m68k');
  621. end
  622. else
  623. op:=A_OR;
  624. mboverflow:=false;
  625. unsigned:=false;
  626. end
  627. else
  628. begin
  629. op:=A_ADD;
  630. mboverflow:=true;
  631. end;
  632. end;
  633. symdifn : begin
  634. { the symetric diff is only for sets }
  635. if is_set then
  636. begin
  637. op:=A_EOR;
  638. mboverflow:=false;
  639. unsigned:=false;
  640. end
  641. else
  642. CGMessage(type_e_mismatch);
  643. end;
  644. muln : begin
  645. if is_set then
  646. begin
  647. op:=A_AND;
  648. mboverflow:=false;
  649. unsigned:=false;
  650. end
  651. else
  652. begin
  653. if unsigned then
  654. op:=A_MULU
  655. else
  656. op:=A_MULS;
  657. mboverflow:=true;
  658. end;
  659. end;
  660. subn : begin
  661. if is_set then
  662. begin
  663. op:=A_AND;
  664. mboverflow:=false;
  665. unsigned:=false;
  666. extra_not:=true;
  667. end
  668. else
  669. begin
  670. op:=A_SUB;
  671. mboverflow:=true;
  672. end;
  673. end;
  674. ltn,lten,
  675. gtn,gten,
  676. equaln,unequaln : begin
  677. op:=A_CMP;
  678. cmpop:=true;
  679. end;
  680. xorn : op:=A_EOR;
  681. orn : op:=A_OR;
  682. andn : op:=A_AND;
  683. else
  684. CGMessage(type_e_mismatch);
  685. end;
  686. { left and right no register? }
  687. { then one must be demanded }
  688. if (p^.left^.location.loc<>LOC_REGISTER) and
  689. (p^.right^.location.loc<>LOC_REGISTER) then
  690. begin
  691. { register variable ? }
  692. if (p^.left^.location.loc=LOC_CREGISTER) then
  693. begin
  694. { it is OK if this is the destination }
  695. if is_in_dest then
  696. begin
  697. hregister:=p^.location.register;
  698. emit_reg_reg(A_MOVE,opsize,p^.left^.location.register,
  699. hregister);
  700. end
  701. else
  702. if cmpop then
  703. begin
  704. { do not disturb the register }
  705. hregister:=p^.location.register;
  706. end
  707. else
  708. begin
  709. hregister:=getregister32;
  710. emit_reg_reg(A_MOVE,opsize,p^.left^.location.register,
  711. hregister);
  712. end
  713. end
  714. else
  715. begin
  716. del_reference(p^.left^.location.reference);
  717. if is_in_dest then
  718. begin
  719. hregister:=p^.location.register;
  720. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  721. newreference(p^.left^.location.reference),hregister)));
  722. end
  723. else
  724. begin
  725. hregister:=getregister32;
  726. { first give free, then demand new register }
  727. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  728. newreference(p^.left^.location.reference),hregister)));
  729. end;
  730. end;
  731. clear_location(p^.location);
  732. p^.location.loc:=LOC_REGISTER;
  733. p^.location.register:=hregister;
  734. end
  735. else
  736. { if on the right the register then swap }
  737. if not(noswap) and (p^.right^.location.loc=LOC_REGISTER) then
  738. begin
  739. swap_location(p^.location,p^.right^.location);
  740. { newly swapped also set swapped flag }
  741. p^.swaped:=not(p^.swaped);
  742. end;
  743. { at this point, p^.location.loc should be LOC_REGISTER }
  744. { and p^.location.register should be a valid register }
  745. { containing the left result }
  746. if p^.right^.location.loc<>LOC_REGISTER then
  747. begin
  748. if (p^.treetype=subn) and p^.swaped then
  749. begin
  750. if p^.right^.location.loc=LOC_CREGISTER then
  751. begin
  752. if extra_not then
  753. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,opsize,p^.location.register)));
  754. emit_reg_reg(A_MOVE,opsize,p^.right^.location.register,R_D6);
  755. emit_reg_reg(op,opsize,p^.location.register,R_D6);
  756. emit_reg_reg(A_MOVE,opsize,R_D6,p^.location.register);
  757. end
  758. else
  759. begin
  760. if extra_not then
  761. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,opsize,p^.location.register)));
  762. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  763. newreference(p^.right^.location.reference),R_D6)));
  764. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,p^.location.register,R_D6)));
  765. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,opsize,R_D6,p^.location.register)));
  766. del_reference(p^.right^.location.reference);
  767. end;
  768. end
  769. else
  770. begin
  771. if (p^.right^.treetype=ordconstn) and (op=A_CMP) and
  772. (p^.right^.value=0) then
  773. exprasmlist^.concat(new(pai68k,op_reg(A_TST,opsize,p^.location.register)))
  774. else
  775. if (p^.right^.treetype=ordconstn) and (op=A_MULS) and
  776. (ispowerof2(p^.right^.value,power)) then
  777. begin
  778. if (power <= 8) then
  779. exprasmlist^.concat(new(pai68k,op_const_reg(A_ASL,opsize,power,
  780. p^.location.register)))
  781. else
  782. begin
  783. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,power,
  784. R_D6)));
  785. exprasmlist^.concat(new(pai68k,op_reg_reg(A_ASL,opsize,R_D6,
  786. p^.location.register)))
  787. end;
  788. end
  789. else
  790. begin
  791. if (p^.right^.location.loc=LOC_CREGISTER) then
  792. begin
  793. if extra_not then
  794. begin
  795. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,R_D6);
  796. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,R_D6)));
  797. emit_reg_reg(A_AND,S_L,R_D6,
  798. p^.location.register);
  799. end
  800. else
  801. begin
  802. if (op=A_MULS) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  803. { Emulation for MC68000 }
  804. begin
  805. emit_reg_reg(A_MOVE,opsize,p^.right^.location.register,
  806. R_D0);
  807. emit_reg_reg(A_MOVE,opsize,p^.location.register,R_D1);
  808. emitcall('FPC_LONGMUL',true);
  809. emit_reg_reg(A_MOVE,opsize,R_D0,p^.location.register);
  810. end
  811. else
  812. if (op=A_MULU) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  813. CGMessage(cg_f_32bit_not_supported_in_68000)
  814. else
  815. emit_reg_reg(op,opsize,p^.right^.location.register,
  816. p^.location.register);
  817. end;
  818. end
  819. else
  820. begin
  821. if extra_not then
  822. begin
  823. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(
  824. p^.right^.location.reference),R_D6)));
  825. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,R_D6)));
  826. emit_reg_reg(A_AND,S_L,R_D6,
  827. p^.location.register);
  828. end
  829. else
  830. begin
  831. if (op=A_MULS) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  832. { Emulation for MC68000 }
  833. begin
  834. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE, opsize,
  835. newreference(p^.right^.location.reference),R_D1)));
  836. emit_reg_reg(A_MOVE,opsize,p^.location.register,R_D0);
  837. emitcall('FPC_LONGMUL',true);
  838. emit_reg_reg(A_MOVE,opsize,R_D0,p^.location.register);
  839. end
  840. else
  841. if (op=A_MULU) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  842. CGMessage(cg_f_32bit_not_supported_in_68000)
  843. else
  844. { When one of the source/destination is a memory reference }
  845. { and the operator is EOR, the we must load it into the }
  846. { value into a register first since only EOR reg,reg exists }
  847. { on the m68k }
  848. if (op=A_EOR) then
  849. begin
  850. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,newreference(
  851. p^.right^.location.reference),R_D0)));
  852. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,R_D0,
  853. p^.location.register)));
  854. end
  855. else
  856. exprasmlist^.concat(new(pai68k,op_ref_reg(op,opsize,newreference(
  857. p^.right^.location.reference),p^.location.register)));
  858. end;
  859. del_reference(p^.right^.location.reference);
  860. end;
  861. end;
  862. end;
  863. end
  864. else
  865. begin
  866. { when swapped another result register }
  867. if (p^.treetype=subn) and p^.swaped then
  868. begin
  869. if extra_not then
  870. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.location.register)));
  871. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,
  872. p^.location.register,p^.right^.location.register)));
  873. swap_location(p^.location,p^.right^.location);
  874. { newly swapped also set swapped flag }
  875. { just to maintain ordering }
  876. p^.swaped:=not(p^.swaped);
  877. end
  878. else
  879. begin
  880. if extra_not then
  881. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.right^.location.register)));
  882. if (op=A_MULS) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  883. { Emulation for MC68000 }
  884. begin
  885. emit_reg_reg(A_MOVE,opsize,p^.right^.location.register,
  886. R_D0);
  887. emit_reg_reg(A_MOVE,opsize,p^.location.register,R_D1);
  888. emitcall('FPC_LONGMUL',true);
  889. emit_reg_reg(A_MOVE,opsize,R_D0,p^.location.register);
  890. end
  891. else
  892. if (op=A_MULU) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  893. CGMessage(cg_f_32bit_not_supported_in_68000)
  894. else
  895. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,
  896. p^.right^.location.register,
  897. p^.location.register)));
  898. end;
  899. ungetregister32(p^.right^.location.register);
  900. end;
  901. if cmpop then
  902. ungetregister32(p^.location.register);
  903. { only in case of overflow operations }
  904. { produce overflow code }
  905. if mboverflow then
  906. emitoverflowcheck(p);
  907. { only in case of overflow operations }
  908. { produce overflow code }
  909. { we must put it here directly, because sign of operation }
  910. { is in unsigned VAR!! }
  911. end
  912. else
  913. { Char type }
  914. if ((p^.left^.resulttype^.deftype=orddef) and
  915. (porddef(p^.left^.resulttype)^.typ=uchar)) then
  916. begin
  917. case p^.treetype of
  918. ltn,lten,gtn,gten,
  919. equaln,unequaln :
  920. cmpop:=true;
  921. else CGMessage(type_e_mismatch);
  922. end;
  923. unsigned:=true;
  924. { left and right no register? }
  925. { the one must be demanded }
  926. if (p^.location.loc<>LOC_REGISTER) and
  927. (p^.right^.location.loc<>LOC_REGISTER) then
  928. begin
  929. if p^.location.loc=LOC_CREGISTER then
  930. begin
  931. if cmpop then
  932. { do not disturb register }
  933. hregister:=p^.location.register
  934. else
  935. begin
  936. hregister:=getregister32;
  937. emit_reg_reg(A_MOVE,S_B,p^.location.register,
  938. hregister);
  939. end;
  940. end
  941. else
  942. begin
  943. del_reference(p^.location.reference);
  944. { first give free then demand new register }
  945. hregister:=getregister32;
  946. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(p^.location.reference),
  947. hregister)));
  948. end;
  949. clear_location(p^.location);
  950. p^.location.loc:=LOC_REGISTER;
  951. p^.location.register:=hregister;
  952. end;
  953. { now p always a register }
  954. if (p^.right^.location.loc=LOC_REGISTER) and
  955. (p^.location.loc<>LOC_REGISTER) then
  956. begin
  957. swap_location(p^.location,p^.right^.location);
  958. { newly swapped also set swapped flag }
  959. p^.swaped:=not(p^.swaped);
  960. end;
  961. if p^.right^.location.loc<>LOC_REGISTER then
  962. begin
  963. if p^.right^.location.loc=LOC_CREGISTER then
  964. begin
  965. emit_reg_reg(A_CMP,S_B,
  966. p^.right^.location.register,p^.location.register);
  967. end
  968. else
  969. begin
  970. exprasmlist^.concat(new(pai68k,op_ref_reg(A_CMP,S_B,newreference(
  971. p^.right^.location.reference),p^.location.register)));
  972. del_reference(p^.right^.location.reference);
  973. end;
  974. end
  975. else
  976. begin
  977. emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  978. p^.location.register);
  979. ungetregister32(p^.right^.location.register);
  980. end;
  981. ungetregister32(p^.location.register);
  982. end
  983. else
  984. { Floating point }
  985. if (p^.left^.resulttype^.deftype=floatdef) and
  986. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  987. begin
  988. { real constants to the left }
  989. if p^.left^.treetype=realconstn then
  990. swaptree(p);
  991. cmpop:=false;
  992. case p^.treetype of
  993. addn : op:=A_FADD;
  994. muln : op:=A_FMUL;
  995. subn : op:=A_FSUB;
  996. slashn : op:=A_FDIV;
  997. ltn,lten,gtn,gten,
  998. equaln,unequaln : begin
  999. op:=A_FCMP;
  1000. cmpop:=true;
  1001. end;
  1002. else CGMessage(type_e_mismatch);
  1003. end;
  1004. if (p^.left^.location.loc <> LOC_FPU) and
  1005. (p^.right^.location.loc <> LOC_FPU) then
  1006. begin
  1007. { we suppose left in reference }
  1008. del_reference(p^.left^.location.reference);
  1009. { get a copy, since we don't want to modify the same }
  1010. { node at the same time. }
  1011. tmpref:=p^.left^.location.reference;
  1012. if assigned(p^.left^.location.reference.symbol) then
  1013. tmpref.symbol:=stringdup(p^.left^.location.reference.symbol^);
  1014. floatload(pfloatdef(p^.left^.resulttype)^.typ, tmpref,
  1015. p^.left^.location);
  1016. clear_reference(tmpref);
  1017. end
  1018. else
  1019. begin
  1020. if (p^.right^.location.loc = LOC_FPU)
  1021. and(p^.left^.location.loc <> LOC_FPU) then
  1022. begin
  1023. swap_location(p^.left^.location, p^.right^.location);
  1024. p^.swaped := not(p^.swaped);
  1025. end
  1026. end;
  1027. { ---------------- LEFT = LOC_FPUREG -------------------- }
  1028. if ((p^.treetype =subn) or (p^.treetype = slashn)) and (p^.swaped) then
  1029. { fpu_reg = right(FP1) / fpu_reg }
  1030. { fpu_reg = right(FP1) - fpu_reg }
  1031. begin
  1032. if (cs_fp_emulation in aktmoduleswitches) then
  1033. begin
  1034. { fpu_reg = right / D1 }
  1035. { fpu_reg = right - D1 }
  1036. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D0)));
  1037. { load value into D1 }
  1038. if p^.right^.location.loc <> LOC_FPU then
  1039. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  1040. newreference(p^.right^.location.reference),R_D1)))
  1041. else
  1042. emit_reg_reg(A_MOVE,S_L,p^.right^.location.fpureg,R_D1);
  1043. { probably a faster way to do this but... }
  1044. case op of
  1045. A_FADD: emitcall('FPC_SINGLE_ADD',true);
  1046. A_FMUL: emitcall('FPC_SINGLE_MUL',true);
  1047. A_FSUB: emitcall('FPC_SINGLE_SUB',true);
  1048. A_FDIV: emitcall('FPC_SINGLE_DIV',true);
  1049. A_FCMP: emitcall('FPC_SINGLE_CMP',true);
  1050. end;
  1051. if not cmpop then { only flags are affected with cmpop }
  1052. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,
  1053. p^.left^.location.fpureg)));
  1054. { if this was a reference, then delete as it }
  1055. { it no longer required. }
  1056. if p^.right^.location.loc <> LOC_FPU then
  1057. del_reference(p^.right^.location.reference);
  1058. end
  1059. else
  1060. begin
  1061. if p^.right^.location.loc <> LOC_FPU then
  1062. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,
  1063. getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1064. newreference(p^.right^.location.reference),
  1065. R_FP1)))
  1066. else
  1067. { FPm --> FPn must use extended precision }
  1068. emit_reg_reg(A_FMOVE,S_FX,p^.right^.location.fpureg,R_FP1);
  1069. { arithmetic expression performed in extended mode }
  1070. exprasmlist^.concat(new(pai68k,op_reg_reg(op,S_FX,
  1071. p^.left^.location.fpureg,R_FP1)));
  1072. { cmpop does not change any floating point register!! }
  1073. if not cmpop then
  1074. emit_reg_reg(A_FMOVE,S_FX,R_FP1,p^.left^.location.fpureg)
  1075. { exprasmlist^.concat(new(pai68k,op_reg_reg(A_FMOVE,
  1076. getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1077. R_FP1,p^.left^.location.fpureg)))}
  1078. else
  1079. { process comparison, to make it compatible with the rest of the code }
  1080. processcc(p);
  1081. { if this was a reference, then delete as it }
  1082. { it no longer required. }
  1083. if p^.right^.location.loc <> LOC_FPU then
  1084. del_reference(p^.right^.location.reference);
  1085. end;
  1086. end
  1087. else { everything is in the right order }
  1088. begin
  1089. { fpu_reg = fpu_reg / right }
  1090. { fpu_reg = fpu_reg - right }
  1091. { + commutative ops }
  1092. if cs_fp_emulation in aktmoduleswitches then
  1093. begin
  1094. { load value into D7 }
  1095. if p^.right^.location.loc <> LOC_FPU then
  1096. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  1097. newreference(p^.right^.location.reference),R_D0)))
  1098. else
  1099. emit_reg_reg(A_MOVE,S_L,p^.right^.location.fpureg,R_D0);
  1100. emit_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D1);
  1101. { probably a faster way to do this but... }
  1102. case op of
  1103. A_FADD: emitcall('FPC_SINGLE_ADD',true);
  1104. A_FMUL: emitcall('FPC_SINGLE_MUL',true);
  1105. A_FSUB: emitcall('FPC_SINGLE_SUB',true);
  1106. A_FDIV: emitcall('FPC_SINGLE_DIV',true);
  1107. A_FCMP: emitcall('FPC_SINGLE_CMP',true);
  1108. end;
  1109. if not cmpop then { only flags are affected with cmpop }
  1110. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,
  1111. p^.left^.location.fpureg)));
  1112. { if this was a reference, then delete as it }
  1113. { it no longer required. }
  1114. if p^.right^.location.loc <> LOC_FPU then
  1115. del_reference(p^.right^.location.reference);
  1116. end
  1117. else
  1118. begin
  1119. if p^.right^.location.loc <> LOC_FPU then
  1120. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,
  1121. getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1122. newreference(p^.right^.location.reference),R_FP1)))
  1123. else
  1124. emit_reg_reg(A_FMOVE,getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1125. p^.right^.location.fpureg,R_FP1);
  1126. emit_reg_reg(op,S_FX,R_FP1,p^.left^.location.fpureg);
  1127. if cmpop then
  1128. processcc(p);
  1129. { if this was a reference, then delete as it }
  1130. { it no longer required. }
  1131. if p^.right^.location.loc <> LOC_FPU then
  1132. del_reference(p^.right^.location.reference);
  1133. end
  1134. end; { endif treetype = .. }
  1135. if cmpop then
  1136. begin
  1137. if p^.swaped then
  1138. case p^.treetype of
  1139. equaln: flags := F_E;
  1140. unequaln: flags := F_NE;
  1141. ltn : flags := F_G;
  1142. lten : flags := F_GE;
  1143. gtn : flags := F_L;
  1144. gten: flags := F_LE;
  1145. end
  1146. else
  1147. case p^.treetype of
  1148. equaln: flags := F_E;
  1149. unequaln : flags := F_NE;
  1150. ltn: flags := F_L;
  1151. lten : flags := F_LE;
  1152. gtn : flags := F_G;
  1153. gten: flags := F_GE;
  1154. end;
  1155. clear_location(p^.location);
  1156. p^.location.loc := LOC_FLAGS;
  1157. p^.location.resflags := flags;
  1158. cmpop := false;
  1159. end
  1160. else
  1161. begin
  1162. clear_location(p^.location);
  1163. p^.location.loc := LOC_FPU;
  1164. if p^.left^.location.loc = LOC_FPU then
  1165. { copy fpu register result . }
  1166. { HERE ON EXIT FPU REGISTER IS IN EXTENDED MODE! }
  1167. p^.location.fpureg := p^.left^.location.fpureg
  1168. else
  1169. begin
  1170. InternalError(34);
  1171. end;
  1172. end;
  1173. end
  1174. else CGMessage(type_e_mismatch);
  1175. end;
  1176. SetResultLocation(cmpop,unsigned,p);
  1177. end;
  1178. end.
  1179. {
  1180. $Log$
  1181. Revision 1.11 1998-10-14 11:28:15 florian
  1182. * emitpushreferenceaddress gets now the asmlist as parameter
  1183. * m68k version compiles with -duseansistrings
  1184. Revision 1.10 1998/10/13 16:50:03 pierre
  1185. * undid some changes of Peter that made the compiler wrong
  1186. for m68k (I had to reinsert some ifdefs)
  1187. * removed several memory leaks under m68k
  1188. * removed the meory leaks for assembler readers
  1189. * cross compiling shoud work again better
  1190. ( crosscompiling sysamiga works
  1191. but as68k still complain about some code !)
  1192. Revision 1.9 1998/10/13 08:19:25 pierre
  1193. + source_os is now set correctly for cross-processor compilers
  1194. (tos contains all target_infos and
  1195. we use CPU86 and CPU68 conditionnals to
  1196. get the source operating system
  1197. this only works if you do not undefine
  1198. the source target !!)
  1199. * several cg68k memory leaks fixed
  1200. + started to change the code so that it should be possible to have
  1201. a complete compiler (both for m68k and i386 !!)
  1202. Revision 1.8 1998/10/09 11:47:47 pierre
  1203. * still more memory leaks fixes !!
  1204. Revision 1.7 1998/10/08 17:17:15 pierre
  1205. * current_module old scanner tagged as invalid if unit is recompiled
  1206. + added ppheap for better info on tracegetmem of heaptrc
  1207. (adds line column and file index)
  1208. * several memory leaks removed ith help of heaptrc !!
  1209. Revision 1.6 1998/09/28 16:57:16 pierre
  1210. * changed all length(p^.value_str^) into str_length(p)
  1211. to get it work with and without ansistrings
  1212. * changed sourcefiles field of tmodule to a pointer
  1213. Revision 1.5 1998/09/17 09:42:21 peter
  1214. + pass_2 for cg386
  1215. * Message() -> CGMessage() for pass_1/pass_2
  1216. Revision 1.4 1998/09/14 10:43:54 peter
  1217. * all internal RTL functions start with FPC_
  1218. Revision 1.3 1998/09/07 18:45:55 peter
  1219. * update smartlinking, uses getdatalabel
  1220. * renamed ptree.value vars to value_str,value_real,value_set
  1221. Revision 1.2 1998/09/04 08:41:42 peter
  1222. * updated some error CGMessages
  1223. Revision 1.1 1998/09/01 09:07:09 peter
  1224. * m68k fixes, splitted cg68k like cgi386
  1225. }