nppcadd.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
  4. Code generation for add nodes on the PowerPC
  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 nppcadd;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nadd,ncgadd,cpubase;
  23. type
  24. tppcaddnode = class(tcgaddnode)
  25. function pass_1: tnode; override;
  26. procedure pass_2;override;
  27. private
  28. procedure pass_left_and_right;
  29. procedure load_left_right(cmpop, load_constants: boolean);
  30. function getresflags : tresflags;
  31. procedure emit_compare(unsigned : boolean);
  32. procedure second_addfloat;override;
  33. procedure second_addboolean;override;
  34. procedure second_addsmallset;override;
  35. {$ifdef SUPPORT_MMX}
  36. procedure second_addmmx;override;
  37. {$endif SUPPORT_MMX}
  38. procedure second_add64bit;override;
  39. end;
  40. implementation
  41. uses
  42. globtype,systems,
  43. cutils,verbose,globals,
  44. symconst,symdef,paramgr,
  45. aasmbase,aasmtai,aasmcpu,defutil,htypechk,
  46. cgbase,cpuinfo,pass_1,pass_2,regvars,
  47. cpupara,cgcpu,cgutils,
  48. ncon,nset,
  49. ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
  50. {*****************************************************************************
  51. Pass 1
  52. *****************************************************************************}
  53. function tppcaddnode.pass_1: tnode;
  54. begin
  55. resulttypepass(left);
  56. if (nodetype in [equaln,unequaln]) and
  57. (left.resulttype.def.deftype = orddef) and
  58. is_64bit(left.resulttype.def) then
  59. begin
  60. result := nil;
  61. firstpass(left);
  62. firstpass(right);
  63. expectloc := LOC_FLAGS;
  64. calcregisters(self,2,0,0);
  65. exit;
  66. end;
  67. result := inherited pass_1;
  68. end;
  69. {*****************************************************************************
  70. Helpers
  71. *****************************************************************************}
  72. procedure tppcaddnode.pass_left_and_right;
  73. begin
  74. { calculate the operator which is more difficult }
  75. firstcomplex(self);
  76. { in case of constant put it to the left }
  77. if (left.nodetype=ordconstn) then
  78. swapleftright;
  79. secondpass(left);
  80. secondpass(right);
  81. end;
  82. procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
  83. procedure load_node(var n: tnode);
  84. begin
  85. case n.location.loc of
  86. LOC_REGISTER:
  87. if not cmpop then
  88. begin
  89. location.register := n.location.register;
  90. if is_64bit(n.resulttype.def) then
  91. location.register64.reghi := n.location.register64.reghi;
  92. end;
  93. LOC_REFERENCE,LOC_CREFERENCE:
  94. begin
  95. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  96. if not cmpop then
  97. begin
  98. location.register := n.location.register;
  99. if is_64bit(n.resulttype.def) then
  100. location.register64.reghi := n.location.register64.reghi;
  101. end;
  102. end;
  103. LOC_CONSTANT:
  104. begin
  105. if load_constants then
  106. begin
  107. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  108. if not cmpop then
  109. location.register := n.location.register;
  110. if is_64bit(n.resulttype.def) then
  111. location.register64.reghi := n.location.register64.reghi;
  112. end;
  113. end;
  114. end;
  115. end;
  116. begin
  117. load_node(left);
  118. load_node(right);
  119. if not(cmpop) and
  120. (location.register = NR_NO) then
  121. begin
  122. location.register := cg.getintregister(exprasmlist,OS_INT);
  123. if is_64bit(resulttype.def) then
  124. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  125. end;
  126. end;
  127. function tppcaddnode.getresflags : tresflags;
  128. begin
  129. if (left.resulttype.def.deftype <> floatdef) then
  130. result.cr := RS_CR0
  131. else
  132. result.cr := RS_CR1;
  133. case nodetype of
  134. equaln : result.flag:=F_EQ;
  135. unequaln : result.flag:=F_NE;
  136. else
  137. if nf_swaped in flags then
  138. case nodetype of
  139. ltn : result.flag:=F_GT;
  140. lten : result.flag:=F_GE;
  141. gtn : result.flag:=F_LT;
  142. gten : result.flag:=F_LE;
  143. end
  144. else
  145. case nodetype of
  146. ltn : result.flag:=F_LT;
  147. lten : result.flag:=F_LE;
  148. gtn : result.flag:=F_GT;
  149. gten : result.flag:=F_GE;
  150. end;
  151. end
  152. end;
  153. procedure tppcaddnode.emit_compare(unsigned: boolean);
  154. var
  155. op : tasmop;
  156. tmpreg : tregister;
  157. useconst : boolean;
  158. begin
  159. // get the constant on the right if there is one
  160. if (left.location.loc = LOC_CONSTANT) then
  161. swapleftright;
  162. // can we use an immediate, or do we have to load the
  163. // constant in a register first?
  164. if (right.location.loc = LOC_CONSTANT) then
  165. begin
  166. {$ifdef dummy}
  167. if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>$ffffffff) or unsigned) then
  168. internalerror(2002080301);
  169. {$endif extdebug}
  170. if (nodetype in [equaln,unequaln]) then
  171. if (unsigned and
  172. (aword(right.location.value) > high(word))) or
  173. (not unsigned and
  174. (aint(right.location.value) < low(smallint)) or
  175. (aint(right.location.value) > high(smallint))) then
  176. { we can then maybe use a constant in the 'othersigned' case
  177. (the sign doesn't matter for // equal/unequal)}
  178. unsigned := not unsigned;
  179. if (unsigned and
  180. (aword(right.location.value) <= high(word))) or
  181. (not(unsigned) and
  182. (aint(right.location.value) >= low(smallint)) and
  183. (aint(right.location.value) <= high(smallint))) then
  184. useconst := true
  185. else
  186. begin
  187. useconst := false;
  188. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  189. cg.a_load_const_reg(exprasmlist,OS_INT,
  190. right.location.value,tmpreg);
  191. end
  192. end
  193. else
  194. useconst := false;
  195. location.loc := LOC_FLAGS;
  196. location.resflags := getresflags;
  197. if not unsigned then
  198. if useconst then
  199. op := A_CMPWI
  200. else
  201. op := A_CMPW
  202. else
  203. if useconst then
  204. op := A_CMPLWI
  205. else
  206. op := A_CMPLW;
  207. if (right.location.loc = LOC_CONSTANT) then
  208. begin
  209. if useconst then
  210. exprasmlist.concat(taicpu.op_reg_const(op,left.location.register,longint(right.location.value)))
  211. else
  212. exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg));
  213. end
  214. else
  215. exprasmlist.concat(taicpu.op_reg_reg(op,
  216. left.location.register,right.location.register));
  217. end;
  218. {*****************************************************************************
  219. AddBoolean
  220. *****************************************************************************}
  221. procedure tppcaddnode.second_addboolean;
  222. var
  223. cgop : TOpCg;
  224. cgsize : TCgSize;
  225. cmpop,
  226. isjump : boolean;
  227. otl,ofl : tasmlabel;
  228. begin
  229. { calculate the operator which is more difficult }
  230. firstcomplex(self);
  231. cmpop:=false;
  232. if (torddef(left.resulttype.def).typ=bool8bit) or
  233. (torddef(right.resulttype.def).typ=bool8bit) then
  234. cgsize:=OS_8
  235. else
  236. if (torddef(left.resulttype.def).typ=bool16bit) or
  237. (torddef(right.resulttype.def).typ=bool16bit) then
  238. cgsize:=OS_16
  239. else
  240. cgsize:=OS_32;
  241. if (cs_full_boolean_eval in aktlocalswitches) or
  242. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  243. begin
  244. if left.nodetype in [ordconstn,realconstn] then
  245. swapleftright;
  246. isjump:=(left.expectloc=LOC_JUMP);
  247. if isjump then
  248. begin
  249. otl:=truelabel;
  250. objectlibrary.getlabel(truelabel);
  251. ofl:=falselabel;
  252. objectlibrary.getlabel(falselabel);
  253. end;
  254. secondpass(left);
  255. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  256. location_force_reg(exprasmlist,left.location,cgsize,false);
  257. if isjump then
  258. begin
  259. truelabel:=otl;
  260. falselabel:=ofl;
  261. end
  262. else if left.location.loc=LOC_JUMP then
  263. internalerror(2003122901);
  264. isjump:=(right.expectloc=LOC_JUMP);
  265. if isjump then
  266. begin
  267. otl:=truelabel;
  268. objectlibrary.getlabel(truelabel);
  269. ofl:=falselabel;
  270. objectlibrary.getlabel(falselabel);
  271. end;
  272. secondpass(right);
  273. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  274. location_force_reg(exprasmlist,right.location,cgsize,false);
  275. if isjump then
  276. begin
  277. truelabel:=otl;
  278. falselabel:=ofl;
  279. end
  280. else if right.location.loc=LOC_JUMP then
  281. internalerror(200312292);
  282. cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  283. { set result location }
  284. if not cmpop then
  285. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  286. else
  287. location_reset(location,LOC_FLAGS,OS_NO);
  288. load_left_right(cmpop,false);
  289. if (left.location.loc = LOC_CONSTANT) then
  290. swapleftright;
  291. { compare the }
  292. case nodetype of
  293. ltn,lten,gtn,gten,
  294. equaln,unequaln :
  295. begin
  296. if (right.location.loc <> LOC_CONSTANT) then
  297. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
  298. left.location.register,right.location.register))
  299. else
  300. exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
  301. left.location.register,longint(right.location.value)));
  302. location.resflags := getresflags;
  303. end;
  304. else
  305. begin
  306. case nodetype of
  307. xorn :
  308. cgop:=OP_XOR;
  309. orn :
  310. cgop:=OP_OR;
  311. andn :
  312. cgop:=OP_AND;
  313. else
  314. internalerror(200203247);
  315. end;
  316. if right.location.loc <> LOC_CONSTANT then
  317. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  318. left.location.register,right.location.register,
  319. location.register)
  320. else
  321. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  322. right.location.value,left.location.register,
  323. location.register);
  324. end;
  325. end;
  326. end
  327. else
  328. begin
  329. // just to make sure we free the right registers
  330. cmpop := true;
  331. case nodetype of
  332. andn,
  333. orn :
  334. begin
  335. location_reset(location,LOC_JUMP,OS_NO);
  336. case nodetype of
  337. andn :
  338. begin
  339. otl:=truelabel;
  340. objectlibrary.getlabel(truelabel);
  341. secondpass(left);
  342. maketojumpbool(exprasmlist,left,lr_load_regvars);
  343. cg.a_label(exprasmlist,truelabel);
  344. truelabel:=otl;
  345. end;
  346. orn :
  347. begin
  348. ofl:=falselabel;
  349. objectlibrary.getlabel(falselabel);
  350. secondpass(left);
  351. maketojumpbool(exprasmlist,left,lr_load_regvars);
  352. cg.a_label(exprasmlist,falselabel);
  353. falselabel:=ofl;
  354. end;
  355. else
  356. internalerror(200403181);
  357. end;
  358. secondpass(right);
  359. maketojumpbool(exprasmlist,right,lr_load_regvars);
  360. end;
  361. end;
  362. end;
  363. end;
  364. {*****************************************************************************
  365. AddFloat
  366. *****************************************************************************}
  367. procedure tppcaddnode.second_addfloat;
  368. var
  369. op : TAsmOp;
  370. cmpop : boolean;
  371. begin
  372. pass_left_and_right;
  373. cmpop:=false;
  374. case nodetype of
  375. addn :
  376. op:=A_FADD;
  377. muln :
  378. op:=A_FMUL;
  379. subn :
  380. op:=A_FSUB;
  381. slashn :
  382. op:=A_FDIV;
  383. ltn,lten,gtn,gten,
  384. equaln,unequaln :
  385. begin
  386. op:=A_FCMPO;
  387. cmpop:=true;
  388. end;
  389. else
  390. internalerror(200403182);
  391. end;
  392. // get the operands in the correct order, there are no special cases
  393. // here, everything is register-based
  394. if nf_swaped in flags then
  395. swapleftright;
  396. // put both operands in a register
  397. location_force_fpureg(exprasmlist,right.location,true);
  398. location_force_fpureg(exprasmlist,left.location,true);
  399. // initialize de result
  400. if not cmpop then
  401. begin
  402. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  403. if left.location.loc = LOC_FPUREGISTER then
  404. location.register := left.location.register
  405. else if right.location.loc = LOC_FPUREGISTER then
  406. location.register := right.location.register
  407. else
  408. location.register := cg.getfpuregister(exprasmlist,location.size);
  409. end
  410. else
  411. begin
  412. location_reset(location,LOC_FLAGS,OS_NO);
  413. location.resflags := getresflags;
  414. end;
  415. // emit the actual operation
  416. if not cmpop then
  417. begin
  418. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  419. location.register,left.location.register,
  420. right.location.register))
  421. end
  422. else
  423. begin
  424. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  425. newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
  426. end;
  427. end;
  428. {*****************************************************************************
  429. AddSmallSet
  430. *****************************************************************************}
  431. procedure tppcaddnode.second_addsmallset;
  432. var
  433. cgop : TOpCg;
  434. tmpreg : tregister;
  435. opdone,
  436. cmpop : boolean;
  437. begin
  438. pass_left_and_right;
  439. { when a setdef is passed, it has to be a smallset }
  440. if ((left.resulttype.def.deftype=setdef) and
  441. (tsetdef(left.resulttype.def).settype<>smallset)) or
  442. ((right.resulttype.def.deftype=setdef) and
  443. (tsetdef(right.resulttype.def).settype<>smallset)) then
  444. internalerror(200203301);
  445. opdone := false;
  446. cmpop:=nodetype in [equaln,unequaln,lten,gten];
  447. { set result location }
  448. if not cmpop then
  449. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  450. else
  451. location_reset(location,LOC_FLAGS,OS_NO);
  452. load_left_right(cmpop,false);
  453. if not(cmpop) and
  454. (location.register = NR_NO) then
  455. location.register := cg.getintregister(exprasmlist,OS_INT);
  456. case nodetype of
  457. addn :
  458. begin
  459. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  460. swapleftright;
  461. { are we adding set elements ? }
  462. if right.nodetype=setelementn then
  463. begin
  464. { no range support for smallsets! }
  465. if assigned(tsetelementnode(right).right) then
  466. internalerror(43244);
  467. if (right.location.loc = LOC_CONSTANT) then
  468. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  469. aint(aword(1) shl aword(right.location.value)),
  470. left.location.register,location.register)
  471. else
  472. begin
  473. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  474. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  475. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  476. right.location.register,tmpreg);
  477. if left.location.loc <> LOC_CONSTANT then
  478. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  479. left.location.register,location.register)
  480. else
  481. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  482. left.location.value,tmpreg,location.register);
  483. end;
  484. opdone := true;
  485. end
  486. else
  487. cgop := OP_OR;
  488. end;
  489. symdifn :
  490. cgop:=OP_XOR;
  491. muln :
  492. cgop:=OP_AND;
  493. subn :
  494. begin
  495. cgop:=OP_AND;
  496. if (not(nf_swaped in flags)) then
  497. if (right.location.loc=LOC_CONSTANT) then
  498. right.location.value := not(right.location.value)
  499. else
  500. opdone := true
  501. else if (left.location.loc=LOC_CONSTANT) then
  502. left.location.value := not(left.location.value)
  503. else
  504. begin
  505. swapleftright;
  506. opdone := true;
  507. end;
  508. if opdone then
  509. begin
  510. if left.location.loc = LOC_CONSTANT then
  511. begin
  512. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  513. cg.a_load_const_reg(exprasmlist,OS_INT,
  514. left.location.value,tmpreg);
  515. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  516. location.register,tmpreg,right.location.register));
  517. end
  518. else
  519. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  520. location.register,left.location.register,
  521. right.location.register));
  522. end;
  523. end;
  524. equaln,
  525. unequaln :
  526. begin
  527. emit_compare(true);
  528. opdone := true;
  529. end;
  530. lten,gten:
  531. begin
  532. If (not(nf_swaped in flags) and
  533. (nodetype = lten)) or
  534. ((nf_swaped in flags) and
  535. (nodetype = gten)) then
  536. swapleftright;
  537. // now we have to check whether left >= right
  538. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  539. if left.location.loc = LOC_CONSTANT then
  540. begin
  541. cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
  542. not(left.location.value),right.location.register,tmpreg);
  543. exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
  544. // the two instructions above should be folded together by
  545. // the peepholeoptimizer
  546. end
  547. else
  548. begin
  549. if right.location.loc = LOC_CONSTANT then
  550. begin
  551. cg.a_load_const_reg(exprasmlist,OS_INT,
  552. right.location.value,tmpreg);
  553. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  554. tmpreg,left.location.register));
  555. end
  556. else
  557. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  558. right.location.register,left.location.register));
  559. end;
  560. location.resflags.cr := RS_CR0;
  561. location.resflags.flag := F_EQ;
  562. opdone := true;
  563. end;
  564. else
  565. internalerror(2002072701);
  566. end;
  567. if not opdone then
  568. begin
  569. // these are all commutative operations
  570. if (left.location.loc = LOC_CONSTANT) then
  571. swapleftright;
  572. if (right.location.loc = LOC_CONSTANT) then
  573. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  574. right.location.value,left.location.register,
  575. location.register)
  576. else
  577. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  578. right.location.register,left.location.register,
  579. location.register);
  580. end;
  581. end;
  582. {*****************************************************************************
  583. Add64bit
  584. *****************************************************************************}
  585. procedure tppcaddnode.second_add64bit;
  586. var
  587. op : TOpCG;
  588. op1,op2 : TAsmOp;
  589. cmpop,
  590. unsigned : boolean;
  591. procedure emit_cmp64_hi;
  592. var
  593. oldleft, oldright: tlocation;
  594. begin
  595. // put the high part of the location in the low part
  596. location_copy(oldleft,left.location);
  597. location_copy(oldright,right.location);
  598. if left.location.loc = LOC_CONSTANT then
  599. left.location.value64 := left.location.value64 shr 32
  600. else
  601. left.location.register64.reglo := left.location.register64.reghi;
  602. if right.location.loc = LOC_CONSTANT then
  603. right.location.value64 := right.location.value64 shr 32
  604. else
  605. right.location.register64.reglo := right.location.register64.reghi;
  606. // and call the normal emit_compare
  607. emit_compare(unsigned);
  608. location_copy(left.location,oldleft);
  609. location_copy(right.location,oldright);
  610. end;
  611. procedure emit_cmp64_lo;
  612. begin
  613. emit_compare(true);
  614. end;
  615. procedure firstjmp64bitcmp;
  616. var
  617. oldnodetype: tnodetype;
  618. begin
  619. {$ifdef OLDREGVARS}
  620. load_all_regvars(exprasmlist);
  621. {$endif OLDREGVARS}
  622. { the jump the sequence is a little bit hairy }
  623. case nodetype of
  624. ltn,gtn:
  625. begin
  626. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  627. { cheat a little bit for the negative test }
  628. toggleflag(nf_swaped);
  629. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  630. toggleflag(nf_swaped);
  631. end;
  632. lten,gten:
  633. begin
  634. oldnodetype:=nodetype;
  635. if nodetype=lten then
  636. nodetype:=ltn
  637. else
  638. nodetype:=gtn;
  639. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  640. { cheat for the negative test }
  641. if nodetype=ltn then
  642. nodetype:=gtn
  643. else
  644. nodetype:=ltn;
  645. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  646. nodetype:=oldnodetype;
  647. end;
  648. equaln:
  649. begin
  650. nodetype := unequaln;
  651. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  652. nodetype := equaln;
  653. end;
  654. unequaln:
  655. begin
  656. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  657. end;
  658. end;
  659. end;
  660. procedure secondjmp64bitcmp;
  661. begin
  662. { the jump the sequence is a little bit hairy }
  663. case nodetype of
  664. ltn,gtn,lten,gten:
  665. begin
  666. { the comparison of the low dword always has }
  667. { to be always unsigned! }
  668. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  669. cg.a_jmp_always(exprasmlist,falselabel);
  670. end;
  671. equaln:
  672. begin
  673. nodetype := unequaln;
  674. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  675. cg.a_jmp_always(exprasmlist,truelabel);
  676. nodetype := equaln;
  677. end;
  678. unequaln:
  679. begin
  680. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  681. cg.a_jmp_always(exprasmlist,falselabel);
  682. end;
  683. end;
  684. end;
  685. var
  686. tempreg64: tregister64;
  687. begin
  688. firstcomplex(self);
  689. pass_left_and_right;
  690. cmpop:=false;
  691. unsigned:=((left.resulttype.def.deftype=orddef) and
  692. (torddef(left.resulttype.def).typ=u64bit)) or
  693. ((right.resulttype.def.deftype=orddef) and
  694. (torddef(right.resulttype.def).typ=u64bit));
  695. case nodetype of
  696. addn :
  697. begin
  698. op:=OP_ADD;
  699. end;
  700. subn :
  701. begin
  702. op:=OP_SUB;
  703. end;
  704. ltn,lten,
  705. gtn,gten,
  706. equaln,unequaln:
  707. begin
  708. op:=OP_NONE;
  709. cmpop:=true;
  710. end;
  711. xorn:
  712. op:=OP_XOR;
  713. orn:
  714. op:=OP_OR;
  715. andn:
  716. op:=OP_AND;
  717. muln:
  718. begin
  719. { should be handled in pass_1 (JM) }
  720. internalerror(200109051);
  721. end;
  722. else
  723. internalerror(2002072705);
  724. end;
  725. if not cmpop then
  726. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  727. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  728. (nodetype in [addn,subn]));
  729. if not(cs_check_overflow in aktlocalswitches) or
  730. not(nodetype in [addn,subn]) then
  731. begin
  732. case nodetype of
  733. ltn,lten,
  734. gtn,gten:
  735. begin
  736. emit_cmp64_hi;
  737. firstjmp64bitcmp;
  738. emit_cmp64_lo;
  739. secondjmp64bitcmp;
  740. end;
  741. equaln,unequaln:
  742. begin
  743. // instead of doing a complicated compare, do
  744. // (left.hi xor right.hi) or (left.lo xor right.lo)
  745. // (somewhate optimized so that no superfluous 'mr's are
  746. // generated)
  747. if (left.location.loc = LOC_CONSTANT) then
  748. swapleftright;
  749. if (right.location.loc = LOC_CONSTANT) then
  750. begin
  751. if left.location.loc = LOC_REGISTER then
  752. begin
  753. tempreg64.reglo := left.location.register64.reglo;
  754. tempreg64.reghi := left.location.register64.reghi;
  755. end
  756. else
  757. begin
  758. if (aint(right.location.value64) <> 0) then
  759. tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
  760. else
  761. tempreg64.reglo := left.location.register64.reglo;
  762. if ((right.location.value64 shr 32) <> 0) then
  763. tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
  764. else
  765. tempreg64.reghi := left.location.register64.reghi;
  766. end;
  767. if (aint(right.location.value64) <> 0) then
  768. { negative values can be handled using SUB, }
  769. { positive values < 65535 using XOR. }
  770. if (longint(right.location.value64) >= -32767) and
  771. (longint(right.location.value64) < 0) then
  772. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  773. aint(right.location.value64),
  774. left.location.register64.reglo,tempreg64.reglo)
  775. else
  776. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  777. aint(right.location.value64),
  778. left.location.register64.reglo,tempreg64.reglo);
  779. if ((right.location.value64 shr 32) <> 0) then
  780. if (longint(right.location.value64 shr 32) >= -32767) and
  781. (longint(right.location.value64 shr 32) < 0) then
  782. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  783. aint(right.location.value64 shr 32),
  784. left.location.register64.reghi,tempreg64.reghi)
  785. else
  786. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  787. aint(right.location.value64 shr 32),
  788. left.location.register64.reghi,tempreg64.reghi);
  789. end
  790. else
  791. begin
  792. tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
  793. tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
  794. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,location.size,
  795. left.location.register64,right.location.register64,
  796. tempreg64);
  797. end;
  798. cg.a_reg_alloc(exprasmlist,NR_R0);
  799. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
  800. tempreg64.reglo,tempreg64.reghi));
  801. cg.a_reg_dealloc(exprasmlist,NR_R0);
  802. location_reset(location,LOC_FLAGS,OS_NO);
  803. location.resflags := getresflags;
  804. end;
  805. xorn,orn,andn,addn:
  806. begin
  807. if (location.register64.reglo = NR_NO) then
  808. begin
  809. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  810. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  811. end;
  812. if (left.location.loc = LOC_CONSTANT) then
  813. swapleftright;
  814. if (right.location.loc = LOC_CONSTANT) then
  815. cg64.a_op64_const_reg_reg(exprasmlist,op,location.size,right.location.value64,
  816. left.location.register64,location.register64)
  817. else
  818. cg64.a_op64_reg_reg_reg(exprasmlist,op,location.size,right.location.register64,
  819. left.location.register64,location.register64);
  820. end;
  821. subn:
  822. begin
  823. if (nf_swaped in flags) then
  824. swapleftright;
  825. if left.location.loc <> LOC_CONSTANT then
  826. begin
  827. if (location.register64.reglo = NR_NO) then
  828. begin
  829. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  830. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  831. end;
  832. if right.location.loc <> LOC_CONSTANT then
  833. // reg64 - reg64
  834. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,location.size,
  835. right.location.register64,left.location.register64,
  836. location.register64)
  837. else
  838. // reg64 - const64
  839. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,location.size,
  840. right.location.value64,left.location.register64,
  841. location.register64)
  842. end
  843. else if ((left.location.value64 shr 32) = 0) then
  844. begin
  845. if (location.register64.reglo = NR_NO) then
  846. begin
  847. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  848. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  849. end;
  850. if (int64(left.location.value64) >= low(smallint)) and
  851. (int64(left.location.value64) <= high(smallint)) then
  852. begin
  853. // consts16 - reg64
  854. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  855. location.register64.reglo,right.location.register64.reglo,
  856. left.location.value));
  857. end
  858. else
  859. begin
  860. // const32 - reg64
  861. location_force_reg(exprasmlist,left.location,
  862. OS_32,true);
  863. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
  864. location.register64.reglo,left.location.register64.reglo,
  865. right.location.register64.reglo));
  866. end;
  867. exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
  868. location.register64.reghi,right.location.register64.reghi));
  869. end
  870. else if (aint(left.location.value64) = 0) then
  871. begin
  872. // (const32 shl 32) - reg64
  873. if (location.register64.reglo = NR_NO) then
  874. begin
  875. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  876. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  877. end;
  878. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  879. location.register64.reglo,right.location.register64.reglo,0));
  880. left.location.value64 := left.location.value64 shr 32;
  881. location_force_reg(exprasmlist,left.location,OS_32,true);
  882. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
  883. location.register64.reghi,right.location.register64.reghi,
  884. left.location.register));
  885. end
  886. else
  887. begin
  888. // const64 - reg64
  889. location_force_reg(exprasmlist,left.location,
  890. def_cgsize(left.resulttype.def),false);
  891. if (left.location.loc = LOC_REGISTER) then
  892. location.register64 := left.location.register64
  893. else if (location.register64.reglo = NR_NO) then
  894. begin
  895. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  896. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  897. end;
  898. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,location.size,
  899. right.location.register64,left.location.register64,
  900. location.register64);
  901. end;
  902. end;
  903. else
  904. internalerror(2002072803);
  905. end;
  906. end
  907. else
  908. begin
  909. if is_signed(resulttype.def) then
  910. begin
  911. case nodetype of
  912. addn:
  913. begin
  914. op1 := A_ADDC;
  915. op2 := A_ADDEO;
  916. end;
  917. subn:
  918. begin
  919. op1 := A_SUBC;
  920. op2 := A_SUBFEO;
  921. end;
  922. else
  923. internalerror(2002072806);
  924. end
  925. end
  926. else
  927. begin
  928. case nodetype of
  929. addn:
  930. begin
  931. op1 := A_ADDC;
  932. op2 := A_ADDE;
  933. end;
  934. subn:
  935. begin
  936. op1 := A_SUBC;
  937. op2 := A_SUBFE;
  938. end;
  939. end;
  940. end;
  941. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.register64.reglo,
  942. left.location.register64.reglo,right.location.register64.reglo));
  943. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.register64.reghi,
  944. right.location.register64.reghi,left.location.register64.reghi));
  945. if not(is_signed(resulttype.def)) then
  946. if nodetype = addn then
  947. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register64.reghi,left.location.register64.reghi))
  948. else
  949. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register64.reghi,location.register64.reghi));
  950. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  951. end;
  952. { set result location }
  953. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  954. { real location only now) (JM) }
  955. if cmpop and
  956. not(nodetype in [equaln,unequaln]) then
  957. location_reset(location,LOC_JUMP,OS_NO);
  958. end;
  959. {*****************************************************************************
  960. AddMMX
  961. *****************************************************************************}
  962. {$ifdef SUPPORT_MMX}
  963. procedure ti386addnode.second_addmmx;
  964. var
  965. op : TAsmOp;
  966. cmpop : boolean;
  967. mmxbase : tmmxtype;
  968. hregister : tregister;
  969. begin
  970. pass_left_and_right;
  971. cmpop:=false;
  972. mmxbase:=mmx_type(left.resulttype.def);
  973. case nodetype of
  974. addn :
  975. begin
  976. if (cs_mmx_saturation in aktlocalswitches) then
  977. begin
  978. case mmxbase of
  979. mmxs8bit:
  980. op:=A_PADDSB;
  981. mmxu8bit:
  982. op:=A_PADDUSB;
  983. mmxs16bit,mmxfixed16:
  984. op:=A_PADDSB;
  985. mmxu16bit:
  986. op:=A_PADDUSW;
  987. end;
  988. end
  989. else
  990. begin
  991. case mmxbase of
  992. mmxs8bit,mmxu8bit:
  993. op:=A_PADDB;
  994. mmxs16bit,mmxu16bit,mmxfixed16:
  995. op:=A_PADDW;
  996. mmxs32bit,mmxu32bit:
  997. op:=A_PADDD;
  998. end;
  999. end;
  1000. end;
  1001. muln :
  1002. begin
  1003. case mmxbase of
  1004. mmxs16bit,mmxu16bit:
  1005. op:=A_PMULLW;
  1006. mmxfixed16:
  1007. op:=A_PMULHW;
  1008. end;
  1009. end;
  1010. subn :
  1011. begin
  1012. if (cs_mmx_saturation in aktlocalswitches) then
  1013. begin
  1014. case mmxbase of
  1015. mmxs8bit:
  1016. op:=A_PSUBSB;
  1017. mmxu8bit:
  1018. op:=A_PSUBUSB;
  1019. mmxs16bit,mmxfixed16:
  1020. op:=A_PSUBSB;
  1021. mmxu16bit:
  1022. op:=A_PSUBUSW;
  1023. end;
  1024. end
  1025. else
  1026. begin
  1027. case mmxbase of
  1028. mmxs8bit,mmxu8bit:
  1029. op:=A_PSUBB;
  1030. mmxs16bit,mmxu16bit,mmxfixed16:
  1031. op:=A_PSUBW;
  1032. mmxs32bit,mmxu32bit:
  1033. op:=A_PSUBD;
  1034. end;
  1035. end;
  1036. end;
  1037. xorn:
  1038. op:=A_PXOR;
  1039. orn:
  1040. op:=A_POR;
  1041. andn:
  1042. op:=A_PAND;
  1043. else
  1044. internalerror(200403183);
  1045. end;
  1046. { left and right no register? }
  1047. { then one must be demanded }
  1048. if (left.location.loc<>LOC_MMXREGISTER) then
  1049. begin
  1050. if (right.location.loc=LOC_MMXREGISTER) then
  1051. begin
  1052. location_swap(left.location,right.location);
  1053. toggleflag(nf_swaped);
  1054. end
  1055. else
  1056. begin
  1057. { register variable ? }
  1058. if (left.location.loc=LOC_CMMXREGISTER) then
  1059. begin
  1060. hregister:=rg.getregistermm(exprasmlist);
  1061. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1062. end
  1063. else
  1064. begin
  1065. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1066. internalerror(200203245);
  1067. location_release(exprasmlist,left.location);
  1068. hregister:=rg.getregistermm(exprasmlist);
  1069. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1070. end;
  1071. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1072. left.location.register:=hregister;
  1073. end;
  1074. end;
  1075. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1076. if right.location.loc<>LOC_MMXREGISTER then
  1077. begin
  1078. if (nodetype=subn) and (nf_swaped in flags) then
  1079. begin
  1080. if right.location.loc=LOC_CMMXREGISTER then
  1081. begin
  1082. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1083. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1084. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1085. end
  1086. else
  1087. begin
  1088. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1089. internalerror(200203247);
  1090. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  1091. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1092. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1093. location_release(exprasmlist,right.location);
  1094. end;
  1095. end
  1096. else
  1097. begin
  1098. if (right.location.loc=LOC_CMMXREGISTER) then
  1099. begin
  1100. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1101. end
  1102. else
  1103. begin
  1104. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1105. internalerror(200203246);
  1106. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1107. location_release(exprasmlist,right.location);
  1108. end;
  1109. end;
  1110. end
  1111. else
  1112. begin
  1113. { right.location=LOC_MMXREGISTER }
  1114. if (nodetype=subn) and (nf_swaped in flags) then
  1115. begin
  1116. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1117. location_swap(left.location,right.location);
  1118. toggleflag(nf_swaped);
  1119. end
  1120. else
  1121. begin
  1122. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1123. end;
  1124. end;
  1125. location_freetemp(exprasmlist,right.location);
  1126. location_release(exprasmlist,right.location);
  1127. if cmpop then
  1128. begin
  1129. location_freetemp(exprasmlist,left.location);
  1130. location_release(exprasmlist,left.location);
  1131. end;
  1132. set_result_location(cmpop,true);
  1133. end;
  1134. {$endif SUPPORT_MMX}
  1135. {*****************************************************************************
  1136. pass_2
  1137. *****************************************************************************}
  1138. procedure tppcaddnode.pass_2;
  1139. { is also being used for xor, and "mul", "sub, or and comparative }
  1140. { operators }
  1141. var
  1142. cgop : topcg;
  1143. op : tasmop;
  1144. tmpreg : tregister;
  1145. hl : tasmlabel;
  1146. cmpop : boolean;
  1147. { true, if unsigned types are compared }
  1148. unsigned : boolean;
  1149. begin
  1150. { to make it more readable, string and set (not smallset!) have their
  1151. own procedures }
  1152. case left.resulttype.def.deftype of
  1153. orddef :
  1154. begin
  1155. { handling boolean expressions }
  1156. if is_boolean(left.resulttype.def) and
  1157. is_boolean(right.resulttype.def) then
  1158. begin
  1159. second_addboolean;
  1160. exit;
  1161. end
  1162. { 64bit operations }
  1163. else if is_64bit(left.resulttype.def) then
  1164. begin
  1165. second_add64bit;
  1166. exit;
  1167. end;
  1168. end;
  1169. stringdef :
  1170. begin
  1171. internalerror(2002072402);
  1172. exit;
  1173. end;
  1174. setdef :
  1175. begin
  1176. { normalsets are already handled in pass1 }
  1177. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1178. internalerror(200109041);
  1179. second_addsmallset;
  1180. exit;
  1181. end;
  1182. arraydef :
  1183. begin
  1184. {$ifdef SUPPORT_MMX}
  1185. if is_mmx_able_array(left.resulttype.def) then
  1186. begin
  1187. second_addmmx;
  1188. exit;
  1189. end;
  1190. {$endif SUPPORT_MMX}
  1191. end;
  1192. floatdef :
  1193. begin
  1194. second_addfloat;
  1195. exit;
  1196. end;
  1197. end;
  1198. { defaults }
  1199. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1200. unsigned:=not(is_signed(left.resulttype.def)) or
  1201. not(is_signed(right.resulttype.def));
  1202. pass_left_and_right;
  1203. { Convert flags to register first }
  1204. { can any of these things be in the flags actually?? (JM) }
  1205. if (left.location.loc = LOC_FLAGS) or
  1206. (right.location.loc = LOC_FLAGS) then
  1207. internalerror(2002072602);
  1208. { set result location }
  1209. if not cmpop then
  1210. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1211. else
  1212. location_reset(location,LOC_FLAGS,OS_NO);
  1213. load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
  1214. (nodetype in [addn,subn,muln]));
  1215. if (location.register = NR_NO) and
  1216. not(cmpop) then
  1217. location.register := cg.getintregister(exprasmlist,OS_INT);
  1218. if not(cs_check_overflow in aktlocalswitches) or
  1219. (cmpop) or
  1220. (nodetype in [orn,andn,xorn]) then
  1221. begin
  1222. case nodetype of
  1223. addn, muln, xorn, orn, andn:
  1224. begin
  1225. case nodetype of
  1226. addn:
  1227. cgop := OP_ADD;
  1228. muln:
  1229. if unsigned then
  1230. cgop := OP_MUL
  1231. else
  1232. cgop := OP_IMUL;
  1233. xorn:
  1234. cgop := OP_XOR;
  1235. orn:
  1236. cgop := OP_OR;
  1237. andn:
  1238. cgop := OP_AND;
  1239. end;
  1240. if (left.location.loc = LOC_CONSTANT) then
  1241. swapleftright;
  1242. if (right.location.loc <> LOC_CONSTANT) then
  1243. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  1244. left.location.register,right.location.register,
  1245. location.register)
  1246. else
  1247. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  1248. right.location.value,left.location.register,
  1249. location.register);
  1250. end;
  1251. subn:
  1252. begin
  1253. if (nf_swaped in flags) then
  1254. swapleftright;
  1255. if left.location.loc <> LOC_CONSTANT then
  1256. if right.location.loc <> LOC_CONSTANT then
  1257. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1258. right.location.register,left.location.register,
  1259. location.register)
  1260. else
  1261. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1262. right.location.value,left.location.register,
  1263. location.register)
  1264. else
  1265. if (longint(left.location.value) >= low(smallint)) and
  1266. (longint(left.location.value) <= high(smallint)) then
  1267. begin
  1268. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  1269. location.register,right.location.register,
  1270. longint(left.location.value)));
  1271. end
  1272. else
  1273. begin
  1274. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  1275. cg.a_load_const_reg(exprasmlist,OS_INT,
  1276. left.location.value,tmpreg);
  1277. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1278. right.location.register,tmpreg,location.register);
  1279. end;
  1280. end;
  1281. ltn,lten,gtn,gten,equaln,unequaln :
  1282. begin
  1283. emit_compare(unsigned);
  1284. end;
  1285. end;
  1286. end
  1287. else
  1288. // overflow checking is on and we have an addn, subn or muln
  1289. begin
  1290. if is_signed(resulttype.def) then
  1291. begin
  1292. case nodetype of
  1293. addn:
  1294. op := A_ADDO;
  1295. subn:
  1296. begin
  1297. op := A_SUBO;
  1298. if (nf_swaped in flags) then
  1299. swapleftright;
  1300. end;
  1301. muln:
  1302. op := A_MULLWO;
  1303. else
  1304. internalerror(2002072601);
  1305. end;
  1306. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1307. left.location.register,right.location.register));
  1308. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1309. end
  1310. else
  1311. begin
  1312. case nodetype of
  1313. addn:
  1314. begin
  1315. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
  1316. left.location.register,right.location.register));
  1317. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
  1318. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1319. end;
  1320. subn:
  1321. begin
  1322. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
  1323. left.location.register,right.location.register));
  1324. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
  1325. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1326. end;
  1327. muln:
  1328. begin
  1329. { calculate the upper 32 bits of the product, = 0 if no overflow }
  1330. cg.a_reg_alloc(exprasmlist,NR_R0);
  1331. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,NR_R0,
  1332. left.location.register,right.location.register));
  1333. cg.a_reg_dealloc(exprasmlist,NR_R0);
  1334. { calculate the real result }
  1335. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
  1336. left.location.register,right.location.register));
  1337. { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
  1338. objectlibrary.getlabel(hl);
  1339. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
  1340. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  1341. cg.a_label(exprasmlist,hl);
  1342. end;
  1343. end;
  1344. end;
  1345. end;
  1346. end;
  1347. begin
  1348. caddnode:=tppcaddnode;
  1349. end.
  1350. {
  1351. $Log$
  1352. Revision 1.57 2005-02-14 17:13:10 peter
  1353. * truncate log
  1354. Revision 1.56 2005/02/13 18:55:19 florian
  1355. + overflow checking for the arm
  1356. }