nppcadd.pas 55 KB

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