nppcadd.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501
  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. hl4 : tasmlabel;
  590. cmpop,
  591. unsigned : boolean;
  592. r : Tregister;
  593. procedure emit_cmp64_hi;
  594. var
  595. oldleft, oldright: tlocation;
  596. begin
  597. // put the high part of the location in the low part
  598. location_copy(oldleft,left.location);
  599. location_copy(oldright,right.location);
  600. if left.location.loc = LOC_CONSTANT then
  601. left.location.value64 := left.location.value64 shr 32
  602. else
  603. left.location.register64.reglo := left.location.register64.reghi;
  604. if right.location.loc = LOC_CONSTANT then
  605. right.location.value64 := right.location.value64 shr 32
  606. else
  607. right.location.register64.reglo := right.location.register64.reghi;
  608. // and call the normal emit_compare
  609. emit_compare(unsigned);
  610. location_copy(left.location,oldleft);
  611. location_copy(right.location,oldright);
  612. end;
  613. procedure emit_cmp64_lo;
  614. begin
  615. emit_compare(true);
  616. end;
  617. procedure firstjmp64bitcmp;
  618. var
  619. oldnodetype: tnodetype;
  620. begin
  621. {$ifdef OLDREGVARS}
  622. load_all_regvars(exprasmlist);
  623. {$endif OLDREGVARS}
  624. { the jump the sequence is a little bit hairy }
  625. case nodetype of
  626. ltn,gtn:
  627. begin
  628. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  629. { cheat a little bit for the negative test }
  630. toggleflag(nf_swaped);
  631. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  632. toggleflag(nf_swaped);
  633. end;
  634. lten,gten:
  635. begin
  636. oldnodetype:=nodetype;
  637. if nodetype=lten then
  638. nodetype:=ltn
  639. else
  640. nodetype:=gtn;
  641. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  642. { cheat for the negative test }
  643. if nodetype=ltn then
  644. nodetype:=gtn
  645. else
  646. nodetype:=ltn;
  647. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  648. nodetype:=oldnodetype;
  649. end;
  650. equaln:
  651. begin
  652. nodetype := unequaln;
  653. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  654. nodetype := equaln;
  655. end;
  656. unequaln:
  657. begin
  658. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  659. end;
  660. end;
  661. end;
  662. procedure secondjmp64bitcmp;
  663. begin
  664. { the jump the sequence is a little bit hairy }
  665. case nodetype of
  666. ltn,gtn,lten,gten:
  667. begin
  668. { the comparison of the low dword always has }
  669. { to be always unsigned! }
  670. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  671. cg.a_jmp_always(exprasmlist,falselabel);
  672. end;
  673. equaln:
  674. begin
  675. nodetype := unequaln;
  676. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  677. cg.a_jmp_always(exprasmlist,truelabel);
  678. nodetype := equaln;
  679. end;
  680. unequaln:
  681. begin
  682. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  683. cg.a_jmp_always(exprasmlist,falselabel);
  684. end;
  685. end;
  686. end;
  687. var
  688. tempreg64: tregister64;
  689. begin
  690. firstcomplex(self);
  691. pass_left_and_right;
  692. cmpop:=false;
  693. unsigned:=((left.resulttype.def.deftype=orddef) and
  694. (torddef(left.resulttype.def).typ=u64bit)) or
  695. ((right.resulttype.def.deftype=orddef) and
  696. (torddef(right.resulttype.def).typ=u64bit));
  697. case nodetype of
  698. addn :
  699. begin
  700. op:=OP_ADD;
  701. end;
  702. subn :
  703. begin
  704. op:=OP_SUB;
  705. end;
  706. ltn,lten,
  707. gtn,gten,
  708. equaln,unequaln:
  709. begin
  710. op:=OP_NONE;
  711. cmpop:=true;
  712. end;
  713. xorn:
  714. op:=OP_XOR;
  715. orn:
  716. op:=OP_OR;
  717. andn:
  718. op:=OP_AND;
  719. muln:
  720. begin
  721. { should be handled in pass_1 (JM) }
  722. internalerror(200109051);
  723. end;
  724. else
  725. internalerror(2002072705);
  726. end;
  727. if not cmpop then
  728. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  729. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  730. (nodetype in [addn,subn]));
  731. if not(cs_check_overflow in aktlocalswitches) or
  732. not(nodetype in [addn,subn]) then
  733. begin
  734. case nodetype of
  735. ltn,lten,
  736. gtn,gten:
  737. begin
  738. emit_cmp64_hi;
  739. firstjmp64bitcmp;
  740. emit_cmp64_lo;
  741. secondjmp64bitcmp;
  742. end;
  743. equaln,unequaln:
  744. begin
  745. // instead of doing a complicated compare, do
  746. // (left.hi xor right.hi) or (left.lo xor right.lo)
  747. // (somewhate optimized so that no superfluous 'mr's are
  748. // generated)
  749. if (left.location.loc = LOC_CONSTANT) then
  750. swapleftright;
  751. if (right.location.loc = LOC_CONSTANT) then
  752. begin
  753. if left.location.loc = LOC_REGISTER then
  754. begin
  755. tempreg64.reglo := left.location.register64.reglo;
  756. tempreg64.reghi := left.location.register64.reghi;
  757. end
  758. else
  759. begin
  760. if (aint(right.location.value64) <> 0) then
  761. tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
  762. else
  763. tempreg64.reglo := left.location.register64.reglo;
  764. if ((right.location.value64 shr 32) <> 0) then
  765. tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
  766. else
  767. tempreg64.reghi := left.location.register64.reghi;
  768. end;
  769. if (aint(right.location.value64) <> 0) then
  770. { negative values can be handled using SUB, }
  771. { positive values < 65535 using XOR. }
  772. if (longint(right.location.value64) >= -32767) and
  773. (longint(right.location.value64) < 0) then
  774. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  775. aint(right.location.value64),
  776. left.location.register64.reglo,tempreg64.reglo)
  777. else
  778. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  779. aint(right.location.value64),
  780. left.location.register64.reglo,tempreg64.reglo);
  781. if ((right.location.value64 shr 32) <> 0) then
  782. if (longint(right.location.value64 shr 32) >= -32767) and
  783. (longint(right.location.value64 shr 32) < 0) then
  784. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  785. aint(right.location.value64 shr 32),
  786. left.location.register64.reghi,tempreg64.reghi)
  787. else
  788. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  789. aint(right.location.value64 shr 32),
  790. left.location.register64.reghi,tempreg64.reghi);
  791. end
  792. else
  793. begin
  794. tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
  795. tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
  796. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
  797. left.location.register64,right.location.register64,
  798. tempreg64);
  799. end;
  800. cg.a_reg_alloc(exprasmlist,NR_R0);
  801. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
  802. tempreg64.reglo,tempreg64.reghi));
  803. cg.a_reg_dealloc(exprasmlist,NR_R0);
  804. location_reset(location,LOC_FLAGS,OS_NO);
  805. location.resflags := getresflags;
  806. end;
  807. xorn,orn,andn,addn:
  808. begin
  809. if (location.register64.reglo = NR_NO) then
  810. begin
  811. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  812. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  813. end;
  814. if (left.location.loc = LOC_CONSTANT) then
  815. swapleftright;
  816. if (right.location.loc = LOC_CONSTANT) then
  817. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.value64,
  818. left.location.register64,location.register64)
  819. else
  820. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  821. left.location.register64,location.register64);
  822. end;
  823. subn:
  824. begin
  825. if (nf_swaped in flags) then
  826. swapleftright;
  827. if left.location.loc <> LOC_CONSTANT then
  828. begin
  829. if (location.register64.reglo = NR_NO) then
  830. begin
  831. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  832. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  833. end;
  834. if right.location.loc <> LOC_CONSTANT then
  835. // reg64 - reg64
  836. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  837. right.location.register64,left.location.register64,
  838. location.register64)
  839. else
  840. // reg64 - const64
  841. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  842. right.location.value64,left.location.register64,
  843. location.register64)
  844. end
  845. else if ((left.location.value64 shr 32) = 0) then
  846. begin
  847. if (location.register64.reglo = NR_NO) then
  848. begin
  849. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  850. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  851. end;
  852. if (int64(left.location.value64) >= low(smallint)) and
  853. (int64(left.location.value64) <= high(smallint)) then
  854. begin
  855. // consts16 - reg64
  856. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  857. location.register64.reglo,right.location.register64.reglo,
  858. left.location.value));
  859. end
  860. else
  861. begin
  862. // const32 - reg64
  863. location_force_reg(exprasmlist,left.location,
  864. OS_32,true);
  865. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
  866. location.register64.reglo,left.location.register64.reglo,
  867. right.location.register64.reglo));
  868. end;
  869. exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
  870. location.register64.reghi,right.location.register64.reghi));
  871. end
  872. else if (aint(left.location.value64) = 0) then
  873. begin
  874. // (const32 shl 32) - reg64
  875. if (location.register64.reglo = NR_NO) then
  876. begin
  877. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  878. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  879. end;
  880. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  881. location.register64.reglo,right.location.register64.reglo,0));
  882. left.location.value64 := left.location.value64 shr 32;
  883. location_force_reg(exprasmlist,left.location,OS_32,true);
  884. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
  885. location.register64.reghi,right.location.register64.reghi,
  886. left.location.register));
  887. end
  888. else
  889. begin
  890. // const64 - reg64
  891. location_force_reg(exprasmlist,left.location,
  892. def_cgsize(left.resulttype.def),false);
  893. if (left.location.loc = LOC_REGISTER) then
  894. location.register64 := left.location.register64
  895. else if (location.register64.reglo = NR_NO) then
  896. begin
  897. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  898. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  899. end;
  900. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  901. right.location.register64,left.location.register64,
  902. location.register64);
  903. end;
  904. end;
  905. else
  906. internalerror(2002072803);
  907. end;
  908. end
  909. else
  910. begin
  911. if is_signed(resulttype.def) then
  912. begin
  913. case nodetype of
  914. addn:
  915. begin
  916. op1 := A_ADDC;
  917. op2 := A_ADDEO;
  918. end;
  919. subn:
  920. begin
  921. op1 := A_SUBC;
  922. op2 := A_SUBFEO;
  923. end;
  924. else
  925. internalerror(2002072806);
  926. end
  927. end
  928. else
  929. begin
  930. case nodetype of
  931. addn:
  932. begin
  933. op1 := A_ADDC;
  934. op2 := A_ADDE;
  935. end;
  936. subn:
  937. begin
  938. op1 := A_SUBC;
  939. op2 := A_SUBFE;
  940. end;
  941. end;
  942. end;
  943. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.register64.reglo,
  944. left.location.register64.reglo,right.location.register64.reglo));
  945. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.register64.reghi,
  946. right.location.register64.reghi,left.location.register64.reghi));
  947. if not(is_signed(resulttype.def)) then
  948. if nodetype = addn then
  949. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register64.reghi,left.location.register64.reghi))
  950. else
  951. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register64.reghi,location.register64.reghi));
  952. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  953. end;
  954. { set result location }
  955. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  956. { real location only now) (JM) }
  957. if cmpop and
  958. not(nodetype in [equaln,unequaln]) then
  959. location_reset(location,LOC_JUMP,OS_NO);
  960. end;
  961. {*****************************************************************************
  962. AddMMX
  963. *****************************************************************************}
  964. {$ifdef SUPPORT_MMX}
  965. procedure ti386addnode.second_addmmx;
  966. var
  967. op : TAsmOp;
  968. cmpop : boolean;
  969. mmxbase : tmmxtype;
  970. hregister : tregister;
  971. begin
  972. pass_left_and_right;
  973. cmpop:=false;
  974. mmxbase:=mmx_type(left.resulttype.def);
  975. case nodetype of
  976. addn :
  977. begin
  978. if (cs_mmx_saturation in aktlocalswitches) then
  979. begin
  980. case mmxbase of
  981. mmxs8bit:
  982. op:=A_PADDSB;
  983. mmxu8bit:
  984. op:=A_PADDUSB;
  985. mmxs16bit,mmxfixed16:
  986. op:=A_PADDSB;
  987. mmxu16bit:
  988. op:=A_PADDUSW;
  989. end;
  990. end
  991. else
  992. begin
  993. case mmxbase of
  994. mmxs8bit,mmxu8bit:
  995. op:=A_PADDB;
  996. mmxs16bit,mmxu16bit,mmxfixed16:
  997. op:=A_PADDW;
  998. mmxs32bit,mmxu32bit:
  999. op:=A_PADDD;
  1000. end;
  1001. end;
  1002. end;
  1003. muln :
  1004. begin
  1005. case mmxbase of
  1006. mmxs16bit,mmxu16bit:
  1007. op:=A_PMULLW;
  1008. mmxfixed16:
  1009. op:=A_PMULHW;
  1010. end;
  1011. end;
  1012. subn :
  1013. begin
  1014. if (cs_mmx_saturation in aktlocalswitches) then
  1015. begin
  1016. case mmxbase of
  1017. mmxs8bit:
  1018. op:=A_PSUBSB;
  1019. mmxu8bit:
  1020. op:=A_PSUBUSB;
  1021. mmxs16bit,mmxfixed16:
  1022. op:=A_PSUBSB;
  1023. mmxu16bit:
  1024. op:=A_PSUBUSW;
  1025. end;
  1026. end
  1027. else
  1028. begin
  1029. case mmxbase of
  1030. mmxs8bit,mmxu8bit:
  1031. op:=A_PSUBB;
  1032. mmxs16bit,mmxu16bit,mmxfixed16:
  1033. op:=A_PSUBW;
  1034. mmxs32bit,mmxu32bit:
  1035. op:=A_PSUBD;
  1036. end;
  1037. end;
  1038. end;
  1039. xorn:
  1040. op:=A_PXOR;
  1041. orn:
  1042. op:=A_POR;
  1043. andn:
  1044. op:=A_PAND;
  1045. else
  1046. internalerror(200403183);
  1047. end;
  1048. { left and right no register? }
  1049. { then one must be demanded }
  1050. if (left.location.loc<>LOC_MMXREGISTER) then
  1051. begin
  1052. if (right.location.loc=LOC_MMXREGISTER) then
  1053. begin
  1054. location_swap(left.location,right.location);
  1055. toggleflag(nf_swaped);
  1056. end
  1057. else
  1058. begin
  1059. { register variable ? }
  1060. if (left.location.loc=LOC_CMMXREGISTER) then
  1061. begin
  1062. hregister:=rg.getregistermm(exprasmlist);
  1063. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1064. end
  1065. else
  1066. begin
  1067. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1068. internalerror(200203245);
  1069. location_release(exprasmlist,left.location);
  1070. hregister:=rg.getregistermm(exprasmlist);
  1071. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1072. end;
  1073. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1074. left.location.register:=hregister;
  1075. end;
  1076. end;
  1077. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1078. if right.location.loc<>LOC_MMXREGISTER then
  1079. begin
  1080. if (nodetype=subn) and (nf_swaped in flags) then
  1081. begin
  1082. if right.location.loc=LOC_CMMXREGISTER then
  1083. begin
  1084. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1085. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1086. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1087. end
  1088. else
  1089. begin
  1090. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1091. internalerror(200203247);
  1092. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  1093. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1094. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1095. location_release(exprasmlist,right.location);
  1096. end;
  1097. end
  1098. else
  1099. begin
  1100. if (right.location.loc=LOC_CMMXREGISTER) then
  1101. begin
  1102. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1103. end
  1104. else
  1105. begin
  1106. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1107. internalerror(200203246);
  1108. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1109. location_release(exprasmlist,right.location);
  1110. end;
  1111. end;
  1112. end
  1113. else
  1114. begin
  1115. { right.location=LOC_MMXREGISTER }
  1116. if (nodetype=subn) and (nf_swaped in flags) then
  1117. begin
  1118. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1119. location_swap(left.location,right.location);
  1120. toggleflag(nf_swaped);
  1121. end
  1122. else
  1123. begin
  1124. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1125. end;
  1126. end;
  1127. location_freetemp(exprasmlist,right.location);
  1128. location_release(exprasmlist,right.location);
  1129. if cmpop then
  1130. begin
  1131. location_freetemp(exprasmlist,left.location);
  1132. location_release(exprasmlist,left.location);
  1133. end;
  1134. set_result_location(cmpop,true);
  1135. end;
  1136. {$endif SUPPORT_MMX}
  1137. {*****************************************************************************
  1138. pass_2
  1139. *****************************************************************************}
  1140. procedure tppcaddnode.pass_2;
  1141. { is also being used for xor, and "mul", "sub, or and comparative }
  1142. { operators }
  1143. var
  1144. cgop : topcg;
  1145. op : tasmop;
  1146. tmpreg : tregister;
  1147. hl : tasmlabel;
  1148. cmpop : boolean;
  1149. { true, if unsigned types are compared }
  1150. unsigned : boolean;
  1151. begin
  1152. { to make it more readable, string and set (not smallset!) have their
  1153. own procedures }
  1154. case left.resulttype.def.deftype of
  1155. orddef :
  1156. begin
  1157. { handling boolean expressions }
  1158. if is_boolean(left.resulttype.def) and
  1159. is_boolean(right.resulttype.def) then
  1160. begin
  1161. second_addboolean;
  1162. exit;
  1163. end
  1164. { 64bit operations }
  1165. else if is_64bit(left.resulttype.def) then
  1166. begin
  1167. second_add64bit;
  1168. exit;
  1169. end;
  1170. end;
  1171. stringdef :
  1172. begin
  1173. internalerror(2002072402);
  1174. exit;
  1175. end;
  1176. setdef :
  1177. begin
  1178. { normalsets are already handled in pass1 }
  1179. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1180. internalerror(200109041);
  1181. second_addsmallset;
  1182. exit;
  1183. end;
  1184. arraydef :
  1185. begin
  1186. {$ifdef SUPPORT_MMX}
  1187. if is_mmx_able_array(left.resulttype.def) then
  1188. begin
  1189. second_addmmx;
  1190. exit;
  1191. end;
  1192. {$endif SUPPORT_MMX}
  1193. end;
  1194. floatdef :
  1195. begin
  1196. second_addfloat;
  1197. exit;
  1198. end;
  1199. end;
  1200. { defaults }
  1201. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1202. unsigned:=not(is_signed(left.resulttype.def)) or
  1203. not(is_signed(right.resulttype.def));
  1204. pass_left_and_right;
  1205. { Convert flags to register first }
  1206. { can any of these things be in the flags actually?? (JM) }
  1207. if (left.location.loc = LOC_FLAGS) or
  1208. (right.location.loc = LOC_FLAGS) then
  1209. internalerror(2002072602);
  1210. { set result location }
  1211. if not cmpop then
  1212. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1213. else
  1214. location_reset(location,LOC_FLAGS,OS_NO);
  1215. load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
  1216. (nodetype in [addn,subn,muln]));
  1217. if (location.register = NR_NO) and
  1218. not(cmpop) then
  1219. location.register := cg.getintregister(exprasmlist,OS_INT);
  1220. if not(cs_check_overflow in aktlocalswitches) or
  1221. (cmpop) or
  1222. (nodetype in [orn,andn,xorn]) then
  1223. begin
  1224. case nodetype of
  1225. addn, muln, xorn, orn, andn:
  1226. begin
  1227. case nodetype of
  1228. addn:
  1229. cgop := OP_ADD;
  1230. muln:
  1231. if unsigned then
  1232. cgop := OP_MUL
  1233. else
  1234. cgop := OP_IMUL;
  1235. xorn:
  1236. cgop := OP_XOR;
  1237. orn:
  1238. cgop := OP_OR;
  1239. andn:
  1240. cgop := OP_AND;
  1241. end;
  1242. if (left.location.loc = LOC_CONSTANT) then
  1243. swapleftright;
  1244. if (right.location.loc <> LOC_CONSTANT) then
  1245. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  1246. left.location.register,right.location.register,
  1247. location.register)
  1248. else
  1249. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  1250. right.location.value,left.location.register,
  1251. location.register);
  1252. end;
  1253. subn:
  1254. begin
  1255. if (nf_swaped in flags) then
  1256. swapleftright;
  1257. if left.location.loc <> LOC_CONSTANT then
  1258. if right.location.loc <> LOC_CONSTANT then
  1259. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1260. right.location.register,left.location.register,
  1261. location.register)
  1262. else
  1263. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1264. right.location.value,left.location.register,
  1265. location.register)
  1266. else
  1267. if (longint(left.location.value) >= low(smallint)) and
  1268. (longint(left.location.value) <= high(smallint)) then
  1269. begin
  1270. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  1271. location.register,right.location.register,
  1272. longint(left.location.value)));
  1273. end
  1274. else
  1275. begin
  1276. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  1277. cg.a_load_const_reg(exprasmlist,OS_INT,
  1278. left.location.value,tmpreg);
  1279. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1280. right.location.register,tmpreg,location.register);
  1281. end;
  1282. end;
  1283. ltn,lten,gtn,gten,equaln,unequaln :
  1284. begin
  1285. emit_compare(unsigned);
  1286. end;
  1287. end;
  1288. end
  1289. else
  1290. // overflow checking is on and we have an addn, subn or muln
  1291. begin
  1292. if is_signed(resulttype.def) then
  1293. begin
  1294. case nodetype of
  1295. addn:
  1296. op := A_ADDO;
  1297. subn:
  1298. op := A_SUBO;
  1299. muln:
  1300. op := A_MULLWO;
  1301. else
  1302. internalerror(2002072601);
  1303. end;
  1304. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1305. left.location.register,right.location.register));
  1306. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1307. end
  1308. else
  1309. begin
  1310. case nodetype of
  1311. addn:
  1312. begin
  1313. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
  1314. left.location.register,right.location.register));
  1315. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
  1316. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1317. end;
  1318. subn:
  1319. begin
  1320. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
  1321. left.location.register,right.location.register));
  1322. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
  1323. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1324. end;
  1325. muln:
  1326. begin
  1327. { calculate the upper 32 bits of the product, = 0 if no overflow }
  1328. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,location.register,
  1329. left.location.register,right.location.register));
  1330. { calculate the real result }
  1331. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
  1332. left.location.register,right.location.register));
  1333. { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
  1334. objectlibrary.getlabel(hl);
  1335. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
  1336. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  1337. cg.a_label(exprasmlist,hl);
  1338. end;
  1339. end;
  1340. end;
  1341. end;
  1342. end;
  1343. begin
  1344. caddnode:=tppcaddnode;
  1345. end.
  1346. {
  1347. $Log$
  1348. Revision 1.52 2004-10-31 21:45:03 peter
  1349. * generic tlocation
  1350. * move tlocation to cgutils
  1351. Revision 1.51 2004/10/26 18:22:31 jonas
  1352. * fixed bugs due to change of the value field of tlocation from aword to
  1353. aint
  1354. Revision 1.50 2004/10/25 15:36:47 peter
  1355. * save standard registers moved to tcgobj
  1356. Revision 1.49 2004/09/25 14:23:54 peter
  1357. * ungetregister is now only used for cpuregisters, renamed to
  1358. ungetcpuregister
  1359. * renamed (get|unget)explicitregister(s) to ..cpuregister
  1360. * removed location-release/reference_release
  1361. Revision 1.48 2004/08/30 09:28:40 jonas
  1362. * only specially handle 64bit operations on ordinals
  1363. Revision 1.47 2004/07/21 15:09:10 jonas
  1364. * do a resulttypepass of left in the overloaded pass_1 before checking
  1365. its resulttype
  1366. Revision 1.46 2004/07/17 14:47:16 jonas
  1367. - removed useless maybe_pushfpu code for ppc
  1368. Revision 1.45 2004/06/20 08:55:32 florian
  1369. * logs truncated
  1370. Revision 1.44 2004/06/17 16:55:46 peter
  1371. * powerpc compiles again
  1372. Revision 1.43 2004/03/18 16:19:03 peter
  1373. * fixed operator overload allowing for pointer-string
  1374. * replaced some type_e_mismatch with more informational messages
  1375. Revision 1.42 2004/01/06 21:37:41 peter
  1376. * fixed too long ie number
  1377. }