/compiler/ncgadd.pas

https://github.com/slibre/freepascal · Pascal · 861 lines · 678 code · 73 blank · 110 comment · 77 complexity · ebf0d391ded042b8c9ece8aacaf0ba32 MD5 · raw file

  1. {
  2. Copyright (c) 2000-2002 by the FPC development team
  3. Code generation for add nodes (generic version)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncgadd;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,nadd,cpubase;
  22. type
  23. tcgaddnode = class(taddnode)
  24. { function pass_1: tnode; override;}
  25. procedure pass_generate_code;override;
  26. protected
  27. { call secondpass for both left and right }
  28. procedure pass_left_right; virtual;
  29. { set the register of the result location }
  30. procedure set_result_location_reg;
  31. { load left and right nodes into registers }
  32. procedure force_reg_left_right(allow_swap,allow_constant:boolean);
  33. procedure second_opfloat;
  34. procedure second_opboolean;
  35. procedure second_opsmallset;
  36. procedure second_op64bit;
  37. procedure second_opordinal;
  38. procedure second_addstring;virtual;
  39. procedure second_addfloat;virtual;abstract;
  40. procedure second_addboolean;virtual;
  41. procedure second_addsmallset;virtual;
  42. procedure second_addsmallsetelement;virtual;
  43. {$ifdef x86}
  44. {$ifdef SUPPORT_MMX}
  45. procedure second_opmmx;virtual;abstract;
  46. {$endif SUPPORT_MMX}
  47. {$endif x86}
  48. procedure second_opvector;virtual;abstract;
  49. procedure second_add64bit;virtual;
  50. procedure second_addordinal;virtual;
  51. procedure second_cmpfloat;virtual;abstract;
  52. procedure second_cmpboolean;virtual;
  53. procedure second_cmpsmallset;virtual;abstract;
  54. procedure second_cmp64bit;virtual;abstract;
  55. procedure second_cmpordinal;virtual;abstract;
  56. end;
  57. implementation
  58. uses
  59. globtype,systems,
  60. cutils,verbose,globals,
  61. symconst,symdef,paramgr,
  62. aasmbase,aasmtai,aasmdata,defutil,
  63. cgbase,procinfo,pass_2,tgobj,
  64. nutils,ncon,nset,ncgutil,cgobj,cgutils,
  65. hlcgobj
  66. ;
  67. {*****************************************************************************
  68. Helpers
  69. *****************************************************************************}
  70. procedure tcgaddnode.pass_left_right;
  71. var
  72. tmpreg : tregister;
  73. {$ifdef x86}
  74. pushedfpu,
  75. {$endif x86}
  76. isjump : boolean;
  77. otl,ofl : tasmlabel;
  78. begin
  79. { calculate the operator which is more difficult }
  80. firstcomplex(self);
  81. { in case of constant put it to the left }
  82. if (left.nodetype=ordconstn) then
  83. swapleftright;
  84. isjump:=(left.expectloc=LOC_JUMP);
  85. if isjump then
  86. begin
  87. otl:=current_procinfo.CurrTrueLabel;
  88. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  89. ofl:=current_procinfo.CurrFalseLabel;
  90. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  91. end;
  92. secondpass(left);
  93. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  94. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,false);
  95. if isjump then
  96. begin
  97. current_procinfo.CurrTrueLabel:=otl;
  98. current_procinfo.CurrFalseLabel:=ofl;
  99. end
  100. else
  101. if left.location.loc=LOC_JUMP then
  102. internalerror(2012081302);
  103. {$ifdef x86}
  104. { are too few registers free? }
  105. pushedfpu:=false;
  106. if (left.location.loc=LOC_FPUREGISTER) and
  107. (node_resources_fpu(right)>=maxfpuregs) then
  108. begin
  109. hlcg.location_force_mem(current_asmdata.CurrAsmList,left.location,left.resultdef);
  110. pushedfpu:=true;
  111. end;
  112. {$endif x86}
  113. isjump:=(right.expectloc=LOC_JUMP);
  114. if isjump then
  115. begin
  116. otl:=current_procinfo.CurrTrueLabel;
  117. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  118. ofl:=current_procinfo.CurrFalseLabel;
  119. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  120. end;
  121. secondpass(right);
  122. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  123. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,false);
  124. if isjump then
  125. begin
  126. current_procinfo.CurrTrueLabel:=otl;
  127. current_procinfo.CurrFalseLabel:=ofl;
  128. end;
  129. {$ifdef x86}
  130. if pushedfpu then
  131. begin
  132. if use_vectorfpu(left.resultdef) then
  133. begin
  134. tmpreg := cg.getmmregister(current_asmdata.CurrAsmList,left.location.size);
  135. hlcg.a_loadmm_loc_reg(current_asmdata.CurrAsmList,left.location.size,left.location.size,left.location,tmpreg,mms_movescalar);
  136. location_freetemp(current_asmdata.CurrAsmList,left.location);
  137. location_reset(left.location,LOC_MMREGISTER,left.location.size);
  138. left.location.register:=tmpreg;
  139. end
  140. else
  141. begin
  142. tmpreg := cg.getfpuregister(current_asmdata.CurrAsmList,left.location.size);
  143. cg.a_loadfpu_loc_reg(current_asmdata.CurrAsmList,left.location.size,left.location,tmpreg);
  144. location_freetemp(current_asmdata.CurrAsmList,left.location);
  145. location_reset(left.location,LOC_FPUREGISTER,left.location.size);
  146. left.location.register := tmpreg;
  147. { left operand is now on top of the stack, instead of the right one! }
  148. if (right.location.loc=LOC_FPUREGISTER) then
  149. toggleflag(nf_swapped);
  150. end;
  151. end;
  152. {$endif x86}
  153. end;
  154. procedure tcgaddnode.set_result_location_reg;
  155. begin
  156. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  157. {$ifdef x86}
  158. if left.location.loc=LOC_REGISTER then
  159. begin
  160. if TCGSize2Size[left.location.size]<>TCGSize2Size[location.size] then
  161. internalerror(200307041);
  162. {$ifndef cpu64bitalu}
  163. if location.size in [OS_64,OS_S64] then
  164. begin
  165. location.register64.reglo := left.location.register64.reglo;
  166. location.register64.reghi := left.location.register64.reghi;
  167. end
  168. else
  169. {$endif}
  170. location.register := left.location.register;
  171. end
  172. else
  173. if right.location.loc=LOC_REGISTER then
  174. begin
  175. if TCGSize2Size[right.location.size]<>TCGSize2Size[location.size] then
  176. internalerror(200307042);
  177. {$ifndef cpu64bitalu}
  178. if location.size in [OS_64,OS_S64] then
  179. begin
  180. location.register64.reglo := right.location.register64.reglo;
  181. location.register64.reghi := right.location.register64.reghi;
  182. end
  183. else
  184. {$endif}
  185. location.register := right.location.register;
  186. end
  187. else
  188. {$endif}
  189. begin
  190. {$ifndef cpu64bitalu}
  191. if location.size in [OS_64,OS_S64] then
  192. begin
  193. location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  194. location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  195. end
  196. else
  197. {$endif}
  198. location.register := hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  199. end;
  200. end;
  201. procedure tcgaddnode.force_reg_left_right(allow_swap,allow_constant:boolean);
  202. begin
  203. if (left.location.loc<>LOC_REGISTER) and
  204. not(
  205. allow_constant and
  206. (left.location.loc in [LOC_CONSTANT,LOC_CREGISTER])
  207. ) then
  208. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
  209. if (right.location.loc<>LOC_REGISTER) and
  210. not(
  211. allow_constant and
  212. (right.location.loc in [LOC_CONSTANT,LOC_CREGISTER]) and
  213. (left.location.loc<>LOC_CONSTANT)
  214. ) then
  215. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,right.resultdef,false);
  216. { Left is always a register, right can be register or constant }
  217. if left.location.loc=LOC_CONSTANT then
  218. begin
  219. { when it is not allowed to swap we have a constant on
  220. left, that will give problems }
  221. if not allow_swap then
  222. internalerror(200307043);
  223. swapleftright;
  224. end;
  225. end;
  226. {*****************************************************************************
  227. Smallsets
  228. *****************************************************************************}
  229. procedure tcgaddnode.second_opsmallset;
  230. begin
  231. { when a setdef is passed, it has to be a smallset }
  232. if not(
  233. ((left.nodetype=setelementn) or is_smallset(left.resultdef)) and
  234. ((right.nodetype=setelementn) or is_smallset(right.resultdef))
  235. ) then
  236. internalerror(200203302);
  237. if (left.nodetype=setelementn) or (right.nodetype=setelementn) then
  238. second_addsmallsetelement
  239. else if nodetype in [equaln,unequaln,gtn,gten,lten,ltn] then
  240. second_cmpsmallset
  241. else
  242. second_addsmallset;
  243. end;
  244. procedure tcgaddnode.second_addsmallset;
  245. var
  246. cgop : TOpCg;
  247. opdone : boolean;
  248. begin
  249. opdone := false;
  250. pass_left_right;
  251. force_reg_left_right(true,true);
  252. set_result_location_reg;
  253. case nodetype of
  254. addn :
  255. cgop:=OP_OR;
  256. symdifn :
  257. cgop:=OP_XOR;
  258. muln :
  259. cgop:=OP_AND;
  260. subn :
  261. begin
  262. cgop:=OP_AND;
  263. if (not(nf_swapped in flags)) then
  264. if (right.location.loc=LOC_CONSTANT) then
  265. right.location.value := not(right.location.value)
  266. else
  267. opdone := true
  268. else if (left.location.loc=LOC_CONSTANT) then
  269. left.location.value := not(left.location.value)
  270. else
  271. begin
  272. swapleftright;
  273. opdone := true;
  274. end;
  275. if opdone then
  276. begin
  277. if (right.location.size<>left.location.size) or
  278. (location.size<>left.location.size) then
  279. internalerror(2010123001);
  280. { make sure that location.register is different from
  281. left.location.register, since right will overwrite it
  282. and we'll use left afterwards }
  283. if (right.location.loc=LOC_REGISTER) then
  284. location.register:=right.location.register
  285. else
  286. location.register:=cg.getintregister(current_asmdata.CurrAsmList,location.size);
  287. { make sure we don't modify left/right.location, because we told
  288. force_reg_left_right above that they can be constant }
  289. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,resultdef,right.location.register,location.register);
  290. if left.location.loc = LOC_CONSTANT then
  291. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,left.location.value,location.register)
  292. else
  293. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_AND,resultdef,left.location.register,location.register);
  294. end;
  295. end;
  296. else
  297. internalerror(2002072701);
  298. end;
  299. if not opdone then
  300. begin
  301. // these are all commutative operations
  302. if (left.location.loc = LOC_CONSTANT) then
  303. swapleftright;
  304. if (right.location.loc = LOC_CONSTANT) then
  305. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,
  306. right.location.value,left.location.register,
  307. location.register)
  308. else
  309. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,
  310. right.location.register,left.location.register,
  311. location.register);
  312. end;
  313. end;
  314. procedure tcgaddnode.second_addsmallsetelement;
  315. var
  316. tmpreg : tregister;
  317. mask,
  318. setbase : aint;
  319. cgop : TOpCg;
  320. begin
  321. if nodetype<>addn then
  322. internalerror(20080302);
  323. { no range support for smallsets }
  324. if assigned(tsetelementnode(right).right) then
  325. internalerror(20080303);
  326. pass_left_right;
  327. { setelementn is a special case, it must be on right }
  328. if (nf_swapped in flags) and
  329. (left.nodetype=setelementn) then
  330. swapleftright;
  331. force_reg_left_right(false,false);
  332. set_result_location_reg;
  333. setbase:=tsetdef(left.resultdef).setbase;
  334. if (right.location.loc = LOC_CONSTANT) then
  335. begin
  336. if (target_info.endian=endian_big) then
  337. mask:=aint((aword(1) shl (resultdef.size*8-1)) shr aword(right.location.value-setbase))
  338. else
  339. mask:=aint(1 shl (right.location.value-setbase));
  340. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,resultdef,
  341. mask,left.location.register,location.register);
  342. end
  343. else
  344. begin
  345. if (target_info.endian=endian_big) then
  346. begin
  347. mask:=aint((aword(1) shl (resultdef.size*8-1)));
  348. cgop:=OP_SHR
  349. end
  350. else
  351. begin
  352. mask:=1;
  353. cgop:=OP_SHL
  354. end;
  355. tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  356. hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef,mask,tmpreg);
  357. hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true);
  358. register_maybe_adjust_setbase(current_asmdata.CurrAsmList,right.location,setbase);
  359. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,
  360. right.location.register,tmpreg);
  361. if left.location.loc <> LOC_CONSTANT then
  362. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_OR,resultdef,tmpreg,
  363. left.location.register,location.register)
  364. else
  365. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,OP_OR,resultdef,
  366. left.location.value,tmpreg,location.register);
  367. end;
  368. end;
  369. {*****************************************************************************
  370. Boolean
  371. *****************************************************************************}
  372. procedure tcgaddnode.second_opboolean;
  373. begin
  374. if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
  375. second_cmpboolean
  376. else
  377. second_addboolean;
  378. end;
  379. procedure tcgaddnode.second_addboolean;
  380. var
  381. cgop : TOpCg;
  382. otl,ofl : tasmlabel;
  383. oldflowcontrol : tflowcontrol;
  384. begin
  385. { And,Or will only evaluate from left to right only the
  386. needed nodes unless full boolean evaluation is enabled }
  387. if (nodetype in [orn,andn]) and
  388. (not(cs_full_boolean_eval in current_settings.localswitches) or
  389. (nf_short_bool in flags)) then
  390. begin
  391. location_reset(location,LOC_JUMP,OS_NO);
  392. case nodetype of
  393. andn :
  394. begin
  395. otl:=current_procinfo.CurrTrueLabel;
  396. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  397. secondpass(left);
  398. hlcg.maketojumpbool(current_asmdata.CurrAsmList,left);
  399. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  400. current_procinfo.CurrTrueLabel:=otl;
  401. end;
  402. orn :
  403. begin
  404. ofl:=current_procinfo.CurrFalseLabel;
  405. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  406. secondpass(left);
  407. hlcg.maketojumpbool(current_asmdata.CurrAsmList,left);
  408. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  409. current_procinfo.CurrFalseLabel:=ofl;
  410. end;
  411. else
  412. internalerror(200307044);
  413. end;
  414. { these jumps mean we're now in a flow control construct }
  415. oldflowcontrol:=flowcontrol;
  416. include(flowcontrol,fc_inflowcontrol);
  417. secondpass(right);
  418. hlcg.maketojumpbool(current_asmdata.CurrAsmList,right);
  419. flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]);
  420. end
  421. else
  422. begin
  423. pass_left_right;
  424. force_reg_left_right(false,true);
  425. set_result_location_reg;
  426. case nodetype of
  427. xorn :
  428. cgop:=OP_XOR;
  429. orn :
  430. cgop:=OP_OR;
  431. andn :
  432. cgop:=OP_AND;
  433. else
  434. internalerror(200203247);
  435. end;
  436. {$ifndef cpu64bitalu}
  437. if right.location.size in [OS_64,OS_S64] then
  438. begin
  439. if right.location.loc <> LOC_CONSTANT then
  440. cg64.a_op64_reg_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
  441. left.location.register64,right.location.register64,
  442. location.register64)
  443. else
  444. cg64.a_op64_const_reg_reg(current_asmdata.CurrAsmList,cgop,location.size,
  445. right.location.value,left.location.register64,
  446. location.register64);
  447. end
  448. else
  449. {$endif cpu64bitalu}
  450. begin
  451. if right.location.loc <> LOC_CONSTANT then
  452. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,
  453. left.location.register,right.location.register,
  454. location.register)
  455. else
  456. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,cgop,resultdef,
  457. right.location.value,left.location.register,
  458. location.register);
  459. end;
  460. end;
  461. end;
  462. {*****************************************************************************
  463. 64-bit
  464. *****************************************************************************}
  465. procedure tcgaddnode.second_op64bit;
  466. begin
  467. if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
  468. second_cmp64bit
  469. else
  470. second_add64bit;
  471. end;
  472. procedure tcgaddnode.second_add64bit;
  473. var
  474. op : TOpCG;
  475. checkoverflow : boolean;
  476. ovloc : tlocation;
  477. begin
  478. ovloc.loc:=LOC_VOID;
  479. pass_left_right;
  480. force_reg_left_right(false,true);
  481. set_result_location_reg;
  482. { assume no overflow checking is required }
  483. checkoverflow := false;
  484. case nodetype of
  485. addn :
  486. begin
  487. op:=OP_ADD;
  488. checkoverflow:=true;
  489. end;
  490. subn :
  491. begin
  492. op:=OP_SUB;
  493. checkoverflow:=true;
  494. end;
  495. xorn:
  496. op:=OP_XOR;
  497. orn:
  498. op:=OP_OR;
  499. andn:
  500. op:=OP_AND;
  501. muln:
  502. begin
  503. { should be handled in pass_1 (JM) }
  504. internalerror(200109051);
  505. end;
  506. else
  507. internalerror(2002072705);
  508. end;
  509. checkoverflow:=
  510. checkoverflow and
  511. (left.resultdef.typ<>pointerdef) and
  512. (right.resultdef.typ<>pointerdef) and
  513. (cs_check_overflow in current_settings.localswitches);
  514. {$ifdef cpu64bitalu}
  515. case nodetype of
  516. xorn,orn,andn,addn:
  517. begin
  518. if (right.location.loc = LOC_CONSTANT) then
  519. hlcg.a_op_const_reg_reg(current_asmdata.CurrAsmList,op,resultdef,right.location.value,
  520. left.location.register,location.register)
  521. else
  522. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,op,resultdef,right.location.register,
  523. left.location.register,location.register);
  524. end;
  525. subn:
  526. begin
  527. if (nf_swapped in flags) then
  528. swapleftright;
  529. if left.location.loc <> LOC_CONSTANT then
  530. begin
  531. if right.location.loc <> LOC_CONSTANT then
  532. // reg64 - reg64
  533. hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef,
  534. right.location.register,left.location.register,location.register,
  535. checkoverflow,ovloc)
  536. else
  537. // reg64 - const64
  538. hlcg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef,
  539. right.location.value,left.location.register,location.register,
  540. checkoverflow,ovloc);
  541. end
  542. else
  543. begin
  544. // const64 - reg64
  545. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  546. hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef,
  547. right.location.register,left.location.register,location.register,
  548. checkoverflow,ovloc);
  549. end;
  550. end;
  551. else
  552. internalerror(2002072803);
  553. end;
  554. {$else cpu64bitalu}
  555. case nodetype of
  556. xorn,orn,andn,addn:
  557. begin
  558. if (right.location.loc = LOC_CONSTANT) then
  559. cg64.a_op64_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,op,location.size,right.location.value64,
  560. left.location.register64,location.register64,
  561. checkoverflow,ovloc)
  562. else
  563. cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,op,location.size,right.location.register64,
  564. left.location.register64,location.register64,
  565. checkoverflow,ovloc);
  566. end;
  567. subn:
  568. begin
  569. if (nf_swapped in flags) then
  570. swapleftright;
  571. if left.location.loc <> LOC_CONSTANT then
  572. begin
  573. if right.location.loc <> LOC_CONSTANT then
  574. // reg64 - reg64
  575. cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
  576. right.location.register64,left.location.register64,
  577. location.register64,
  578. checkoverflow,ovloc)
  579. else
  580. // reg64 - const64
  581. cg64.a_op64_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
  582. right.location.value64,left.location.register64,
  583. location.register64,
  584. checkoverflow,ovloc)
  585. end
  586. else
  587. begin
  588. // const64 - reg64
  589. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,true);
  590. cg64.a_op64_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,location.size,
  591. right.location.register64,left.location.register64,
  592. location.register64,
  593. checkoverflow,ovloc);
  594. end;
  595. end;
  596. else
  597. internalerror(2002072803);
  598. end;
  599. {$endif cpu64bitalu}
  600. { emit overflow check if enabled }
  601. if checkoverflow then
  602. hlcg.g_overflowcheck_loc(current_asmdata.CurrAsmList,Location,resultdef,ovloc);
  603. end;
  604. {*****************************************************************************
  605. Strings
  606. *****************************************************************************}
  607. procedure tcgaddnode.second_addstring;
  608. begin
  609. { this should already be handled in pass1 }
  610. internalerror(2002072402);
  611. end;
  612. {*****************************************************************************
  613. Floats
  614. *****************************************************************************}
  615. procedure tcgaddnode.second_opfloat;
  616. begin
  617. if nodetype in [ltn,lten,gtn,gten,equaln,unequaln] then
  618. second_cmpfloat
  619. else
  620. second_addfloat;
  621. end;
  622. {*****************************************************************************
  623. Ordinals
  624. *****************************************************************************}
  625. procedure tcgaddnode.second_opordinal;
  626. begin
  627. if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) then
  628. second_cmpordinal
  629. else
  630. second_addordinal;
  631. end;
  632. procedure tcgaddnode.second_addordinal;
  633. var
  634. unsigned,
  635. checkoverflow : boolean;
  636. cgop : topcg;
  637. tmpreg : tregister;
  638. ovloc : tlocation;
  639. begin
  640. ovloc.loc:=LOC_VOID;
  641. pass_left_right;
  642. force_reg_left_right(false,true);
  643. set_result_location_reg;
  644. { determine if the comparison will be unsigned }
  645. unsigned:=not(is_signed(left.resultdef)) or
  646. not(is_signed(right.resultdef));
  647. { assume no overflow checking is require }
  648. checkoverflow := false;
  649. case nodetype of
  650. addn:
  651. begin
  652. cgop:=OP_ADD;
  653. checkoverflow:=true;
  654. end;
  655. xorn :
  656. begin
  657. cgop:=OP_XOR;
  658. end;
  659. orn :
  660. begin
  661. cgop:=OP_OR;
  662. end;
  663. andn:
  664. begin
  665. cgop:=OP_AND;
  666. end;
  667. muln:
  668. begin
  669. checkoverflow:=true;
  670. if unsigned then
  671. cgop:=OP_MUL
  672. else
  673. cgop:=OP_IMUL;
  674. end;
  675. subn :
  676. begin
  677. checkoverflow:=true;
  678. cgop:=OP_SUB;
  679. end;
  680. end;
  681. checkoverflow:=
  682. checkoverflow and
  683. (left.resultdef.typ<>pointerdef) and
  684. (right.resultdef.typ<>pointerdef) and
  685. (cs_check_overflow in current_settings.localswitches);
  686. if nodetype<>subn then
  687. begin
  688. if (right.location.loc<>LOC_CONSTANT) then
  689. hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,cgop,resultdef,
  690. left.location.register,right.location.register,
  691. location.register,checkoverflow,ovloc)
  692. else
  693. hlcg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,cgop,resultdef,
  694. right.location.value,left.location.register,
  695. location.register,checkoverflow,ovloc);
  696. end
  697. else { subtract is a special case since its not commutative }
  698. begin
  699. if (nf_swapped in flags) then
  700. swapleftright;
  701. if left.location.loc<>LOC_CONSTANT then
  702. begin
  703. if right.location.loc<>LOC_CONSTANT then
  704. hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef,
  705. right.location.register,left.location.register,
  706. location.register,checkoverflow,ovloc)
  707. else
  708. hlcg.a_op_const_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef,
  709. right.location.value,left.location.register,
  710. location.register,checkoverflow,ovloc);
  711. end
  712. else
  713. begin
  714. tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  715. hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef,
  716. left.location.value,tmpreg);
  717. hlcg.a_op_reg_reg_reg_checkoverflow(current_asmdata.CurrAsmList,OP_SUB,resultdef,
  718. right.location.register,tmpreg,location.register,checkoverflow,ovloc);
  719. end;
  720. end;
  721. { emit overflow check if required }
  722. if checkoverflow then
  723. hlcg.g_overflowcheck_loc(current_asmdata.CurrAsmList,Location,resultdef,ovloc);
  724. end;
  725. procedure tcgaddnode.second_cmpboolean;
  726. begin
  727. second_cmpordinal;
  728. end;
  729. {*****************************************************************************
  730. pass_generate_code;
  731. *****************************************************************************}
  732. procedure tcgaddnode.pass_generate_code;
  733. begin
  734. case left.resultdef.typ of
  735. orddef :
  736. begin
  737. { handling boolean expressions }
  738. if is_boolean(left.resultdef) and
  739. is_boolean(right.resultdef) then
  740. second_opboolean
  741. { 64bit operations }
  742. else if is_64bit(left.resultdef) then
  743. second_op64bit
  744. else
  745. second_opordinal;
  746. end;
  747. stringdef :
  748. begin
  749. second_addstring;
  750. end;
  751. setdef :
  752. begin
  753. if is_smallset(tsetdef(left.resultdef)) then
  754. second_opsmallset
  755. else
  756. internalerror(200109041);
  757. end;
  758. arraydef :
  759. begin
  760. { support dynarr=nil }
  761. if is_dynamic_array(left.resultdef) then
  762. second_opordinal
  763. else
  764. if (cs_support_vectors in current_settings.globalswitches) and
  765. is_vector(left.resultdef) then
  766. second_opvector
  767. {$ifdef SUPPORT_MMX}
  768. else
  769. if is_mmx_able_array(left.resultdef) then
  770. second_opmmx
  771. {$endif SUPPORT_MMX}
  772. else
  773. internalerror(200306016);
  774. end;
  775. floatdef :
  776. second_opfloat;
  777. else
  778. second_opordinal;
  779. end;
  780. end;
  781. begin
  782. caddnode:=tcgaddnode;
  783. end.