cg68kadd.pas 63 KB

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