nppcadd.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl and Jonas Maebe
  3. Code generation for add nodes on the PowerPC
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nppcadd;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,nadd,ncgadd,cpubase;
  22. type
  23. tppcaddnode = class(tcgaddnode)
  24. function pass_1: tnode; override;
  25. procedure pass_2;override;
  26. private
  27. procedure pass_left_and_right;
  28. procedure load_left_right(cmpop, load_constants: boolean);
  29. function getresflags : tresflags;
  30. procedure emit_compare(unsigned : boolean);
  31. procedure second_addfloat;override;
  32. procedure second_addboolean;override;
  33. procedure second_addsmallset;override;
  34. {$ifdef SUPPORT_MMX}
  35. procedure second_addmmx;override;
  36. {$endif SUPPORT_MMX}
  37. procedure second_add64bit;override;
  38. end;
  39. implementation
  40. uses
  41. globtype,systems,
  42. cutils,verbose,globals,
  43. symconst,symdef,paramgr,
  44. aasmbase,aasmtai,aasmcpu,defutil,htypechk,
  45. cgbase,cpuinfo,pass_1,pass_2,regvars,
  46. cpupara,cgcpu,cgutils,
  47. ncon,nset,
  48. ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
  49. {*****************************************************************************
  50. Pass 1
  51. *****************************************************************************}
  52. function tppcaddnode.pass_1: tnode;
  53. begin
  54. resulttypepass(left);
  55. if (nodetype in [equaln,unequaln]) and
  56. (left.resulttype.def.deftype = orddef) and
  57. is_64bit(left.resulttype.def) then
  58. begin
  59. result := nil;
  60. firstpass(left);
  61. firstpass(right);
  62. expectloc := LOC_FLAGS;
  63. calcregisters(self,2,0,0);
  64. exit;
  65. end;
  66. result := inherited pass_1;
  67. end;
  68. {*****************************************************************************
  69. Helpers
  70. *****************************************************************************}
  71. procedure tppcaddnode.pass_left_and_right;
  72. begin
  73. { calculate the operator which is more difficult }
  74. firstcomplex(self);
  75. { in case of constant put it to the left }
  76. if (left.nodetype=ordconstn) then
  77. swapleftright;
  78. secondpass(left);
  79. secondpass(right);
  80. end;
  81. procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
  82. procedure load_node(var n: tnode);
  83. begin
  84. case n.location.loc of
  85. LOC_REGISTER:
  86. if not cmpop then
  87. begin
  88. location.register := n.location.register;
  89. if is_64bit(n.resulttype.def) then
  90. location.register64.reghi := n.location.register64.reghi;
  91. end;
  92. LOC_REFERENCE,LOC_CREFERENCE:
  93. begin
  94. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  95. if not cmpop then
  96. begin
  97. location.register := n.location.register;
  98. if is_64bit(n.resulttype.def) then
  99. location.register64.reghi := n.location.register64.reghi;
  100. end;
  101. end;
  102. LOC_CONSTANT:
  103. begin
  104. if load_constants then
  105. begin
  106. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  107. if not cmpop then
  108. begin
  109. location.register := n.location.register;
  110. if is_64bit(n.resulttype.def) then
  111. location.register64.reghi := n.location.register64.reghi;
  112. end;
  113. end;
  114. end;
  115. end;
  116. end;
  117. begin
  118. load_node(left);
  119. load_node(right);
  120. if not(cmpop) and
  121. (location.register = NR_NO) then
  122. begin
  123. location.register := cg.getintregister(exprasmlist,OS_INT);
  124. if is_64bit(resulttype.def) then
  125. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  126. end;
  127. end;
  128. function tppcaddnode.getresflags : tresflags;
  129. begin
  130. if (left.resulttype.def.deftype <> floatdef) then
  131. result.cr := RS_CR0
  132. else
  133. result.cr := RS_CR1;
  134. case nodetype of
  135. equaln : result.flag:=F_EQ;
  136. unequaln : result.flag:=F_NE;
  137. else
  138. if nf_swaped in flags then
  139. case nodetype of
  140. ltn : result.flag:=F_GT;
  141. lten : result.flag:=F_GE;
  142. gtn : result.flag:=F_LT;
  143. gten : result.flag:=F_LE;
  144. end
  145. else
  146. case nodetype of
  147. ltn : result.flag:=F_LT;
  148. lten : result.flag:=F_LE;
  149. gtn : result.flag:=F_GT;
  150. gten : result.flag:=F_GE;
  151. end;
  152. end
  153. end;
  154. procedure tppcaddnode.emit_compare(unsigned: boolean);
  155. var
  156. op : tasmop;
  157. tmpreg : tregister;
  158. useconst : boolean;
  159. begin
  160. // get the constant on the right if there is one
  161. if (left.location.loc = LOC_CONSTANT) then
  162. swapleftright;
  163. // can we use an immediate, or do we have to load the
  164. // constant in a register first?
  165. if (right.location.loc = LOC_CONSTANT) then
  166. begin
  167. {$ifdef dummy}
  168. if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.value64)<>0) and ((hi(right.location.value64)<>$ffffffff) or unsigned) then
  169. internalerror(2002080301);
  170. {$endif extdebug}
  171. if (nodetype in [equaln,unequaln]) then
  172. if (unsigned and
  173. (aword(right.location.value) > high(word))) or
  174. (not unsigned and
  175. (aint(right.location.value) < low(smallint)) or
  176. (aint(right.location.value) > high(smallint))) then
  177. { we can then maybe use a constant in the 'othersigned' case
  178. (the sign doesn't matter for // equal/unequal)}
  179. unsigned := not unsigned;
  180. if (unsigned and
  181. (aword(right.location.value) <= high(word))) or
  182. (not(unsigned) and
  183. (aint(right.location.value) >= low(smallint)) and
  184. (aint(right.location.value) <= high(smallint))) then
  185. useconst := true
  186. else
  187. begin
  188. useconst := false;
  189. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  190. cg.a_load_const_reg(exprasmlist,OS_INT,
  191. right.location.value,tmpreg);
  192. end
  193. end
  194. else
  195. useconst := false;
  196. location.loc := LOC_FLAGS;
  197. location.resflags := getresflags;
  198. if not unsigned then
  199. if useconst then
  200. op := A_CMPWI
  201. else
  202. op := A_CMPW
  203. else
  204. if useconst then
  205. op := A_CMPLWI
  206. else
  207. op := A_CMPLW;
  208. if (right.location.loc = LOC_CONSTANT) then
  209. begin
  210. if useconst then
  211. exprasmlist.concat(taicpu.op_reg_const(op,left.location.register,longint(right.location.value)))
  212. else
  213. exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg));
  214. end
  215. else
  216. exprasmlist.concat(taicpu.op_reg_reg(op,
  217. left.location.register,right.location.register));
  218. end;
  219. {*****************************************************************************
  220. AddBoolean
  221. *****************************************************************************}
  222. procedure tppcaddnode.second_addboolean;
  223. var
  224. cgop : TOpCg;
  225. cgsize : TCgSize;
  226. cmpop,
  227. isjump : boolean;
  228. otl,ofl : tasmlabel;
  229. begin
  230. { calculate the operator which is more difficult }
  231. firstcomplex(self);
  232. cmpop:=false;
  233. if (torddef(left.resulttype.def).typ=bool8bit) or
  234. (torddef(right.resulttype.def).typ=bool8bit) then
  235. cgsize:=OS_8
  236. else
  237. if (torddef(left.resulttype.def).typ=bool16bit) or
  238. (torddef(right.resulttype.def).typ=bool16bit) then
  239. cgsize:=OS_16
  240. else
  241. cgsize:=OS_32;
  242. if ((cs_full_boolean_eval in aktlocalswitches) and
  243. not(nf_short_bool in flags)) or
  244. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  245. begin
  246. if left.nodetype in [ordconstn,realconstn] then
  247. swapleftright;
  248. isjump:=(left.expectloc=LOC_JUMP);
  249. if isjump then
  250. begin
  251. otl:=truelabel;
  252. objectlibrary.getlabel(truelabel);
  253. ofl:=falselabel;
  254. objectlibrary.getlabel(falselabel);
  255. end;
  256. secondpass(left);
  257. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  258. location_force_reg(exprasmlist,left.location,cgsize,false);
  259. if isjump then
  260. begin
  261. truelabel:=otl;
  262. falselabel:=ofl;
  263. end
  264. else if left.location.loc=LOC_JUMP then
  265. internalerror(2003122901);
  266. isjump:=(right.expectloc=LOC_JUMP);
  267. if isjump then
  268. begin
  269. otl:=truelabel;
  270. objectlibrary.getlabel(truelabel);
  271. ofl:=falselabel;
  272. objectlibrary.getlabel(falselabel);
  273. end;
  274. secondpass(right);
  275. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  276. location_force_reg(exprasmlist,right.location,cgsize,false);
  277. if isjump then
  278. begin
  279. truelabel:=otl;
  280. falselabel:=ofl;
  281. end
  282. else if right.location.loc=LOC_JUMP then
  283. internalerror(200312292);
  284. cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  285. { set result location }
  286. if not cmpop then
  287. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  288. else
  289. location_reset(location,LOC_FLAGS,OS_NO);
  290. load_left_right(cmpop,false);
  291. if (left.location.loc = LOC_CONSTANT) then
  292. swapleftright;
  293. { compare the }
  294. case nodetype of
  295. ltn,lten,gtn,gten,
  296. equaln,unequaln :
  297. begin
  298. if (right.location.loc <> LOC_CONSTANT) then
  299. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
  300. left.location.register,right.location.register))
  301. else
  302. exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
  303. left.location.register,longint(right.location.value)));
  304. location.resflags := getresflags;
  305. end;
  306. else
  307. begin
  308. case nodetype of
  309. xorn :
  310. cgop:=OP_XOR;
  311. orn :
  312. cgop:=OP_OR;
  313. andn :
  314. cgop:=OP_AND;
  315. else
  316. internalerror(200203247);
  317. end;
  318. if right.location.loc <> LOC_CONSTANT then
  319. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  320. left.location.register,right.location.register,
  321. location.register)
  322. else
  323. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  324. right.location.value,left.location.register,
  325. location.register);
  326. end;
  327. end;
  328. end
  329. else
  330. begin
  331. // just to make sure we free the right registers
  332. cmpop := true;
  333. case nodetype of
  334. andn,
  335. orn :
  336. begin
  337. location_reset(location,LOC_JUMP,OS_NO);
  338. case nodetype of
  339. andn :
  340. begin
  341. otl:=truelabel;
  342. objectlibrary.getlabel(truelabel);
  343. secondpass(left);
  344. maketojumpbool(exprasmlist,left,lr_load_regvars);
  345. cg.a_label(exprasmlist,truelabel);
  346. truelabel:=otl;
  347. end;
  348. orn :
  349. begin
  350. ofl:=falselabel;
  351. objectlibrary.getlabel(falselabel);
  352. secondpass(left);
  353. maketojumpbool(exprasmlist,left,lr_load_regvars);
  354. cg.a_label(exprasmlist,falselabel);
  355. falselabel:=ofl;
  356. end;
  357. else
  358. internalerror(200403181);
  359. end;
  360. secondpass(right);
  361. maketojumpbool(exprasmlist,right,lr_load_regvars);
  362. end;
  363. end;
  364. end;
  365. end;
  366. {*****************************************************************************
  367. AddFloat
  368. *****************************************************************************}
  369. procedure tppcaddnode.second_addfloat;
  370. var
  371. op : TAsmOp;
  372. cmpop : boolean;
  373. begin
  374. pass_left_and_right;
  375. cmpop:=false;
  376. case nodetype of
  377. addn :
  378. op:=A_FADD;
  379. muln :
  380. op:=A_FMUL;
  381. subn :
  382. op:=A_FSUB;
  383. slashn :
  384. op:=A_FDIV;
  385. ltn,lten,gtn,gten,
  386. equaln,unequaln :
  387. begin
  388. op:=A_FCMPO;
  389. cmpop:=true;
  390. end;
  391. else
  392. internalerror(200403182);
  393. end;
  394. // get the operands in the correct order, there are no special cases
  395. // here, everything is register-based
  396. if nf_swaped in flags then
  397. swapleftright;
  398. // put both operands in a register
  399. location_force_fpureg(exprasmlist,right.location,true);
  400. location_force_fpureg(exprasmlist,left.location,true);
  401. // initialize de result
  402. if not cmpop then
  403. begin
  404. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  405. if left.location.loc = LOC_FPUREGISTER then
  406. location.register := left.location.register
  407. else if right.location.loc = LOC_FPUREGISTER then
  408. location.register := right.location.register
  409. else
  410. location.register := cg.getfpuregister(exprasmlist,location.size);
  411. end
  412. else
  413. begin
  414. location_reset(location,LOC_FLAGS,OS_NO);
  415. location.resflags := getresflags;
  416. end;
  417. // emit the actual operation
  418. if not cmpop then
  419. begin
  420. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  421. location.register,left.location.register,
  422. right.location.register))
  423. end
  424. else
  425. begin
  426. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  427. newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
  428. end;
  429. end;
  430. {*****************************************************************************
  431. AddSmallSet
  432. *****************************************************************************}
  433. procedure tppcaddnode.second_addsmallset;
  434. var
  435. cgop : TOpCg;
  436. tmpreg : tregister;
  437. opdone,
  438. cmpop : boolean;
  439. begin
  440. pass_left_and_right;
  441. { when a setdef is passed, it has to be a smallset }
  442. if ((left.resulttype.def.deftype=setdef) and
  443. (tsetdef(left.resulttype.def).settype<>smallset)) or
  444. ((right.resulttype.def.deftype=setdef) and
  445. (tsetdef(right.resulttype.def).settype<>smallset)) then
  446. internalerror(200203301);
  447. opdone := false;
  448. cmpop:=nodetype in [equaln,unequaln,lten,gten];
  449. { set result location }
  450. if not cmpop then
  451. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  452. else
  453. location_reset(location,LOC_FLAGS,OS_NO);
  454. load_left_right(cmpop,false);
  455. if not(cmpop) and
  456. (location.register = NR_NO) then
  457. location.register := cg.getintregister(exprasmlist,OS_INT);
  458. case nodetype of
  459. addn :
  460. begin
  461. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  462. swapleftright;
  463. { are we adding set elements ? }
  464. if right.nodetype=setelementn then
  465. begin
  466. { no range support for smallsets! }
  467. if assigned(tsetelementnode(right).right) then
  468. internalerror(43244);
  469. if (right.location.loc = LOC_CONSTANT) then
  470. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  471. aint(aword(1) shl aword(right.location.value)),
  472. left.location.register,location.register)
  473. else
  474. begin
  475. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  476. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  477. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  478. right.location.register,tmpreg);
  479. if left.location.loc <> LOC_CONSTANT then
  480. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  481. left.location.register,location.register)
  482. else
  483. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  484. left.location.value,tmpreg,location.register);
  485. end;
  486. opdone := true;
  487. end
  488. else
  489. cgop := OP_OR;
  490. end;
  491. symdifn :
  492. cgop:=OP_XOR;
  493. muln :
  494. cgop:=OP_AND;
  495. subn :
  496. begin
  497. cgop:=OP_AND;
  498. if (not(nf_swaped in flags)) then
  499. if (right.location.loc=LOC_CONSTANT) then
  500. right.location.value := not(right.location.value)
  501. else
  502. opdone := true
  503. else if (left.location.loc=LOC_CONSTANT) then
  504. left.location.value := not(left.location.value)
  505. else
  506. begin
  507. swapleftright;
  508. opdone := true;
  509. end;
  510. if opdone then
  511. begin
  512. if left.location.loc = LOC_CONSTANT then
  513. begin
  514. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  515. cg.a_load_const_reg(exprasmlist,OS_INT,
  516. left.location.value,tmpreg);
  517. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  518. location.register,tmpreg,right.location.register));
  519. end
  520. else
  521. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  522. location.register,left.location.register,
  523. right.location.register));
  524. end;
  525. end;
  526. equaln,
  527. unequaln :
  528. begin
  529. emit_compare(true);
  530. opdone := true;
  531. end;
  532. lten,gten:
  533. begin
  534. If (not(nf_swaped in flags) and
  535. (nodetype = lten)) or
  536. ((nf_swaped in flags) and
  537. (nodetype = gten)) then
  538. swapleftright;
  539. // now we have to check whether left >= right
  540. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  541. if left.location.loc = LOC_CONSTANT then
  542. begin
  543. cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
  544. not(left.location.value),right.location.register,tmpreg);
  545. exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
  546. // the two instructions above should be folded together by
  547. // the peepholeoptimizer
  548. end
  549. else
  550. begin
  551. if right.location.loc = LOC_CONSTANT then
  552. begin
  553. cg.a_load_const_reg(exprasmlist,OS_INT,
  554. right.location.value,tmpreg);
  555. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  556. tmpreg,left.location.register));
  557. end
  558. else
  559. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  560. right.location.register,left.location.register));
  561. end;
  562. location.resflags.cr := RS_CR0;
  563. location.resflags.flag := F_EQ;
  564. opdone := true;
  565. end;
  566. else
  567. internalerror(2002072701);
  568. end;
  569. if not opdone then
  570. begin
  571. // these are all commutative operations
  572. if (left.location.loc = LOC_CONSTANT) then
  573. swapleftright;
  574. if (right.location.loc = LOC_CONSTANT) then
  575. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  576. right.location.value,left.location.register,
  577. location.register)
  578. else
  579. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  580. right.location.register,left.location.register,
  581. location.register);
  582. end;
  583. end;
  584. {*****************************************************************************
  585. Add64bit
  586. *****************************************************************************}
  587. procedure tppcaddnode.second_add64bit;
  588. var
  589. op : TOpCG;
  590. op1,op2 : TAsmOp;
  591. cmpop,
  592. unsigned : boolean;
  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. if (nf_swaped in flags) then
  706. swapleftright;
  707. end;
  708. ltn,lten,
  709. gtn,gten,
  710. equaln,unequaln:
  711. begin
  712. op:=OP_NONE;
  713. cmpop:=true;
  714. end;
  715. xorn:
  716. op:=OP_XOR;
  717. orn:
  718. op:=OP_OR;
  719. andn:
  720. op:=OP_AND;
  721. muln:
  722. begin
  723. { should be handled in pass_1 (JM) }
  724. internalerror(200109051);
  725. end;
  726. else
  727. internalerror(2002072705);
  728. end;
  729. if not cmpop then
  730. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  731. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  732. (nodetype in [addn,subn]));
  733. if not(cs_check_overflow in aktlocalswitches) or
  734. not(nodetype in [addn,subn]) then
  735. begin
  736. case nodetype of
  737. ltn,lten,
  738. gtn,gten:
  739. begin
  740. emit_cmp64_hi;
  741. firstjmp64bitcmp;
  742. emit_cmp64_lo;
  743. secondjmp64bitcmp;
  744. end;
  745. equaln,unequaln:
  746. begin
  747. // instead of doing a complicated compare, do
  748. // (left.hi xor right.hi) or (left.lo xor right.lo)
  749. // (somewhate optimized so that no superfluous 'mr's are
  750. // generated)
  751. if (left.location.loc = LOC_CONSTANT) then
  752. swapleftright;
  753. if (right.location.loc = LOC_CONSTANT) then
  754. begin
  755. if left.location.loc = LOC_REGISTER then
  756. begin
  757. tempreg64.reglo := left.location.register64.reglo;
  758. tempreg64.reghi := left.location.register64.reghi;
  759. end
  760. else
  761. begin
  762. if (aint(right.location.value64) <> 0) then
  763. tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
  764. else
  765. tempreg64.reglo := left.location.register64.reglo;
  766. if ((right.location.value64 shr 32) <> 0) then
  767. tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
  768. else
  769. tempreg64.reghi := left.location.register64.reghi;
  770. end;
  771. if (aint(right.location.value64) <> 0) then
  772. { negative values can be handled using SUB, }
  773. { positive values < 65535 using XOR. }
  774. if (longint(right.location.value64) >= -32767) and
  775. (longint(right.location.value64) < 0) then
  776. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  777. aint(right.location.value64),
  778. left.location.register64.reglo,tempreg64.reglo)
  779. else
  780. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  781. aint(right.location.value64),
  782. left.location.register64.reglo,tempreg64.reglo);
  783. if ((right.location.value64 shr 32) <> 0) then
  784. if (longint(right.location.value64 shr 32) >= -32767) and
  785. (longint(right.location.value64 shr 32) < 0) then
  786. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  787. aint(right.location.value64 shr 32),
  788. left.location.register64.reghi,tempreg64.reghi)
  789. else
  790. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  791. aint(right.location.value64 shr 32),
  792. left.location.register64.reghi,tempreg64.reghi);
  793. end
  794. else
  795. begin
  796. tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
  797. tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
  798. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,location.size,
  799. left.location.register64,right.location.register64,
  800. tempreg64);
  801. end;
  802. cg.a_reg_alloc(exprasmlist,NR_R0);
  803. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
  804. tempreg64.reglo,tempreg64.reghi));
  805. cg.a_reg_dealloc(exprasmlist,NR_R0);
  806. location_reset(location,LOC_FLAGS,OS_NO);
  807. location.resflags := getresflags;
  808. end;
  809. xorn,orn,andn,addn:
  810. begin
  811. if (location.register64.reglo = NR_NO) then
  812. begin
  813. location.register64.reglo := cg.getintregister(exprasmlist,OS_INT);
  814. location.register64.reghi := cg.getintregister(exprasmlist,OS_INT);
  815. end;
  816. if (left.location.loc = LOC_CONSTANT) then
  817. swapleftright;
  818. if (right.location.loc = LOC_CONSTANT) then
  819. cg64.a_op64_const_reg_reg(exprasmlist,op,location.size,right.location.value64,
  820. left.location.register64,location.register64)
  821. else
  822. cg64.a_op64_reg_reg_reg(exprasmlist,op,location.size,right.location.register64,
  823. left.location.register64,location.register64);
  824. end;
  825. subn:
  826. begin
  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,location.size,
  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,location.size,
  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,location.size,
  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. begin
  1299. op := A_SUBO;
  1300. if (nf_swaped in flags) then
  1301. swapleftright;
  1302. end;
  1303. muln:
  1304. op := A_MULLWO;
  1305. else
  1306. internalerror(2002072601);
  1307. end;
  1308. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1309. left.location.register,right.location.register));
  1310. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1311. end
  1312. else
  1313. begin
  1314. case nodetype of
  1315. addn:
  1316. begin
  1317. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
  1318. left.location.register,right.location.register));
  1319. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
  1320. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1321. end;
  1322. subn:
  1323. begin
  1324. if nf_swaped in flags then
  1325. swapleftright;
  1326. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
  1327. left.location.register,right.location.register));
  1328. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
  1329. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1330. end;
  1331. muln:
  1332. begin
  1333. { calculate the upper 32 bits of the product, = 0 if no overflow }
  1334. cg.a_reg_alloc(exprasmlist,NR_R0);
  1335. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,NR_R0,
  1336. left.location.register,right.location.register));
  1337. cg.a_reg_dealloc(exprasmlist,NR_R0);
  1338. { calculate the real result }
  1339. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
  1340. left.location.register,right.location.register));
  1341. { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
  1342. objectlibrary.getlabel(hl);
  1343. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
  1344. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  1345. cg.a_label(exprasmlist,hl);
  1346. end;
  1347. end;
  1348. end;
  1349. end;
  1350. end;
  1351. begin
  1352. caddnode:=tppcaddnode;
  1353. end.