nppcadd.pas 54 KB

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