ncgadd.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  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. protected
  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_opordinal;
  38. procedure second_addfloat;virtual;abstract;
  39. procedure second_addboolean;virtual;
  40. procedure second_addsmallset;virtual;
  41. procedure second_add64bit;virtual;
  42. procedure second_addordinal;virtual;
  43. procedure second_cmpfloat;virtual;abstract;
  44. procedure second_cmpboolean;virtual;abstract;
  45. procedure second_cmpsmallset;virtual;abstract;
  46. procedure second_cmp64bit;virtual;abstract;
  47. procedure second_cmpordinal;virtual;abstract;
  48. end;
  49. implementation
  50. uses
  51. globtype,systems,
  52. cutils,verbose,globals,
  53. symconst,symdef,paramgr,
  54. aasmbase,aasmtai,aasmcpu,defutil,htypechk,
  55. cgbase,cpuinfo,pass_1,pass_2,regvars,
  56. ncon,nset,ncgutil,tgobj,rgobj,cgobj,
  57. {$ifdef cpu64bit}
  58. cg64f64
  59. {$else cpu64bit}
  60. cg64f32
  61. {$endif cpu64bit}
  62. ;
  63. {*****************************************************************************
  64. Helpers
  65. *****************************************************************************}
  66. procedure tcgaddnode.pass_left_and_right;
  67. var
  68. pushedregs : tmaybesave;
  69. tmpreg : tregister;
  70. pushedfpu : boolean;
  71. begin
  72. { calculate the operator which is more difficult }
  73. firstcomplex(self);
  74. { in case of constant put it to the left }
  75. if (left.nodetype=ordconstn) then
  76. swapleftright;
  77. secondpass(left);
  78. { are too few registers free? }
  79. {$ifndef newra}
  80. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  81. {$endif}
  82. if location.loc=LOC_FPUREGISTER then
  83. pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
  84. else
  85. pushedfpu:=false;
  86. secondpass(right);
  87. {$ifndef newra}
  88. maybe_restore(exprasmlist,left.location,pushedregs);
  89. {$endif}
  90. if pushedfpu then
  91. begin
  92. tmpreg := rg.getregisterfpu(exprasmlist,left.location.size);
  93. cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
  94. location_reset(left.location,LOC_FPUREGISTER,left.location.size);
  95. left.location.register := tmpreg;
  96. end;
  97. end;
  98. procedure tcgaddnode.load_left_right(cmpop, load_constants: boolean);
  99. procedure load_node(var n: tnode);
  100. begin
  101. case n.location.loc of
  102. LOC_REGISTER:
  103. if not cmpop then
  104. begin
  105. location.register := n.location.register;
  106. if is_64bit(n.resulttype.def) then
  107. location.registerhigh := n.location.registerhigh;
  108. end;
  109. LOC_REFERENCE,LOC_CREFERENCE:
  110. begin
  111. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  112. if not cmpop then
  113. begin
  114. location.register := n.location.register;
  115. if is_64bit(n.resulttype.def) then
  116. location.registerhigh := n.location.registerhigh;
  117. end;
  118. end;
  119. LOC_CONSTANT:
  120. begin
  121. if load_constants then
  122. begin
  123. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  124. if not cmpop then
  125. location.register := n.location.register;
  126. if is_64bit(n.resulttype.def) then
  127. location.registerhigh := n.location.registerhigh;
  128. end;
  129. end;
  130. end;
  131. end;
  132. begin
  133. load_node(left);
  134. load_node(right);
  135. end;
  136. procedure tcgaddnode.clear_left_right(cmpop: boolean);
  137. begin
  138. if (right.location.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  139. (cmpop or
  140. (location.register.enum <> right.location.register.enum)) then
  141. begin
  142. location_release(exprasmlist,right.location);
  143. end;
  144. if (left.location.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  145. (cmpop or
  146. (location.register.enum <> left.location.register.enum)) then
  147. begin
  148. location_release(exprasmlist,left.location);
  149. end;
  150. end;
  151. {*****************************************************************************
  152. Smallsets
  153. *****************************************************************************}
  154. procedure tcgaddnode.second_opsmallset;
  155. var
  156. cmpop : boolean;
  157. begin
  158. cmpop := false;
  159. pass_left_and_right;
  160. { when a setdef is passed, it has to be a smallset }
  161. if ((left.resulttype.def.deftype=setdef) and
  162. (tsetdef(left.resulttype.def).settype<>smallset)) or
  163. ((right.resulttype.def.deftype=setdef) and
  164. (tsetdef(right.resulttype.def).settype<>smallset)) then
  165. internalerror(200203301);
  166. if nodetype in [equaln,unequaln,gtn,gten,lten,ltn] then
  167. cmpop := true;
  168. { load non-constant values (left and right) into registers }
  169. load_left_right(cmpop,false);
  170. if cmpop then
  171. second_cmpsmallset
  172. else
  173. second_addsmallset;
  174. clear_left_right(cmpop);
  175. end;
  176. procedure tcgaddnode.second_addsmallset;
  177. var
  178. cgop : TOpCg;
  179. tmpreg : tregister;
  180. opdone : boolean;
  181. size:Tcgsize;
  182. begin
  183. opdone := false;
  184. size:=def_cgsize(resulttype.def);
  185. location_reset(location,LOC_REGISTER,size);
  186. if (location.register.enum = R_NO) then
  187. location.register := rg.getregisterint(exprasmlist,size);
  188. case nodetype of
  189. addn :
  190. begin
  191. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  192. swapleftright;
  193. { are we adding set elements ? }
  194. if right.nodetype=setelementn then
  195. begin
  196. { no range support for smallsets! }
  197. if assigned(tsetelementnode(right).right) then
  198. internalerror(43244);
  199. if (right.location.loc = LOC_CONSTANT) then
  200. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  201. aword(1 shl aword(right.location.value)),
  202. left.location.register,location.register)
  203. else
  204. begin
  205. {$ifdef newra}
  206. tmpreg := rg.getregisterint(exprasmlist,size);
  207. {$else}
  208. tmpreg := cg.get_scratch_reg_int(exprasmlist,size);
  209. {$endif}
  210. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  211. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  212. right.location.register,tmpreg);
  213. if left.location.loc <> LOC_CONSTANT then
  214. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  215. left.location.register,location.register)
  216. else
  217. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  218. aword(left.location.value),tmpreg,location.register);
  219. {$ifdef newra}
  220. rg.ungetregisterint(exprasmlist,tmpreg);
  221. {$else}
  222. cg.free_scratch_reg(exprasmlist,tmpreg);
  223. {$endif}
  224. end;
  225. opdone := true;
  226. end
  227. else
  228. cgop := OP_OR;
  229. end;
  230. symdifn :
  231. cgop:=OP_XOR;
  232. muln :
  233. cgop:=OP_AND;
  234. subn :
  235. begin
  236. cgop:=OP_AND;
  237. if (not(nf_swaped in flags)) then
  238. if (right.location.loc=LOC_CONSTANT) then
  239. right.location.value := not(right.location.value)
  240. else
  241. opdone := true
  242. else if (left.location.loc=LOC_CONSTANT) then
  243. left.location.value := not(left.location.value)
  244. else
  245. begin
  246. swapleftright;
  247. opdone := true;
  248. end;
  249. if opdone then
  250. begin
  251. if left.location.loc = LOC_CONSTANT then
  252. begin
  253. {$ifdef newra}
  254. tmpreg := rg.getregisterint(exprasmlist,OS_INT);
  255. {$else}
  256. tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
  257. {$endif}
  258. cg.a_load_const_reg(exprasmlist,OS_INT,
  259. aword(left.location.value),tmpreg);
  260. cg.a_op_reg_reg(exprasmlist,OP_NOT,OS_INT,right.location.register,right.location.register);
  261. cg.a_op_reg_reg(exprasmlist,OP_AND,OS_INT,right.location.register,tmpreg);
  262. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,tmpreg,location.register);
  263. {$ifdef newra}
  264. rg.ungetregisterint(exprasmlist,tmpreg);
  265. {$else}
  266. cg.free_scratch_reg(exprasmlist,tmpreg);
  267. {$endif}
  268. end
  269. else
  270. begin
  271. cg.a_op_reg_reg(exprasmlist,OP_NOT,OS_INT,right.location.register,right.location.register);
  272. cg.a_op_reg_reg(exprasmlist,OP_AND,OS_INT,right.location.register,left.location.register);
  273. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_INT,left.location.register,location.register);
  274. end;
  275. end;
  276. end;
  277. else
  278. internalerror(2002072701);
  279. end;
  280. if not opdone then
  281. begin
  282. // these are all commutative operations
  283. if (left.location.loc = LOC_CONSTANT) then
  284. swapleftright;
  285. if (right.location.loc = LOC_CONSTANT) then
  286. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  287. aword(right.location.value),left.location.register,
  288. location.register)
  289. else
  290. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  291. right.location.register,left.location.register,
  292. location.register);
  293. end;
  294. end;
  295. {*****************************************************************************
  296. Boolean
  297. *****************************************************************************}
  298. procedure tcgaddnode.second_opboolean;
  299. begin
  300. { calculate the operator which is more difficult }
  301. firstcomplex(self);
  302. if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
  303. second_cmpboolean
  304. else
  305. second_addboolean;
  306. end;
  307. procedure tcgaddnode.second_addboolean;
  308. var
  309. cgop : TOpCg;
  310. cgsize : TCgSize;
  311. isjump : boolean;
  312. otl,ofl : tasmlabel;
  313. pushedregs : tmaybesave;
  314. begin
  315. if (torddef(left.resulttype.def).typ=bool8bit) or
  316. (torddef(right.resulttype.def).typ=bool8bit) then
  317. cgsize:=OS_8
  318. else
  319. if (torddef(left.resulttype.def).typ=bool16bit) or
  320. (torddef(right.resulttype.def).typ=bool16bit) then
  321. cgsize:=OS_16
  322. else
  323. cgsize:=OS_32;
  324. if (cs_full_boolean_eval in aktlocalswitches) or
  325. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  326. begin
  327. if left.nodetype in [ordconstn,realconstn] then
  328. swapleftright;
  329. isjump:=(left.location.loc=LOC_JUMP);
  330. if isjump then
  331. begin
  332. otl:=truelabel;
  333. objectlibrary.getlabel(truelabel);
  334. ofl:=falselabel;
  335. objectlibrary.getlabel(falselabel);
  336. end;
  337. secondpass(left);
  338. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  339. location_force_reg(exprasmlist,left.location,cgsize,false);
  340. if isjump then
  341. begin
  342. truelabel:=otl;
  343. falselabel:=ofl;
  344. end;
  345. {$ifndef newra}
  346. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  347. {$endif}
  348. isjump:=(right.location.loc=LOC_JUMP);
  349. if isjump then
  350. begin
  351. otl:=truelabel;
  352. objectlibrary.getlabel(truelabel);
  353. ofl:=falselabel;
  354. objectlibrary.getlabel(falselabel);
  355. end;
  356. secondpass(right);
  357. {$ifndef newra}
  358. maybe_restore(exprasmlist,left.location,pushedregs);
  359. {$endif}
  360. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  361. location_force_reg(exprasmlist,right.location,cgsize,false);
  362. if isjump then
  363. begin
  364. truelabel:=otl;
  365. falselabel:=ofl;
  366. end;
  367. { set result location }
  368. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  369. load_left_right(false,false);
  370. if (left.location.loc = LOC_CONSTANT) then
  371. swapleftright;
  372. case nodetype of
  373. xorn :
  374. cgop:=OP_XOR;
  375. orn :
  376. cgop:=OP_OR;
  377. andn :
  378. cgop:=OP_AND;
  379. else
  380. internalerror(200203247);
  381. end;
  382. if right.location.loc <> LOC_CONSTANT then
  383. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  384. left.location.register,right.location.register,
  385. location.register)
  386. else
  387. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  388. aword(right.location.value),left.location.register,
  389. location.register);
  390. end
  391. else
  392. begin
  393. case nodetype of
  394. andn,
  395. orn :
  396. begin
  397. location_reset(location,LOC_JUMP,OS_NO);
  398. case nodetype of
  399. andn :
  400. begin
  401. otl:=truelabel;
  402. objectlibrary.getlabel(truelabel);
  403. secondpass(left);
  404. maketojumpbool(exprasmlist,left,lr_load_regvars);
  405. cg.a_label(exprasmlist,truelabel);
  406. truelabel:=otl;
  407. end;
  408. orn :
  409. begin
  410. ofl:=falselabel;
  411. objectlibrary.getlabel(falselabel);
  412. secondpass(left);
  413. maketojumpbool(exprasmlist,left,lr_load_regvars);
  414. cg.a_label(exprasmlist,falselabel);
  415. falselabel:=ofl;
  416. end;
  417. end;
  418. secondpass(right);
  419. maketojumpbool(exprasmlist,right,lr_load_regvars);
  420. end;
  421. end;
  422. end;
  423. { free used register (except the result register) }
  424. clear_left_right(true);
  425. end;
  426. {*****************************************************************************
  427. 64-bit
  428. *****************************************************************************}
  429. procedure tcgaddnode.second_op64bit;
  430. var
  431. cmpop : boolean;
  432. begin
  433. cmpop:=(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]);
  434. firstcomplex(self);
  435. pass_left_and_right;
  436. if cmpop then
  437. second_cmp64bit
  438. else
  439. second_add64bit;
  440. { free used register (except the result register) }
  441. clear_left_right(cmpop);
  442. end;
  443. procedure tcgaddnode.second_add64bit;
  444. var
  445. op : TOpCG;
  446. checkoverflow : boolean;
  447. begin
  448. { assume no overflow checking is required }
  449. checkoverflow := false;
  450. case nodetype of
  451. addn :
  452. begin
  453. op:=OP_ADD;
  454. checkoverflow := true;
  455. end;
  456. subn :
  457. begin
  458. op:=OP_SUB;
  459. checkoverflow := true;
  460. end;
  461. xorn:
  462. op:=OP_XOR;
  463. orn:
  464. op:=OP_OR;
  465. andn:
  466. op:=OP_AND;
  467. muln:
  468. begin
  469. { should be handled in pass_1 (JM) }
  470. internalerror(200109051);
  471. end;
  472. else
  473. internalerror(2002072705);
  474. end;
  475. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  476. load_left_right(false,(cs_check_overflow in aktlocalswitches) and
  477. (nodetype in [addn,subn]));
  478. case nodetype of
  479. xorn,orn,andn,addn:
  480. begin
  481. if (location.registerlow.enum = R_NO) then
  482. begin
  483. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  484. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  485. end;
  486. if (left.location.loc = LOC_CONSTANT) then
  487. swapleftright;
  488. if (right.location.loc = LOC_CONSTANT) then
  489. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
  490. left.location.register64,location.register64)
  491. else
  492. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  493. left.location.register64,location.register64);
  494. end;
  495. subn:
  496. begin
  497. if (nf_swaped in flags) then
  498. swapleftright;
  499. if left.location.loc <> LOC_CONSTANT then
  500. begin
  501. if (location.registerlow.enum = R_NO) then
  502. begin
  503. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  504. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  505. end;
  506. if right.location.loc <> LOC_CONSTANT then
  507. // reg64 - reg64
  508. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  509. right.location.register64,left.location.register64,
  510. location.register64)
  511. else
  512. // reg64 - const64
  513. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  514. right.location.valueqword,left.location.register64,
  515. location.register64)
  516. end
  517. else
  518. begin
  519. // const64 - reg64
  520. location_force_reg(exprasmlist,left.location,
  521. def_cgsize(left.resulttype.def),true);
  522. if (left.location.loc = LOC_REGISTER) then
  523. location.register64 := left.location.register64
  524. else if (location.registerlow.enum = R_NO) then
  525. begin
  526. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  527. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  528. end;
  529. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  530. right.location.register64,left.location.register64,
  531. location.register64);
  532. end;
  533. end;
  534. else
  535. internalerror(2002072803);
  536. end;
  537. { emit overflow check if enabled }
  538. if checkoverflow then
  539. cg.g_overflowcheck(exprasmlist,Location,ResultType.Def);
  540. end;
  541. {*****************************************************************************
  542. Floats
  543. *****************************************************************************}
  544. procedure tcgaddnode.second_opfloat;
  545. var
  546. cmpop : boolean;
  547. begin
  548. cmpop:=(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]);
  549. firstcomplex(self);
  550. pass_left_and_right;
  551. if cmpop then
  552. second_cmpfloat
  553. else
  554. second_addfloat;
  555. { free used register (except the result register) }
  556. clear_left_right(cmpop);
  557. end;
  558. {*****************************************************************************
  559. Ordinals
  560. *****************************************************************************}
  561. procedure tcgaddnode.second_opordinal;
  562. var
  563. cmpop : boolean;
  564. begin
  565. cmpop:=(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]);
  566. { normally nothing should be in flags }
  567. if (left.location.loc = LOC_FLAGS) or
  568. (right.location.loc = LOC_FLAGS) then
  569. internalerror(2002072602);
  570. pass_left_and_right;
  571. if cmpop then
  572. second_cmpordinal
  573. else
  574. second_addordinal;
  575. { free used register (except the result register) }
  576. clear_left_right(cmpop);
  577. end;
  578. procedure tcgaddnode.second_addordinal;
  579. var
  580. unsigned : boolean;
  581. checkoverflow : boolean;
  582. cgop : topcg;
  583. tmpreg : tregister;
  584. size:Tcgsize;
  585. begin
  586. size:=def_cgsize(resulttype.def);
  587. { set result location }
  588. location_reset(location,LOC_REGISTER,size);
  589. { determine if the comparison will be unsigned }
  590. unsigned:=not(is_signed(left.resulttype.def)) or
  591. not(is_signed(right.resulttype.def));
  592. { load values into registers }
  593. load_left_right(false, (cs_check_overflow in aktlocalswitches) and
  594. (nodetype in [addn,subn,muln]));
  595. if (location.register.enum = R_NO) then
  596. location.register := rg.getregisterint(exprasmlist,OS_INT);
  597. { assume no overflow checking is require }
  598. checkoverflow := false;
  599. case nodetype of
  600. addn:
  601. begin
  602. cgop := OP_ADD;
  603. checkoverflow := true;
  604. end;
  605. xorn :
  606. begin
  607. cgop := OP_XOR;
  608. end;
  609. orn :
  610. begin
  611. cgop := OP_OR;
  612. end;
  613. andn:
  614. begin
  615. cgop := OP_AND;
  616. end;
  617. muln:
  618. begin
  619. checkoverflow := true;
  620. if unsigned then
  621. cgop := OP_MUL
  622. else
  623. cgop := OP_IMUL;
  624. end;
  625. subn :
  626. begin
  627. checkoverflow := true;
  628. cgop := OP_SUB;
  629. end;
  630. end;
  631. if nodetype <> subn then
  632. begin
  633. if (left.location.loc = LOC_CONSTANT) then
  634. swapleftright;
  635. if (right.location.loc <> LOC_CONSTANT) then
  636. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  637. left.location.register,right.location.register,
  638. location.register)
  639. else
  640. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  641. aword(right.location.value),left.location.register,
  642. location.register);
  643. end
  644. else { subtract is a special case since its not commutative }
  645. begin
  646. if (nf_swaped in flags) then
  647. swapleftright;
  648. if left.location.loc <> LOC_CONSTANT then
  649. begin
  650. if right.location.loc <> LOC_CONSTANT then
  651. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  652. right.location.register,left.location.register,
  653. location.register)
  654. else
  655. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  656. aword(right.location.value),left.location.register,
  657. location.register);
  658. end
  659. else
  660. begin
  661. {$ifdef newra}
  662. tmpreg := rg.getregisterint(exprasmlist,OS_INT);
  663. {$else}
  664. tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
  665. {$endif}
  666. cg.a_load_const_reg(exprasmlist,OS_INT,
  667. aword(left.location.value),tmpreg);
  668. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  669. right.location.register,tmpreg,location.register);
  670. {$ifdef newra}
  671. rg.ungetregisterint(exprasmlist,tmpreg);
  672. {$else}
  673. cg.free_scratch_reg(exprasmlist,tmpreg);
  674. {$endif}
  675. end;
  676. end;
  677. { emit overflow check if required }
  678. if checkoverflow then
  679. cg.g_overflowcheck(exprasmlist,Location,ResultType.Def);
  680. end;
  681. {*****************************************************************************
  682. pass_2
  683. *****************************************************************************}
  684. procedure tcgaddnode.pass_2;
  685. begin
  686. case left.resulttype.def.deftype of
  687. orddef :
  688. begin
  689. { handling boolean expressions }
  690. if is_boolean(left.resulttype.def) and
  691. is_boolean(right.resulttype.def) then
  692. second_opboolean
  693. { 64bit operations }
  694. else if is_64bit(left.resulttype.def) then
  695. second_op64bit
  696. else
  697. second_opordinal;
  698. end;
  699. stringdef :
  700. begin
  701. { this should already be handled in pass1 }
  702. internalerror(2002072402);
  703. end;
  704. setdef :
  705. begin
  706. { normalsets are already handled in pass1 }
  707. if (tsetdef(left.resulttype.def).settype<>smallset) then
  708. internalerror(200109041);
  709. second_opsmallset;
  710. end;
  711. arraydef :
  712. begin
  713. {$ifdef SUPPORT_MMX}
  714. if is_mmx_able_array(left.resulttype.def) then
  715. second_opmmx;
  716. {$endif SUPPORT_MMX}
  717. { only mmx arrays are possible }
  718. internalerror(200306016);
  719. end;
  720. floatdef :
  721. second_opfloat;
  722. else
  723. second_opordinal;
  724. end;
  725. end;
  726. begin
  727. caddnode:=tcgaddnode;
  728. end.
  729. {
  730. $Log$
  731. Revision 1.13 2003-06-12 16:43:07 peter
  732. * newra compiles for sparc
  733. Revision 1.12 2003/06/10 20:46:17 mazen
  734. * fixing a general compile problem related to
  735. cg.g_overflowcheck declaration that has
  736. changed
  737. Revision 1.11 2003/06/01 21:38:06 peter
  738. * getregisterfpu size parameter added
  739. * op_const_reg size parameter added
  740. * sparc updates
  741. Revision 1.10 2003/05/23 14:27:35 peter
  742. * remove some unit dependencies
  743. * current_procinfo changes to store more info
  744. Revision 1.9 2003/04/30 22:15:59 florian
  745. * some 64 bit adaptions in ncgadd
  746. * x86-64 now uses ncgadd
  747. * tparamanager.ret_in_acc doesn't return true anymore for a void-def
  748. Revision 1.8 2003/04/23 20:16:04 peter
  749. + added currency support based on int64
  750. + is_64bit for use in cg units instead of is_64bitint
  751. * removed cgmessage from n386add, replace with internalerrors
  752. Revision 1.7 2003/04/22 23:50:22 peter
  753. * firstpass uses expectloc
  754. * checks if there are differences between the expectloc and
  755. location.loc from secondpass in EXTDEBUG
  756. Revision 1.6 2003/02/19 22:00:14 daniel
  757. * Code generator converted to new register notation
  758. - Horribily outdated todo.txt removed
  759. Revision 1.5 2003/02/02 19:25:54 carl
  760. * Several bugfixes for m68k target (register alloc., opcode emission)
  761. + VIS target
  762. + Generic add more complete (still not verified)
  763. Revision 1.4 2003/01/08 18:43:56 daniel
  764. * Tregister changed into a record
  765. Revision 1.3 2002/12/14 15:02:03 carl
  766. * maxoperands -> max_operands (for portability in rautils.pas)
  767. * fix some range-check errors with loadconst
  768. + add ncgadd unit to m68k
  769. * some bugfix of a_param_reg with LOC_CREFERENCE
  770. Revision 1.2 2002/12/08 15:02:17 carl
  771. + more fixes
  772. Revision 1.1 2002/12/07 19:51:35 carl
  773. + first version (uncompilable!)
  774. }