cg68kadd.pas 64 KB

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