cg68kadd.pas 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  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(p^.right^.location.reference);
  260. emitpushreferenceaddr(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(p^.right^.location.reference);
  358. emitpushreferenceaddr(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(href);
  381. emitcall('FPC_SET_SET_RANGE',true);
  382. end
  383. else
  384. begin
  385. loadsetelement(p^.right^.left);
  386. emitpushreferenceaddr(href);
  387. emitcall('FPC_SET_SET_BYTE',true);
  388. end;
  389. end
  390. else
  391. begin
  392. { must be an other set }
  393. emitpushreferenceaddr(href);
  394. emitpushreferenceaddr(p^.right^.location.reference);
  395. emitpushreferenceaddr(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(href);
  415. emitpushreferenceaddr(p^.right^.location.reference);
  416. emitpushreferenceaddr(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. emit_reg_reg(A_MOVE,opsize,p^.left^.location.register,
  710. hregister);
  711. end
  712. end
  713. else
  714. begin
  715. del_reference(p^.left^.location.reference);
  716. if is_in_dest then
  717. begin
  718. hregister:=p^.location.register;
  719. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  720. newreference(p^.left^.location.reference),hregister)));
  721. end
  722. else
  723. begin
  724. { first give free, then demand new register }
  725. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  726. newreference(p^.left^.location.reference),hregister)));
  727. end;
  728. end;
  729. clear_location(p^.location);
  730. p^.location.loc:=LOC_REGISTER;
  731. p^.location.register:=hregister;
  732. end
  733. else
  734. { if on the right the register then swap }
  735. if not(noswap) and (p^.right^.location.loc=LOC_REGISTER) then
  736. begin
  737. swap_location(p^.location,p^.right^.location);
  738. { newly swapped also set swapped flag }
  739. p^.swaped:=not(p^.swaped);
  740. end;
  741. { at this point, p^.location.loc should be LOC_REGISTER }
  742. { and p^.location.register should be a valid register }
  743. { containing the left result }
  744. if p^.right^.location.loc<>LOC_REGISTER then
  745. begin
  746. if (p^.treetype=subn) and p^.swaped then
  747. begin
  748. if p^.right^.location.loc=LOC_CREGISTER then
  749. begin
  750. if extra_not then
  751. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,opsize,p^.location.register)));
  752. emit_reg_reg(A_MOVE,opsize,p^.right^.location.register,R_D6);
  753. emit_reg_reg(op,opsize,p^.location.register,R_D6);
  754. emit_reg_reg(A_MOVE,opsize,R_D6,p^.location.register);
  755. end
  756. else
  757. begin
  758. if extra_not then
  759. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,opsize,p^.location.register)));
  760. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,
  761. newreference(p^.right^.location.reference),R_D6)));
  762. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,p^.location.register,R_D6)));
  763. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,opsize,R_D6,p^.location.register)));
  764. del_reference(p^.right^.location.reference);
  765. end;
  766. end
  767. else
  768. begin
  769. if (p^.right^.treetype=ordconstn) and (op=A_CMP) and
  770. (p^.right^.value=0) then
  771. exprasmlist^.concat(new(pai68k,op_reg(A_TST,opsize,p^.location.register)))
  772. else
  773. if (p^.right^.treetype=ordconstn) and (op=A_MULS) and
  774. (ispowerof2(p^.right^.value,power)) then
  775. begin
  776. if (power <= 8) then
  777. exprasmlist^.concat(new(pai68k,op_const_reg(A_ASL,opsize,power,
  778. p^.location.register)))
  779. else
  780. begin
  781. exprasmlist^.concat(new(pai68k,op_const_reg(A_MOVE,S_L,power,
  782. R_D6)));
  783. exprasmlist^.concat(new(pai68k,op_reg_reg(A_ASL,opsize,R_D6,
  784. p^.location.register)))
  785. end;
  786. end
  787. else
  788. begin
  789. if (p^.right^.location.loc=LOC_CREGISTER) then
  790. begin
  791. if extra_not then
  792. begin
  793. emit_reg_reg(A_MOVE,S_L,p^.right^.location.register,R_D6);
  794. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,R_D6)));
  795. emit_reg_reg(A_AND,S_L,R_D6,
  796. p^.location.register);
  797. end
  798. else
  799. begin
  800. if (op=A_MULS) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  801. { Emulation for MC68000 }
  802. begin
  803. emit_reg_reg(A_MOVE,opsize,p^.right^.location.register,
  804. R_D0);
  805. emit_reg_reg(A_MOVE,opsize,p^.location.register,R_D1);
  806. emitcall('FPC_LONGMUL',true);
  807. emit_reg_reg(A_MOVE,opsize,R_D0,p^.location.register);
  808. end
  809. else
  810. if (op=A_MULU) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  811. CGMessage(cg_f_32bit_not_supported_in_68000)
  812. else
  813. emit_reg_reg(op,opsize,p^.right^.location.register,
  814. p^.location.register);
  815. end;
  816. end
  817. else
  818. begin
  819. if extra_not then
  820. begin
  821. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,newreference(
  822. p^.right^.location.reference),R_D6)));
  823. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,R_D6)));
  824. emit_reg_reg(A_AND,S_L,R_D6,
  825. p^.location.register);
  826. end
  827. else
  828. begin
  829. if (op=A_MULS) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  830. { Emulation for MC68000 }
  831. begin
  832. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE, opsize,
  833. newreference(p^.right^.location.reference),R_D1)));
  834. emit_reg_reg(A_MOVE,opsize,p^.location.register,R_D0);
  835. emitcall('FPC_LONGMUL',true);
  836. emit_reg_reg(A_MOVE,opsize,R_D0,p^.location.register);
  837. end
  838. else
  839. if (op=A_MULU) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  840. CGMessage(cg_f_32bit_not_supported_in_68000)
  841. else
  842. { When one of the source/destination is a memory reference }
  843. { and the operator is EOR, the we must load it into the }
  844. { value into a register first since only EOR reg,reg exists }
  845. { on the m68k }
  846. if (op=A_EOR) then
  847. begin
  848. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,opsize,newreference(
  849. p^.right^.location.reference),R_D0)));
  850. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,R_D0,
  851. p^.location.register)));
  852. end
  853. else
  854. exprasmlist^.concat(new(pai68k,op_ref_reg(op,opsize,newreference(
  855. p^.right^.location.reference),p^.location.register)));
  856. end;
  857. del_reference(p^.right^.location.reference);
  858. end;
  859. end;
  860. end;
  861. end
  862. else
  863. begin
  864. { when swapped another result register }
  865. if (p^.treetype=subn) and p^.swaped then
  866. begin
  867. if extra_not then
  868. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.location.register)));
  869. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,
  870. p^.location.register,p^.right^.location.register)));
  871. swap_location(p^.location,p^.right^.location);
  872. { newly swapped also set swapped flag }
  873. { just to maintain ordering }
  874. p^.swaped:=not(p^.swaped);
  875. end
  876. else
  877. begin
  878. if extra_not then
  879. exprasmlist^.concat(new(pai68k,op_reg(A_NOT,S_L,p^.right^.location.register)));
  880. if (op=A_MULS) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  881. { Emulation for MC68000 }
  882. begin
  883. emit_reg_reg(A_MOVE,opsize,p^.right^.location.register,
  884. R_D0);
  885. emit_reg_reg(A_MOVE,opsize,p^.location.register,R_D1);
  886. emitcall('FPC_LONGMUL',true);
  887. emit_reg_reg(A_MOVE,opsize,R_D0,p^.location.register);
  888. end
  889. else
  890. if (op=A_MULU) and (opsize = S_L) and (aktoptprocessor=MC68000) then
  891. CGMessage(cg_f_32bit_not_supported_in_68000)
  892. else
  893. exprasmlist^.concat(new(pai68k,op_reg_reg(op,opsize,
  894. p^.right^.location.register,
  895. p^.location.register)));
  896. end;
  897. ungetregister32(p^.right^.location.register);
  898. end;
  899. if cmpop then
  900. ungetregister32(p^.location.register);
  901. { only in case of overflow operations }
  902. { produce overflow code }
  903. if mboverflow then
  904. emitoverflowcheck(p);
  905. { only in case of overflow operations }
  906. { produce overflow code }
  907. { we must put it here directly, because sign of operation }
  908. { is in unsigned VAR!! }
  909. end
  910. else
  911. { Char type }
  912. if ((p^.left^.resulttype^.deftype=orddef) and
  913. (porddef(p^.left^.resulttype)^.typ=uchar)) then
  914. begin
  915. case p^.treetype of
  916. ltn,lten,gtn,gten,
  917. equaln,unequaln :
  918. cmpop:=true;
  919. else CGMessage(type_e_mismatch);
  920. end;
  921. unsigned:=true;
  922. { left and right no register? }
  923. { the one must be demanded }
  924. if (p^.location.loc<>LOC_REGISTER) and
  925. (p^.right^.location.loc<>LOC_REGISTER) then
  926. begin
  927. if p^.location.loc=LOC_CREGISTER then
  928. begin
  929. if cmpop then
  930. { do not disturb register }
  931. hregister:=p^.location.register
  932. else
  933. begin
  934. hregister:=getregister32;
  935. emit_reg_reg(A_MOVE,S_B,p^.location.register,
  936. hregister);
  937. end;
  938. end
  939. else
  940. begin
  941. del_reference(p^.location.reference);
  942. { first give free then demand new register }
  943. hregister:=getregister32;
  944. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_B,newreference(p^.location.reference),
  945. hregister)));
  946. end;
  947. clear_location(p^.location);
  948. p^.location.loc:=LOC_REGISTER;
  949. p^.location.register:=hregister;
  950. end;
  951. { now p always a register }
  952. if (p^.right^.location.loc=LOC_REGISTER) and
  953. (p^.location.loc<>LOC_REGISTER) then
  954. begin
  955. swap_location(p^.location,p^.right^.location);
  956. { newly swapped also set swapped flag }
  957. p^.swaped:=not(p^.swaped);
  958. end;
  959. if p^.right^.location.loc<>LOC_REGISTER then
  960. begin
  961. if p^.right^.location.loc=LOC_CREGISTER then
  962. begin
  963. emit_reg_reg(A_CMP,S_B,
  964. p^.right^.location.register,p^.location.register);
  965. end
  966. else
  967. begin
  968. exprasmlist^.concat(new(pai68k,op_ref_reg(A_CMP,S_B,newreference(
  969. p^.right^.location.reference),p^.location.register)));
  970. del_reference(p^.right^.location.reference);
  971. end;
  972. end
  973. else
  974. begin
  975. emit_reg_reg(A_CMP,S_B,p^.right^.location.register,
  976. p^.location.register);
  977. ungetregister32(p^.right^.location.register);
  978. end;
  979. ungetregister32(p^.location.register);
  980. end
  981. else
  982. { Floating point }
  983. if (p^.left^.resulttype^.deftype=floatdef) and
  984. (pfloatdef(p^.left^.resulttype)^.typ<>f32bit) then
  985. begin
  986. { real constants to the left }
  987. if p^.left^.treetype=realconstn then
  988. swaptree(p);
  989. cmpop:=false;
  990. case p^.treetype of
  991. addn : op:=A_FADD;
  992. muln : op:=A_FMUL;
  993. subn : op:=A_FSUB;
  994. slashn : op:=A_FDIV;
  995. ltn,lten,gtn,gten,
  996. equaln,unequaln : begin
  997. op:=A_FCMP;
  998. cmpop:=true;
  999. end;
  1000. else CGMessage(type_e_mismatch);
  1001. end;
  1002. if (p^.left^.location.loc <> LOC_FPU) and
  1003. (p^.right^.location.loc <> LOC_FPU) then
  1004. begin
  1005. { we suppose left in reference }
  1006. del_reference(p^.left^.location.reference);
  1007. { get a copy, since we don't want to modify the same }
  1008. { node at the same time. }
  1009. tmpref:=p^.left^.location.reference;
  1010. if assigned(p^.left^.location.reference.symbol) then
  1011. tmpref.symbol:=stringdup(p^.left^.location.reference.symbol^);
  1012. floatload(pfloatdef(p^.left^.resulttype)^.typ, tmpref,
  1013. p^.left^.location);
  1014. clear_reference(tmpref);
  1015. end
  1016. else
  1017. begin
  1018. if (p^.right^.location.loc = LOC_FPU)
  1019. and(p^.left^.location.loc <> LOC_FPU) then
  1020. begin
  1021. swap_location(p^.left^.location, p^.right^.location);
  1022. p^.swaped := not(p^.swaped);
  1023. end
  1024. end;
  1025. { ---------------- LEFT = LOC_FPUREG -------------------- }
  1026. if ((p^.treetype =subn) or (p^.treetype = slashn)) and (p^.swaped) then
  1027. { fpu_reg = right(FP1) / fpu_reg }
  1028. { fpu_reg = right(FP1) - fpu_reg }
  1029. begin
  1030. if (cs_fp_emulation in aktmoduleswitches) then
  1031. begin
  1032. { fpu_reg = right / D1 }
  1033. { fpu_reg = right - D1 }
  1034. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D0)));
  1035. { load value into D1 }
  1036. if p^.right^.location.loc <> LOC_FPU then
  1037. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  1038. newreference(p^.right^.location.reference),R_D1)))
  1039. else
  1040. emit_reg_reg(A_MOVE,S_L,p^.right^.location.fpureg,R_D1);
  1041. { probably a faster way to do this but... }
  1042. case op of
  1043. A_FADD: emitcall('FPC_SINGLE_ADD',true);
  1044. A_FMUL: emitcall('FPC_SINGLE_MUL',true);
  1045. A_FSUB: emitcall('FPC_SINGLE_SUB',true);
  1046. A_FDIV: emitcall('FPC_SINGLE_DIV',true);
  1047. A_FCMP: emitcall('FPC_SINGLE_CMP',true);
  1048. end;
  1049. if not cmpop then { only flags are affected with cmpop }
  1050. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,
  1051. p^.left^.location.fpureg)));
  1052. { if this was a reference, then delete as it }
  1053. { it no longer required. }
  1054. if p^.right^.location.loc <> LOC_FPU then
  1055. del_reference(p^.right^.location.reference);
  1056. end
  1057. else
  1058. begin
  1059. if p^.right^.location.loc <> LOC_FPU then
  1060. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,
  1061. getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1062. newreference(p^.right^.location.reference),
  1063. R_FP1)))
  1064. else
  1065. { FPm --> FPn must use extended precision }
  1066. emit_reg_reg(A_FMOVE,S_FX,p^.right^.location.fpureg,R_FP1);
  1067. { arithmetic expression performed in extended mode }
  1068. exprasmlist^.concat(new(pai68k,op_reg_reg(op,S_FX,
  1069. p^.left^.location.fpureg,R_FP1)));
  1070. { cmpop does not change any floating point register!! }
  1071. if not cmpop then
  1072. emit_reg_reg(A_FMOVE,S_FX,R_FP1,p^.left^.location.fpureg)
  1073. { exprasmlist^.concat(new(pai68k,op_reg_reg(A_FMOVE,
  1074. getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1075. R_FP1,p^.left^.location.fpureg)))}
  1076. else
  1077. { process comparison, to make it compatible with the rest of the code }
  1078. processcc(p);
  1079. { if this was a reference, then delete as it }
  1080. { it no longer required. }
  1081. if p^.right^.location.loc <> LOC_FPU then
  1082. del_reference(p^.right^.location.reference);
  1083. end;
  1084. end
  1085. else { everything is in the right order }
  1086. begin
  1087. { fpu_reg = fpu_reg / right }
  1088. { fpu_reg = fpu_reg - right }
  1089. { + commutative ops }
  1090. if cs_fp_emulation in aktmoduleswitches then
  1091. begin
  1092. { load value into D7 }
  1093. if p^.right^.location.loc <> LOC_FPU then
  1094. exprasmlist^.concat(new(pai68k,op_ref_reg(A_MOVE,S_L,
  1095. newreference(p^.right^.location.reference),R_D0)))
  1096. else
  1097. emit_reg_reg(A_MOVE,S_L,p^.right^.location.fpureg,R_D0);
  1098. emit_reg_reg(A_MOVE,S_L,p^.left^.location.fpureg,R_D1);
  1099. { probably a faster way to do this but... }
  1100. case op of
  1101. A_FADD: emitcall('FPC_SINGLE_ADD',true);
  1102. A_FMUL: emitcall('FPC_SINGLE_MUL',true);
  1103. A_FSUB: emitcall('FPC_SINGLE_SUB',true);
  1104. A_FDIV: emitcall('FPC_SINGLE_DIV',true);
  1105. A_FCMP: emitcall('FPC_SINGLE_CMP',true);
  1106. end;
  1107. if not cmpop then { only flags are affected with cmpop }
  1108. exprasmlist^.concat(new(pai68k,op_reg_reg(A_MOVE,S_L,R_D0,
  1109. p^.left^.location.fpureg)));
  1110. { if this was a reference, then delete as it }
  1111. { it no longer required. }
  1112. if p^.right^.location.loc <> LOC_FPU then
  1113. del_reference(p^.right^.location.reference);
  1114. end
  1115. else
  1116. begin
  1117. if p^.right^.location.loc <> LOC_FPU then
  1118. exprasmlist^.concat(new(pai68k,op_ref_reg(A_FMOVE,
  1119. getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1120. newreference(p^.right^.location.reference),R_FP1)))
  1121. else
  1122. emit_reg_reg(A_FMOVE,getfloatsize(pfloatdef(p^.left^.resulttype)^.typ),
  1123. p^.right^.location.fpureg,R_FP1);
  1124. emit_reg_reg(op,S_FX,R_FP1,p^.left^.location.fpureg);
  1125. if cmpop then
  1126. processcc(p);
  1127. { if this was a reference, then delete as it }
  1128. { it no longer required. }
  1129. if p^.right^.location.loc <> LOC_FPU then
  1130. del_reference(p^.right^.location.reference);
  1131. end
  1132. end; { endif treetype = .. }
  1133. if cmpop then
  1134. begin
  1135. if p^.swaped then
  1136. case p^.treetype of
  1137. equaln: flags := F_E;
  1138. unequaln: flags := F_NE;
  1139. ltn : flags := F_G;
  1140. lten : flags := F_GE;
  1141. gtn : flags := F_L;
  1142. gten: flags := F_LE;
  1143. end
  1144. else
  1145. case p^.treetype of
  1146. equaln: flags := F_E;
  1147. unequaln : flags := F_NE;
  1148. ltn: flags := F_L;
  1149. lten : flags := F_LE;
  1150. gtn : flags := F_G;
  1151. gten: flags := F_GE;
  1152. end;
  1153. p^.location.loc := LOC_FLAGS;
  1154. p^.location.resflags := flags;
  1155. cmpop := false;
  1156. end
  1157. else
  1158. begin
  1159. p^.location.loc := LOC_FPU;
  1160. if p^.left^.location.loc = LOC_FPU then
  1161. { copy fpu register result . }
  1162. { HERE ON EXIT FPU REGISTER IS IN EXTENDED MODE! }
  1163. p^.location.fpureg := p^.left^.location.fpureg
  1164. else
  1165. begin
  1166. InternalError(34);
  1167. end;
  1168. end;
  1169. end
  1170. else CGMessage(type_e_mismatch);
  1171. end;
  1172. SetResultLocation(cmpop,unsigned,p);
  1173. end;
  1174. end.
  1175. {
  1176. $Log$
  1177. Revision 1.8 1998-10-09 11:47:47 pierre
  1178. * still more memory leaks fixes !!
  1179. Revision 1.7 1998/10/08 17:17:15 pierre
  1180. * current_module old scanner tagged as invalid if unit is recompiled
  1181. + added ppheap for better info on tracegetmem of heaptrc
  1182. (adds line column and file index)
  1183. * several memory leaks removed ith help of heaptrc !!
  1184. Revision 1.6 1998/09/28 16:57:16 pierre
  1185. * changed all length(p^.value_str^) into str_length(p)
  1186. to get it work with and without ansistrings
  1187. * changed sourcefiles field of tmodule to a pointer
  1188. Revision 1.5 1998/09/17 09:42:21 peter
  1189. + pass_2 for cg386
  1190. * Message() -> CGMessage() for pass_1/pass_2
  1191. Revision 1.4 1998/09/14 10:43:54 peter
  1192. * all internal RTL functions start with FPC_
  1193. Revision 1.3 1998/09/07 18:45:55 peter
  1194. * update smartlinking, uses getdatalabel
  1195. * renamed ptree.value vars to value_str,value_real,value_set
  1196. Revision 1.2 1998/09/04 08:41:42 peter
  1197. * updated some error CGMessages
  1198. Revision 1.1 1998/09/01 09:07:09 peter
  1199. * m68k fixes, splitted cg68k like cgi386
  1200. }