2
0

ncgadd.pas 29 KB

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