ncgadd.pas 30 KB

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