ncgadd.pas 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by the FPC development team
  4. Code generation for add nodes (generic version)
  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 ncgadd;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nadd,cpubase,cginfo;
  23. type
  24. tcgaddnode = class(taddnode)
  25. { function pass_1: tnode; override;}
  26. procedure pass_2;override;
  27. private
  28. procedure pass_left_and_right;
  29. { load left and right nodes into registers }
  30. procedure load_left_right(cmpop, load_constants: boolean);
  31. { free used registers, except result location }
  32. procedure clear_left_right(cmpop: boolean);
  33. procedure second_opfloat;
  34. procedure second_opboolean;
  35. procedure second_opsmallset;
  36. procedure second_op64bit;
  37. { procedure second_addfloat;virtual;}
  38. procedure second_addboolean;virtual;
  39. procedure second_addsmallset;virtual;
  40. procedure second_add64bit;virtual;
  41. procedure second_addordinal;virtual;
  42. { procedure second_cmpfloat;virtual;}
  43. procedure second_cmpboolean;virtual;
  44. procedure second_cmpsmallset;virtual;
  45. procedure second_cmp64bit;virtual;
  46. procedure second_cmpordinal;virtual;
  47. end;
  48. implementation
  49. uses
  50. globtype,systems,
  51. cutils,verbose,globals,
  52. symconst,symdef,paramgr,
  53. aasmbase,aasmtai,aasmcpu,defutil,htypechk,
  54. cgbase,cpuinfo,pass_1,pass_2,regvars,
  55. cpupara,
  56. ncon,nset,ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
  57. {*****************************************************************************
  58. Helpers
  59. *****************************************************************************}
  60. (*
  61. function tcgaddnode.getresflags(unsigned : boolean) : tresflags;
  62. begin
  63. case nodetype of
  64. equaln : getresflags:=F_E;
  65. unequaln : getresflags:=F_NE;
  66. else
  67. if not(unsigned) then
  68. begin
  69. if nf_swaped in flags then
  70. case nodetype of
  71. ltn : getresflags:=F_G;
  72. lten : getresflags:=F_GE;
  73. gtn : getresflags:=F_L;
  74. gten : getresflags:=F_LE;
  75. end
  76. else
  77. case nodetype of
  78. ltn : getresflags:=F_L;
  79. lten : getresflags:=F_LE;
  80. gtn : getresflags:=F_G;
  81. gten : getresflags:=F_GE;
  82. end;
  83. end
  84. else
  85. begin
  86. if nf_swaped in flags then
  87. case nodetype of
  88. ltn : getresflags:=F_A;
  89. lten : getresflags:=F_AE;
  90. gtn : getresflags:=F_B;
  91. gten : getresflags:=F_BE;
  92. end
  93. else
  94. case nodetype of
  95. ltn : getresflags:=F_B;
  96. lten : getresflags:=F_BE;
  97. gtn : getresflags:=F_A;
  98. gten : getresflags:=F_AE;
  99. end;
  100. end;
  101. end;
  102. end;
  103. *)
  104. procedure tcgaddnode.pass_left_and_right;
  105. var
  106. pushedregs : tmaybesave;
  107. tmpreg : tregister;
  108. pushedfpu : boolean;
  109. begin
  110. { calculate the operator which is more difficult }
  111. firstcomplex(self);
  112. { in case of constant put it to the left }
  113. if (left.nodetype=ordconstn) then
  114. swapleftright;
  115. secondpass(left);
  116. { are too few registers free? }
  117. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  118. if location.loc=LOC_FPUREGISTER then
  119. pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
  120. else
  121. pushedfpu:=false;
  122. secondpass(right);
  123. maybe_restore(exprasmlist,left.location,pushedregs);
  124. if pushedfpu then
  125. begin
  126. tmpreg := rg.getregisterfpu(exprasmlist);
  127. cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
  128. location_reset(left.location,LOC_FPUREGISTER,left.location.size);
  129. left.location.register := tmpreg;
  130. end;
  131. end;
  132. procedure tcgaddnode.load_left_right(cmpop, load_constants: boolean);
  133. procedure load_node(var n: tnode);
  134. begin
  135. case n.location.loc of
  136. LOC_REGISTER:
  137. if not cmpop then
  138. begin
  139. location.register := n.location.register;
  140. if is_64bitint(n.resulttype.def) then
  141. location.registerhigh := n.location.registerhigh;
  142. end;
  143. LOC_REFERENCE,LOC_CREFERENCE:
  144. begin
  145. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  146. if not cmpop then
  147. begin
  148. location.register := n.location.register;
  149. if is_64bitint(n.resulttype.def) then
  150. location.registerhigh := n.location.registerhigh;
  151. end;
  152. end;
  153. LOC_CONSTANT:
  154. begin
  155. if load_constants then
  156. begin
  157. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  158. if not cmpop then
  159. location.register := n.location.register;
  160. if is_64bitint(n.resulttype.def) then
  161. location.registerhigh := n.location.registerhigh;
  162. end;
  163. end;
  164. end;
  165. end;
  166. begin
  167. load_node(left);
  168. load_node(right);
  169. end;
  170. procedure tcgaddnode.clear_left_right(cmpop: boolean);
  171. begin
  172. if (right.location.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  173. (cmpop or
  174. (location.register <> right.location.register)) then
  175. begin
  176. rg.ungetregister(exprasmlist,right.location.register);
  177. if is_64bitint(right.resulttype.def) then
  178. rg.ungetregister(exprasmlist,right.location.registerhigh);
  179. end;
  180. if (left.location.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  181. (cmpop or
  182. (location.register <> left.location.register)) then
  183. begin
  184. rg.ungetregister(exprasmlist,left.location.register);
  185. if is_64bitint(left.resulttype.def) then
  186. rg.ungetregister(exprasmlist,left.location.registerhigh);
  187. end;
  188. end;
  189. {*****************************************************************************
  190. Smallsets
  191. *****************************************************************************}
  192. procedure tcgaddnode.second_opsmallset;
  193. var
  194. cmpop : boolean;
  195. begin
  196. cmpop := false;
  197. pass_left_and_right;
  198. { when a setdef is passed, it has to be a smallset }
  199. if ((left.resulttype.def.deftype=setdef) and
  200. (tsetdef(left.resulttype.def).settype<>smallset)) or
  201. ((right.resulttype.def.deftype=setdef) and
  202. (tsetdef(right.resulttype.def).settype<>smallset)) then
  203. internalerror(200203301);
  204. if nodetype in [equaln,unequaln,gtn,gten,lten,ltn] then
  205. cmpop := true;
  206. { load non-constant values (left and right) into registers }
  207. load_left_right(cmpop,false);
  208. if cmpop then
  209. second_cmpsmallset
  210. else
  211. second_addsmallset;
  212. clear_left_right(cmpop);
  213. end;
  214. procedure tcgaddnode.second_cmpsmallset;
  215. begin
  216. location_reset(location,LOC_FLAGS,OS_NO);
  217. case nodetype of
  218. equaln,
  219. unequaln :
  220. begin
  221. {emit_compare(true);}
  222. end;
  223. lten,gten:
  224. begin
  225. (*
  226. If (not(nf_swaped in flags) and
  227. (nodetype = lten)) or
  228. ((nf_swaped in flags) and
  229. (nodetype = gten)) then
  230. swapleftright;
  231. // now we have to check whether left >= right
  232. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  233. if left.location.loc = LOC_CONSTANT then
  234. begin
  235. cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
  236. not(left.location.value),right.location.register,tmpreg);
  237. exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
  238. // the two instructions above should be folded together by
  239. // the peepholeoptimizer
  240. end
  241. else
  242. begin
  243. if right.location.loc = LOC_CONSTANT then
  244. begin
  245. cg.a_load_const_reg(exprasmlist,OS_INT,
  246. aword(right.location.value),tmpreg);
  247. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  248. tmpreg,left.location.register));
  249. end
  250. else
  251. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  252. right.location.register,left.location.register));
  253. end;
  254. cg.free_scratch_reg(exprasmlist,tmpreg);
  255. location.resflags.cr := R_CR0;
  256. location.resflags.flag := F_EQ;
  257. opdone := true;*)
  258. end;
  259. else
  260. internalerror(2002072701);
  261. end;
  262. end;
  263. procedure tcgaddnode.second_addsmallset;
  264. var
  265. cgop : TOpCg;
  266. tmpreg : tregister;
  267. opdone,
  268. cmpop : boolean;
  269. begin
  270. opdone := false;
  271. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  272. if (location.register = R_NO) then
  273. location.register := rg.getregisterint(exprasmlist);
  274. case nodetype of
  275. addn :
  276. begin
  277. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  278. swapleftright;
  279. { are we adding set elements ? }
  280. if right.nodetype=setelementn then
  281. begin
  282. { no range support for smallsets! }
  283. if assigned(tsetelementnode(right).right) then
  284. internalerror(43244);
  285. if (right.location.loc = LOC_CONSTANT) then
  286. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  287. aword(1 shl aword(right.location.value)),
  288. left.location.register,location.register)
  289. else
  290. begin
  291. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  292. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  293. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  294. right.location.register,tmpreg);
  295. if left.location.loc <> LOC_CONSTANT then
  296. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  297. left.location.register,location.register)
  298. else
  299. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  300. aword(left.location.value),tmpreg,location.register);
  301. cg.free_scratch_reg(exprasmlist,tmpreg);
  302. end;
  303. opdone := true;
  304. end
  305. else
  306. cgop := OP_OR;
  307. end;
  308. symdifn :
  309. cgop:=OP_XOR;
  310. muln :
  311. cgop:=OP_AND;
  312. subn :
  313. begin
  314. cgop:=OP_AND;
  315. if (not(nf_swaped in flags)) then
  316. if (right.location.loc=LOC_CONSTANT) then
  317. right.location.value := not(right.location.value)
  318. else
  319. opdone := true
  320. else if (left.location.loc=LOC_CONSTANT) then
  321. left.location.value := not(left.location.value)
  322. else
  323. begin
  324. swapleftright;
  325. opdone := true;
  326. end;
  327. if opdone then
  328. begin
  329. if left.location.loc = LOC_CONSTANT then
  330. begin
  331. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  332. cg.a_load_const_reg(exprasmlist,OS_INT,
  333. aword(left.location.value),tmpreg);
  334. cg.a_op_reg_reg(exprasmlist,OP_NOT,OS_INT,right.location.register,right.location.register);
  335. cg.a_op_reg_reg(exprasmlist,OP_AND,OS_INT,right.location.register,tmpreg);
  336. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,tmpreg,location.register);
  337. cg.free_scratch_reg(exprasmlist,tmpreg);
  338. end
  339. else
  340. begin
  341. cg.a_op_reg_reg(exprasmlist,OP_NOT,OS_INT,right.location.register,right.location.register);
  342. cg.a_op_reg_reg(exprasmlist,OP_AND,OS_INT,right.location.register,left.location.register);
  343. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,left.location.register,location.register);
  344. end;
  345. end;
  346. end;
  347. else
  348. internalerror(2002072701);
  349. end;
  350. if not opdone then
  351. begin
  352. // these are all commutative operations
  353. if (left.location.loc = LOC_CONSTANT) then
  354. swapleftright;
  355. if (right.location.loc = LOC_CONSTANT) then
  356. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  357. aword(right.location.value),left.location.register,
  358. location.register)
  359. else
  360. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  361. right.location.register,left.location.register,
  362. location.register);
  363. end;
  364. end;
  365. {*****************************************************************************
  366. Boolean
  367. *****************************************************************************}
  368. procedure tcgaddnode.second_opboolean;
  369. var
  370. cmpop : boolean;
  371. begin
  372. cmpop := false;
  373. { calculate the operator which is more difficult }
  374. firstcomplex(self);
  375. if cmpop then
  376. second_cmpboolean
  377. else
  378. second_addboolean;
  379. end;
  380. procedure tcgaddnode.second_cmpboolean;
  381. begin
  382. end;
  383. procedure tcgaddnode.second_addboolean;
  384. var
  385. cgop : TOpCg;
  386. cgsize : TCgSize;
  387. cmpop,
  388. isjump : boolean;
  389. otl,ofl : tasmlabel;
  390. pushedregs : tmaybesave;
  391. begin
  392. cmpop:=false;
  393. if (torddef(left.resulttype.def).typ=bool8bit) or
  394. (torddef(right.resulttype.def).typ=bool8bit) then
  395. cgsize:=OS_8
  396. else
  397. if (torddef(left.resulttype.def).typ=bool16bit) or
  398. (torddef(right.resulttype.def).typ=bool16bit) then
  399. cgsize:=OS_16
  400. else
  401. cgsize:=OS_32;
  402. (*
  403. if (cs_full_boolean_eval in aktlocalswitches) or
  404. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  405. begin
  406. if left.nodetype in [ordconstn,realconstn] then
  407. swapleftright;
  408. isjump:=(left.location.loc=LOC_JUMP);
  409. if isjump then
  410. begin
  411. otl:=truelabel;
  412. objectlibrary.getlabel(truelabel);
  413. ofl:=falselabel;
  414. objectlibrary.getlabel(falselabel);
  415. end;
  416. secondpass(left);
  417. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  418. location_force_reg(exprasmlist,left.location,cgsize,false);
  419. if isjump then
  420. begin
  421. truelabel:=otl;
  422. falselabel:=ofl;
  423. end;
  424. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  425. isjump:=(right.location.loc=LOC_JUMP);
  426. if isjump then
  427. begin
  428. otl:=truelabel;
  429. objectlibrary.getlabel(truelabel);
  430. ofl:=falselabel;
  431. objectlibrary.getlabel(falselabel);
  432. end;
  433. secondpass(right);
  434. maybe_restore(exprasmlist,left.location,pushedregs);
  435. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  436. location_force_reg(exprasmlist,right.location,cgsize,false);
  437. if isjump then
  438. begin
  439. truelabel:=otl;
  440. falselabel:=ofl;
  441. end;
  442. cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  443. { set result location }
  444. if not cmpop then
  445. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  446. else
  447. location_reset(location,LOC_FLAGS,OS_NO);
  448. load_left_right(cmpop,false);
  449. if (left.location.loc = LOC_CONSTANT) then
  450. swapleftright;
  451. { compare the }
  452. case nodetype of
  453. ltn,lten,gtn,gten,
  454. equaln,unequaln :
  455. begin
  456. if (right.location.loc <> LOC_CONSTANT) then
  457. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
  458. left.location.register,right.location.register))
  459. else
  460. exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
  461. left.location.register,longint(right.location.value)));
  462. location.resflags := getresflags;
  463. end;
  464. else
  465. begin
  466. case nodetype of
  467. xorn :
  468. cgop:=OP_XOR;
  469. orn :
  470. cgop:=OP_OR;
  471. andn :
  472. cgop:=OP_AND;
  473. else
  474. internalerror(200203247);
  475. end;
  476. if right.location.loc <> LOC_CONSTANT then
  477. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  478. left.location.register,right.location.register,
  479. location.register)
  480. else
  481. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  482. aword(right.location.value),left.location.register,
  483. location.register);
  484. end;
  485. end;
  486. end
  487. else
  488. begin
  489. // just to make sure we free the right registers
  490. cmpop := true;
  491. case nodetype of
  492. andn,
  493. orn :
  494. begin
  495. location_reset(location,LOC_JUMP,OS_NO);
  496. case nodetype of
  497. andn :
  498. begin
  499. otl:=truelabel;
  500. objectlibrary.getlabel(truelabel);
  501. secondpass(left);
  502. maketojumpbool(exprasmlist,left,lr_load_regvars);
  503. cg.a_label(exprasmlist,truelabel);
  504. truelabel:=otl;
  505. end;
  506. orn :
  507. begin
  508. ofl:=falselabel;
  509. objectlibrary.getlabel(falselabel);
  510. secondpass(left);
  511. maketojumpbool(exprasmlist,left,lr_load_regvars);
  512. cg.a_label(exprasmlist,falselabel);
  513. falselabel:=ofl;
  514. end;
  515. else
  516. CGMessage(type_e_mismatch);
  517. end;
  518. secondpass(right);
  519. maketojumpbool(exprasmlist,right,lr_load_regvars);
  520. end;
  521. end;
  522. end;*)
  523. { free used register (except the result register) }
  524. clear_left_right(cmpop);
  525. end;
  526. {*****************************************************************************
  527. 64-bit
  528. *****************************************************************************}
  529. procedure tcgaddnode.second_op64bit;
  530. var
  531. cmpop : boolean;
  532. begin
  533. cmpop := false;
  534. firstcomplex(self);
  535. pass_left_and_right;
  536. if nodetype in [equaln,unequaln,gtn,gten,ltn,lten] then
  537. cmpop := true;
  538. if cmpop then
  539. second_cmp64bit
  540. else
  541. second_add64bit;
  542. { free used register (except the result register) }
  543. clear_left_right(cmpop);
  544. end;
  545. procedure tcgaddnode.second_cmp64bit;
  546. begin
  547. (* load_left_right(true,false);
  548. case nodetype of
  549. ltn,lten,
  550. gtn,gten:
  551. begin
  552. emit_cmp64_hi;
  553. firstjmp64bitcmp;
  554. emit_cmp64_lo;
  555. secondjmp64bitcmp;
  556. end;
  557. equaln,unequaln:
  558. begin
  559. // instead of doing a complicated compare, do
  560. // (left.hi xor right.hi) or (left.lo xor right.lo)
  561. // (somewhate optimized so that no superfluous 'mr's are
  562. // generated)
  563. if (left.location.loc = LOC_CONSTANT) then
  564. swapleftright;
  565. if (right.location.loc = LOC_CONSTANT) then
  566. begin
  567. if left.location.loc = LOC_REGISTER then
  568. begin
  569. tempreg64.reglo := left.location.registerlow;
  570. tempreg64.reghi := left.location.registerhigh;
  571. end
  572. else
  573. begin
  574. if (aword(right.location.valueqword) <> 0) then
  575. tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist)
  576. else
  577. tempreg64.reglo := left.location.registerlow;
  578. if ((right.location.valueqword shr 32) <> 0) then
  579. tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist)
  580. else
  581. tempreg64.reghi := left.location.registerhigh;
  582. end;
  583. if (aword(right.location.valueqword) <> 0) then
  584. { negative values can be handled using SUB, }
  585. { positive values < 65535 using XOR. }
  586. if (longint(right.location.valueqword) >= -32767) and
  587. (longint(right.location.valueqword) < 0) then
  588. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  589. aword(right.location.valueqword),
  590. left.location.registerlow,tempreg64.reglo)
  591. else
  592. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  593. aword(right.location.valueqword),
  594. left.location.registerlow,tempreg64.reglo);
  595. if ((right.location.valueqword shr 32) <> 0) then
  596. if (longint(right.location.valueqword shr 32) >= -32767) and
  597. (longint(right.location.valueqword shr 32) < 0) then
  598. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  599. aword(right.location.valueqword shr 32),
  600. left.location.registerhigh,tempreg64.reghi)
  601. else
  602. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  603. aword(right.location.valueqword shr 32),
  604. left.location.registerhigh,tempreg64.reghi);
  605. end
  606. else
  607. begin
  608. tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist);
  609. tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist);
  610. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
  611. left.location.register64,right.location.register64,
  612. tempreg64);
  613. end;
  614. cg.a_reg_alloc(exprasmlist,R_0);
  615. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,R_0,
  616. tempreg64.reglo,tempreg64.reghi));
  617. cg.a_reg_dealloc(exprasmlist,R_0);
  618. if (tempreg64.reglo <> left.location.registerlow) then
  619. cg.free_scratch_reg(exprasmlist,tempreg64.reglo);
  620. if (tempreg64.reghi <> left.location.registerhigh) then
  621. cg.free_scratch_reg(exprasmlist,tempreg64.reghi);
  622. location_reset(location,LOC_FLAGS,OS_NO);
  623. location.resflags := getresflags;
  624. end;
  625. else
  626. internalerror(2002072803);
  627. end;
  628. { set result location }
  629. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  630. { real location only now) (JM) }
  631. if cmpop and
  632. not(nodetype in [equaln,unequaln]) then
  633. location_reset(location,LOC_JUMP,OS_NO);
  634. *)
  635. end;
  636. procedure tcgaddnode.second_add64bit;
  637. var
  638. op : TOpCG;
  639. unsigned : boolean;
  640. checkoverflow : boolean;
  641. begin
  642. unsigned:=((left.resulttype.def.deftype=orddef) and
  643. (torddef(left.resulttype.def).typ=u64bit)) or
  644. ((right.resulttype.def.deftype=orddef) and
  645. (torddef(right.resulttype.def).typ=u64bit));
  646. { assume no overflow checking is required }
  647. checkoverflow := false;
  648. case nodetype of
  649. addn :
  650. begin
  651. op:=OP_ADD;
  652. checkoverflow := true;
  653. end;
  654. subn :
  655. begin
  656. op:=OP_SUB;
  657. checkoverflow := true;
  658. end;
  659. xorn:
  660. op:=OP_XOR;
  661. orn:
  662. op:=OP_OR;
  663. andn:
  664. op:=OP_AND;
  665. muln:
  666. begin
  667. { should be handled in pass_1 (JM) }
  668. internalerror(200109051);
  669. end;
  670. else
  671. internalerror(2002072705);
  672. end;
  673. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  674. load_left_right(false,(cs_check_overflow in aktlocalswitches) and
  675. (nodetype in [addn,subn]));
  676. case nodetype of
  677. xorn,orn,andn,addn:
  678. begin
  679. if (location.registerlow = R_NO) then
  680. begin
  681. location.registerlow := rg.getregisterint(exprasmlist);
  682. location.registerhigh := rg.getregisterint(exprasmlist);
  683. end;
  684. if (left.location.loc = LOC_CONSTANT) then
  685. swapleftright;
  686. if (right.location.loc = LOC_CONSTANT) then
  687. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
  688. left.location.register64,location.register64)
  689. else
  690. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  691. left.location.register64,location.register64);
  692. end;
  693. subn:
  694. begin
  695. if (nf_swaped in flags) then
  696. swapleftright;
  697. if left.location.loc <> LOC_CONSTANT then
  698. begin
  699. if (location.registerlow = R_NO) then
  700. begin
  701. location.registerlow := rg.getregisterint(exprasmlist);
  702. location.registerhigh := rg.getregisterint(exprasmlist);
  703. end;
  704. if right.location.loc <> LOC_CONSTANT then
  705. // reg64 - reg64
  706. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  707. right.location.register64,left.location.register64,
  708. location.register64)
  709. else
  710. // reg64 - const64
  711. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  712. right.location.valueqword,left.location.register64,
  713. location.register64)
  714. end
  715. else
  716. begin
  717. // const64 - reg64
  718. location_force_reg(exprasmlist,left.location,
  719. def_cgsize(left.resulttype.def),true);
  720. if (left.location.loc = LOC_REGISTER) then
  721. location.register64 := left.location.register64
  722. else if (location.registerlow = R_NO) then
  723. begin
  724. location.registerlow := rg.getregisterint(exprasmlist);
  725. location.registerhigh := rg.getregisterint(exprasmlist);
  726. end;
  727. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  728. right.location.register64,left.location.register64,
  729. location.register64);
  730. end;
  731. end;
  732. else
  733. internalerror(2002072803);
  734. end;
  735. { emit overflow check if enabled }
  736. if checkoverflow then
  737. cg.g_overflowcheck(exprasmlist,self);
  738. end;
  739. {*****************************************************************************
  740. Floats
  741. *****************************************************************************}
  742. procedure tcgaddnode.second_opfloat;
  743. begin
  744. end;
  745. {*****************************************************************************
  746. Ordinals
  747. *****************************************************************************}
  748. procedure tcgaddnode.second_cmpordinal;
  749. var
  750. unsigned : boolean;
  751. begin
  752. { set result location }
  753. location_reset(location,LOC_FLAGS,OS_NO);
  754. { load values into registers (except constants) }
  755. load_left_right(true, false);
  756. { determine if the comparison will be unsigned }
  757. unsigned:=not(is_signed(left.resulttype.def)) or
  758. not(is_signed(right.resulttype.def));
  759. end;
  760. procedure tcgaddnode.second_addordinal;
  761. var
  762. unsigned : boolean;
  763. checkoverflow : boolean;
  764. cgop : topcg;
  765. tmpreg : tregister;
  766. begin
  767. { set result location }
  768. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  769. { determine if the comparison will be unsigned }
  770. unsigned:=not(is_signed(left.resulttype.def)) or
  771. not(is_signed(right.resulttype.def));
  772. { load values into registers }
  773. load_left_right(false, (cs_check_overflow in aktlocalswitches) and
  774. (nodetype in [addn,subn,muln]));
  775. if (location.register = R_NO) then
  776. location.register := rg.getregisterint(exprasmlist);
  777. { assume no overflow checking is require }
  778. checkoverflow := false;
  779. case nodetype of
  780. addn:
  781. begin
  782. cgop := OP_ADD;
  783. checkoverflow := true;
  784. end;
  785. xorn :
  786. begin
  787. cgop := OP_XOR;
  788. end;
  789. orn :
  790. begin
  791. cgop := OP_OR;
  792. end;
  793. andn:
  794. begin
  795. cgop := OP_AND;
  796. end;
  797. muln:
  798. begin
  799. checkoverflow := true;
  800. if unsigned then
  801. cgop := OP_MUL
  802. else
  803. cgop := OP_IMUL;
  804. end;
  805. subn :
  806. begin
  807. checkoverflow := true;
  808. cgop := OP_SUB;
  809. end;
  810. end;
  811. if nodetype <> subn then
  812. begin
  813. if (left.location.loc = LOC_CONSTANT) then
  814. swapleftright;
  815. if (right.location.loc <> LOC_CONSTANT) then
  816. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  817. left.location.register,right.location.register,
  818. location.register)
  819. else
  820. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  821. aword(right.location.value),left.location.register,
  822. location.register);
  823. end
  824. else { subtract is a special case since its not commutative }
  825. begin
  826. if (nf_swaped in flags) then
  827. swapleftright;
  828. if left.location.loc <> LOC_CONSTANT then
  829. begin
  830. if right.location.loc <> LOC_CONSTANT then
  831. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  832. right.location.register,left.location.register,
  833. location.register)
  834. else
  835. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  836. aword(right.location.value),left.location.register,
  837. location.register);
  838. end
  839. else
  840. begin
  841. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  842. cg.a_load_const_reg(exprasmlist,OS_INT,
  843. aword(left.location.value),tmpreg);
  844. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  845. right.location.register,tmpreg,location.register);
  846. cg.free_scratch_reg(exprasmlist,tmpreg);
  847. end;
  848. end;
  849. { emit overflow check if required }
  850. if checkoverflow then
  851. cg.g_overflowcheck(exprasmlist,self);
  852. end;
  853. {*****************************************************************************
  854. pass_2
  855. *****************************************************************************}
  856. procedure tcgaddnode.pass_2;
  857. { is also being used for xor, and "mul", "sub, or and comparative }
  858. { operators }
  859. var
  860. cmpop : boolean;
  861. cgop : topcg;
  862. op : tasmop;
  863. tmpreg : tregister;
  864. { true, if unsigned types are compared }
  865. unsigned : boolean;
  866. regstopush: tregisterset;
  867. begin
  868. { to make it more readable, string and set (not smallset!) have their
  869. own procedures }
  870. case left.resulttype.def.deftype of
  871. orddef :
  872. begin
  873. { handling boolean expressions }
  874. if is_boolean(left.resulttype.def) and
  875. is_boolean(right.resulttype.def) then
  876. begin
  877. second_opboolean;
  878. exit;
  879. end
  880. { 64bit operations }
  881. else if is_64bitint(left.resulttype.def) then
  882. begin
  883. second_op64bit;
  884. exit;
  885. end;
  886. end;
  887. stringdef :
  888. begin
  889. { this should already be handled in pass1 }
  890. internalerror(2002072402);
  891. exit;
  892. end;
  893. setdef :
  894. begin
  895. { normalsets are already handled in pass1 }
  896. if (tsetdef(left.resulttype.def).settype<>smallset) then
  897. internalerror(200109041);
  898. second_opsmallset;
  899. exit;
  900. end;
  901. arraydef :
  902. begin
  903. {$ifdef SUPPORT_MMX}
  904. if is_mmx_able_array(left.resulttype.def) then
  905. begin
  906. second_opmmx;
  907. exit;
  908. end;
  909. {$endif SUPPORT_MMX}
  910. end;
  911. floatdef :
  912. begin
  913. second_opfloat;
  914. exit;
  915. end;
  916. end;
  917. {*********************** ordinals / integrals *******************}
  918. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  919. { normally nothing should be in flags }
  920. if (left.location.loc = LOC_FLAGS) or
  921. (right.location.loc = LOC_FLAGS) then
  922. internalerror(2002072602);
  923. pass_left_and_right;
  924. if cmpop then
  925. second_cmpordinal
  926. else
  927. second_addordinal;
  928. { free used register (except the result register) }
  929. clear_left_right(cmpop);
  930. end;
  931. end.
  932. {
  933. $Log$
  934. Revision 1.3 2002-12-14 15:02:03 carl
  935. * maxoperands -> max_operands (for portability in rautils.pas)
  936. * fix some range-check errors with loadconst
  937. + add ncgadd unit to m68k
  938. * some bugfix of a_param_reg with LOC_CREFERENCE
  939. Revision 1.2 2002/12/08 15:02:17 carl
  940. + more fixes
  941. Revision 1.1 2002/12/07 19:51:35 carl
  942. + first version (uncompilable!)
  943. }