ncgadd.pas 37 KB

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