nppcadd.pas 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567
  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,cginfo;
  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,
  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 := rg.getregisterfpu(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 := rg.getregisterint(exprasmlist,OS_INT);
  136. if is_64bit(resulttype.def) then
  137. location.registerhigh := rg.getregisterint(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.valueqword)<>0) and ((hi(right.location.valueqword)<>$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 := rg.getregisterint(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. rg.ungetregisterint(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.location.loc=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. isjump:=(right.location.loc=LOC_JUMP);
  279. if isjump then
  280. begin
  281. otl:=truelabel;
  282. objectlibrary.getlabel(truelabel);
  283. ofl:=falselabel;
  284. objectlibrary.getlabel(falselabel);
  285. end;
  286. secondpass(right);
  287. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  288. location_force_reg(exprasmlist,right.location,cgsize,false);
  289. if isjump then
  290. begin
  291. truelabel:=otl;
  292. falselabel:=ofl;
  293. end;
  294. cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  295. { set result location }
  296. if not cmpop then
  297. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  298. else
  299. location_reset(location,LOC_FLAGS,OS_NO);
  300. load_left_right(cmpop,false);
  301. if (left.location.loc = LOC_CONSTANT) then
  302. swapleftright;
  303. { compare the }
  304. case nodetype of
  305. ltn,lten,gtn,gten,
  306. equaln,unequaln :
  307. begin
  308. if (right.location.loc <> LOC_CONSTANT) then
  309. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
  310. left.location.register,right.location.register))
  311. else
  312. exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
  313. left.location.register,longint(right.location.value)));
  314. location.resflags := getresflags;
  315. end;
  316. else
  317. begin
  318. case nodetype of
  319. xorn :
  320. cgop:=OP_XOR;
  321. orn :
  322. cgop:=OP_OR;
  323. andn :
  324. cgop:=OP_AND;
  325. else
  326. internalerror(200203247);
  327. end;
  328. if right.location.loc <> LOC_CONSTANT then
  329. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  330. left.location.register,right.location.register,
  331. location.register)
  332. else
  333. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  334. aword(right.location.value),left.location.register,
  335. location.register);
  336. end;
  337. end;
  338. end
  339. else
  340. begin
  341. // just to make sure we free the right registers
  342. cmpop := true;
  343. case nodetype of
  344. andn,
  345. orn :
  346. begin
  347. location_reset(location,LOC_JUMP,OS_NO);
  348. case nodetype of
  349. andn :
  350. begin
  351. otl:=truelabel;
  352. objectlibrary.getlabel(truelabel);
  353. secondpass(left);
  354. maketojumpbool(exprasmlist,left,lr_load_regvars);
  355. cg.a_label(exprasmlist,truelabel);
  356. truelabel:=otl;
  357. end;
  358. orn :
  359. begin
  360. ofl:=falselabel;
  361. objectlibrary.getlabel(falselabel);
  362. secondpass(left);
  363. maketojumpbool(exprasmlist,left,lr_load_regvars);
  364. cg.a_label(exprasmlist,falselabel);
  365. falselabel:=ofl;
  366. end;
  367. else
  368. CGMessage(type_e_mismatch);
  369. end;
  370. secondpass(right);
  371. maketojumpbool(exprasmlist,right,lr_load_regvars);
  372. end;
  373. end;
  374. end;
  375. release_reg_left_right;
  376. end;
  377. {*****************************************************************************
  378. AddFloat
  379. *****************************************************************************}
  380. procedure tppcaddnode.second_addfloat;
  381. var
  382. op : TAsmOp;
  383. cmpop : boolean;
  384. begin
  385. pass_left_and_right;
  386. cmpop:=false;
  387. case nodetype of
  388. addn :
  389. op:=A_FADD;
  390. muln :
  391. op:=A_FMUL;
  392. subn :
  393. op:=A_FSUB;
  394. slashn :
  395. op:=A_FDIV;
  396. ltn,lten,gtn,gten,
  397. equaln,unequaln :
  398. begin
  399. op:=A_FCMPO;
  400. cmpop:=true;
  401. end;
  402. else
  403. CGMessage(type_e_mismatch);
  404. end;
  405. // get the operands in the correct order, there are no special cases
  406. // here, everything is register-based
  407. if nf_swaped in flags then
  408. swapleftright;
  409. // put both operands in a register
  410. location_force_fpureg(exprasmlist,right.location,true);
  411. location_force_fpureg(exprasmlist,left.location,true);
  412. // initialize de result
  413. if not cmpop then
  414. begin
  415. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  416. if left.location.loc = LOC_FPUREGISTER then
  417. location.register := left.location.register
  418. else if right.location.loc = LOC_FPUREGISTER then
  419. location.register := right.location.register
  420. else
  421. location.register := rg.getregisterfpu(exprasmlist,location.size);
  422. end
  423. else
  424. begin
  425. location_reset(location,LOC_FLAGS,OS_NO);
  426. location.resflags := getresflags;
  427. end;
  428. // emit the actual operation
  429. if not cmpop then
  430. begin
  431. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  432. location.register,left.location.register,
  433. right.location.register))
  434. end
  435. else
  436. begin
  437. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  438. newreg(R_SPECIALREGISTER,location.resflags.cr,R_SUBNONE),left.location.register,right.location.register))
  439. end;
  440. release_reg_left_right;
  441. end;
  442. {*****************************************************************************
  443. AddSmallSet
  444. *****************************************************************************}
  445. procedure tppcaddnode.second_addsmallset;
  446. var
  447. cgop : TOpCg;
  448. tmpreg : tregister;
  449. opdone,
  450. cmpop : boolean;
  451. begin
  452. pass_left_and_right;
  453. { when a setdef is passed, it has to be a smallset }
  454. if ((left.resulttype.def.deftype=setdef) and
  455. (tsetdef(left.resulttype.def).settype<>smallset)) or
  456. ((right.resulttype.def.deftype=setdef) and
  457. (tsetdef(right.resulttype.def).settype<>smallset)) then
  458. internalerror(200203301);
  459. opdone := false;
  460. cmpop:=nodetype in [equaln,unequaln,lten,gten];
  461. { set result location }
  462. if not cmpop then
  463. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  464. else
  465. location_reset(location,LOC_FLAGS,OS_NO);
  466. load_left_right(cmpop,false);
  467. if not(cmpop) and
  468. (location.register = NR_NO) then
  469. location.register := rg.getregisterint(exprasmlist,OS_INT);
  470. case nodetype of
  471. addn :
  472. begin
  473. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  474. swapleftright;
  475. { are we adding set elements ? }
  476. if right.nodetype=setelementn then
  477. begin
  478. { no range support for smallsets! }
  479. if assigned(tsetelementnode(right).right) then
  480. internalerror(43244);
  481. if (right.location.loc = LOC_CONSTANT) then
  482. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  483. aword(1 shl aword(right.location.value)),
  484. left.location.register,location.register)
  485. else
  486. begin
  487. tmpreg := rg.getregisterint(exprasmlist,OS_INT);
  488. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  489. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  490. right.location.register,tmpreg);
  491. if left.location.loc <> LOC_CONSTANT then
  492. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  493. left.location.register,location.register)
  494. else
  495. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  496. aword(left.location.value),tmpreg,location.register);
  497. rg.ungetregisterint(exprasmlist,tmpreg);
  498. end;
  499. opdone := true;
  500. end
  501. else
  502. cgop := OP_OR;
  503. end;
  504. symdifn :
  505. cgop:=OP_XOR;
  506. muln :
  507. cgop:=OP_AND;
  508. subn :
  509. begin
  510. cgop:=OP_AND;
  511. if (not(nf_swaped in flags)) then
  512. if (right.location.loc=LOC_CONSTANT) then
  513. right.location.value := not(right.location.value)
  514. else
  515. opdone := true
  516. else if (left.location.loc=LOC_CONSTANT) then
  517. left.location.value := not(left.location.value)
  518. else
  519. begin
  520. swapleftright;
  521. opdone := true;
  522. end;
  523. if opdone then
  524. begin
  525. if left.location.loc = LOC_CONSTANT then
  526. begin
  527. tmpreg := rg.getregisterint(exprasmlist,OS_INT);
  528. cg.a_load_const_reg(exprasmlist,OS_INT,
  529. aword(left.location.value),tmpreg);
  530. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  531. location.register,tmpreg,right.location.register));
  532. rg.ungetregisterint(exprasmlist,tmpreg);
  533. end
  534. else
  535. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  536. location.register,left.location.register,
  537. right.location.register));
  538. end;
  539. end;
  540. equaln,
  541. unequaln :
  542. begin
  543. emit_compare(true);
  544. opdone := true;
  545. end;
  546. lten,gten:
  547. begin
  548. If (not(nf_swaped in flags) and
  549. (nodetype = lten)) or
  550. ((nf_swaped in flags) and
  551. (nodetype = gten)) then
  552. swapleftright;
  553. // now we have to check whether left >= right
  554. tmpreg := rg.getregisterint(exprasmlist,OS_INT);
  555. if left.location.loc = LOC_CONSTANT then
  556. begin
  557. cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
  558. not(left.location.value),right.location.register,tmpreg);
  559. exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
  560. // the two instructions above should be folded together by
  561. // the peepholeoptimizer
  562. end
  563. else
  564. begin
  565. if right.location.loc = LOC_CONSTANT then
  566. begin
  567. cg.a_load_const_reg(exprasmlist,OS_INT,
  568. aword(right.location.value),tmpreg);
  569. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  570. tmpreg,left.location.register));
  571. end
  572. else
  573. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  574. right.location.register,left.location.register));
  575. end;
  576. rg.ungetregisterint(exprasmlist,tmpreg);
  577. location.resflags.cr := RS_CR0;
  578. location.resflags.flag := F_EQ;
  579. opdone := true;
  580. end;
  581. else
  582. internalerror(2002072701);
  583. end;
  584. if not opdone then
  585. begin
  586. // these are all commutative operations
  587. if (left.location.loc = LOC_CONSTANT) then
  588. swapleftright;
  589. if (right.location.loc = LOC_CONSTANT) then
  590. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  591. aword(right.location.value),left.location.register,
  592. location.register)
  593. else
  594. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  595. right.location.register,left.location.register,
  596. location.register);
  597. end;
  598. release_reg_left_right;
  599. end;
  600. {*****************************************************************************
  601. Add64bit
  602. *****************************************************************************}
  603. procedure tppcaddnode.second_add64bit;
  604. var
  605. op : TOpCG;
  606. op1,op2 : TAsmOp;
  607. hl4 : tasmlabel;
  608. cmpop,
  609. unsigned : boolean;
  610. r : Tregister;
  611. procedure emit_cmp64_hi;
  612. var
  613. oldleft, oldright: tlocation;
  614. begin
  615. // put the high part of the location in the low part
  616. location_copy(oldleft,left.location);
  617. location_copy(oldright,right.location);
  618. if left.location.loc = LOC_CONSTANT then
  619. left.location.valueqword := left.location.valueqword shr 32
  620. else
  621. left.location.registerlow := left.location.registerhigh;
  622. if right.location.loc = LOC_CONSTANT then
  623. right.location.valueqword := right.location.valueqword shr 32
  624. else
  625. right.location.registerlow := right.location.registerhigh;
  626. // and call the normal emit_compare
  627. emit_compare(unsigned);
  628. location_copy(left.location,oldleft);
  629. location_copy(right.location,oldright);
  630. end;
  631. procedure emit_cmp64_lo;
  632. begin
  633. emit_compare(true);
  634. end;
  635. procedure firstjmp64bitcmp;
  636. var
  637. oldnodetype: tnodetype;
  638. begin
  639. load_all_regvars(exprasmlist);
  640. { the jump the sequence is a little bit hairy }
  641. case nodetype of
  642. ltn,gtn:
  643. begin
  644. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  645. { cheat a little bit for the negative test }
  646. toggleflag(nf_swaped);
  647. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  648. toggleflag(nf_swaped);
  649. end;
  650. lten,gten:
  651. begin
  652. oldnodetype:=nodetype;
  653. if nodetype=lten then
  654. nodetype:=ltn
  655. else
  656. nodetype:=gtn;
  657. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  658. { cheat for the negative test }
  659. if nodetype=ltn then
  660. nodetype:=gtn
  661. else
  662. nodetype:=ltn;
  663. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  664. nodetype:=oldnodetype;
  665. end;
  666. equaln:
  667. begin
  668. nodetype := unequaln;
  669. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  670. nodetype := equaln;
  671. end;
  672. unequaln:
  673. begin
  674. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  675. end;
  676. end;
  677. end;
  678. procedure secondjmp64bitcmp;
  679. begin
  680. { the jump the sequence is a little bit hairy }
  681. case nodetype of
  682. ltn,gtn,lten,gten:
  683. begin
  684. { the comparison of the low dword always has }
  685. { to be always unsigned! }
  686. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  687. cg.a_jmp_always(exprasmlist,falselabel);
  688. end;
  689. equaln:
  690. begin
  691. nodetype := unequaln;
  692. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  693. cg.a_jmp_always(exprasmlist,truelabel);
  694. nodetype := equaln;
  695. end;
  696. unequaln:
  697. begin
  698. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  699. cg.a_jmp_always(exprasmlist,falselabel);
  700. end;
  701. end;
  702. end;
  703. var
  704. tempreg64: tregister64;
  705. begin
  706. firstcomplex(self);
  707. pass_left_and_right;
  708. cmpop:=false;
  709. unsigned:=((left.resulttype.def.deftype=orddef) and
  710. (torddef(left.resulttype.def).typ=u64bit)) or
  711. ((right.resulttype.def.deftype=orddef) and
  712. (torddef(right.resulttype.def).typ=u64bit));
  713. case nodetype of
  714. addn :
  715. begin
  716. op:=OP_ADD;
  717. end;
  718. subn :
  719. begin
  720. op:=OP_SUB;
  721. end;
  722. ltn,lten,
  723. gtn,gten,
  724. equaln,unequaln:
  725. begin
  726. op:=OP_NONE;
  727. cmpop:=true;
  728. end;
  729. xorn:
  730. op:=OP_XOR;
  731. orn:
  732. op:=OP_OR;
  733. andn:
  734. op:=OP_AND;
  735. muln:
  736. begin
  737. { should be handled in pass_1 (JM) }
  738. internalerror(200109051);
  739. end;
  740. else
  741. internalerror(2002072705);
  742. end;
  743. if not cmpop then
  744. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  745. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  746. (nodetype in [addn,subn]));
  747. if not(cs_check_overflow in aktlocalswitches) or
  748. not(nodetype in [addn,subn]) then
  749. begin
  750. case nodetype of
  751. ltn,lten,
  752. gtn,gten:
  753. begin
  754. emit_cmp64_hi;
  755. firstjmp64bitcmp;
  756. emit_cmp64_lo;
  757. secondjmp64bitcmp;
  758. end;
  759. equaln,unequaln:
  760. begin
  761. // instead of doing a complicated compare, do
  762. // (left.hi xor right.hi) or (left.lo xor right.lo)
  763. // (somewhate optimized so that no superfluous 'mr's are
  764. // generated)
  765. if (left.location.loc = LOC_CONSTANT) then
  766. swapleftright;
  767. if (right.location.loc = LOC_CONSTANT) then
  768. begin
  769. if left.location.loc = LOC_REGISTER then
  770. begin
  771. tempreg64.reglo := left.location.registerlow;
  772. tempreg64.reghi := left.location.registerhigh;
  773. end
  774. else
  775. begin
  776. if (aword(right.location.valueqword) <> 0) then
  777. tempreg64.reglo := rg.getregisterint(exprasmlist,OS_32)
  778. else
  779. tempreg64.reglo := left.location.registerlow;
  780. if ((right.location.valueqword shr 32) <> 0) then
  781. tempreg64.reghi := rg.getregisterint(exprasmlist,OS_32)
  782. else
  783. tempreg64.reghi := left.location.registerhigh;
  784. end;
  785. if (aword(right.location.valueqword) <> 0) then
  786. { negative values can be handled using SUB, }
  787. { positive values < 65535 using XOR. }
  788. if (longint(right.location.valueqword) >= -32767) and
  789. (longint(right.location.valueqword) < 0) then
  790. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  791. aword(right.location.valueqword),
  792. left.location.registerlow,tempreg64.reglo)
  793. else
  794. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  795. aword(right.location.valueqword),
  796. left.location.registerlow,tempreg64.reglo);
  797. if ((right.location.valueqword shr 32) <> 0) then
  798. if (longint(right.location.valueqword shr 32) >= -32767) and
  799. (longint(right.location.valueqword shr 32) < 0) then
  800. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  801. aword(right.location.valueqword shr 32),
  802. left.location.registerhigh,tempreg64.reghi)
  803. else
  804. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  805. aword(right.location.valueqword shr 32),
  806. left.location.registerhigh,tempreg64.reghi);
  807. end
  808. else
  809. begin
  810. tempreg64.reglo := rg.getregisterint(exprasmlist,OS_INT);
  811. tempreg64.reghi := rg.getregisterint(exprasmlist,OS_INT);
  812. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
  813. left.location.register64,right.location.register64,
  814. tempreg64);
  815. end;
  816. cg.a_reg_alloc(exprasmlist,NR_R0);
  817. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
  818. tempreg64.reglo,tempreg64.reghi));
  819. cg.a_reg_dealloc(exprasmlist,NR_R0);
  820. if (tempreg64.reglo <> left.location.registerlow) then
  821. rg.ungetregisterint(exprasmlist,tempreg64.reglo);
  822. if (tempreg64.reghi <> left.location.registerhigh) then
  823. rg.ungetregisterint(exprasmlist,tempreg64.reghi);
  824. location_reset(location,LOC_FLAGS,OS_NO);
  825. location.resflags := getresflags;
  826. end;
  827. xorn,orn,andn,addn:
  828. begin
  829. if (location.registerlow = NR_NO) then
  830. begin
  831. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  832. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  833. end;
  834. if (left.location.loc = LOC_CONSTANT) then
  835. swapleftright;
  836. if (right.location.loc = LOC_CONSTANT) then
  837. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
  838. left.location.register64,location.register64)
  839. else
  840. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  841. left.location.register64,location.register64);
  842. end;
  843. subn:
  844. begin
  845. if (nf_swaped in flags) then
  846. swapleftright;
  847. if left.location.loc <> LOC_CONSTANT then
  848. begin
  849. if (location.registerlow = NR_NO) then
  850. begin
  851. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  852. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  853. end;
  854. if right.location.loc <> LOC_CONSTANT then
  855. // reg64 - reg64
  856. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  857. right.location.register64,left.location.register64,
  858. location.register64)
  859. else
  860. // reg64 - const64
  861. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  862. right.location.valueqword,left.location.register64,
  863. location.register64)
  864. end
  865. else if ((left.location.valueqword shr 32) = 0) then
  866. begin
  867. if (location.registerlow = NR_NO) then
  868. begin
  869. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  870. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  871. end;
  872. if (int64(left.location.valueqword) >= low(smallint)) and
  873. (int64(left.location.valueqword) <= high(smallint)) then
  874. begin
  875. // consts16 - reg64
  876. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  877. location.registerlow,right.location.registerlow,
  878. aword(left.location.value)));
  879. end
  880. else
  881. begin
  882. // const32 - reg64
  883. location_force_reg(exprasmlist,left.location,
  884. OS_32,true);
  885. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
  886. location.registerlow,left.location.registerlow,
  887. right.location.registerlow));
  888. end;
  889. exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
  890. location.registerhigh,right.location.registerhigh));
  891. end
  892. else if (aword(left.location.valueqword) = 0) then
  893. begin
  894. // (const32 shl 32) - reg64
  895. if (location.registerlow = NR_NO) then
  896. begin
  897. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  898. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  899. end;
  900. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  901. location.registerlow,right.location.registerlow,0));
  902. left.location.valueqword := left.location.valueqword shr 32;
  903. location_force_reg(exprasmlist,left.location,OS_32,true);
  904. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
  905. location.registerhigh,right.location.registerhigh,
  906. left.location.register));
  907. end
  908. else
  909. begin
  910. // const64 - reg64
  911. location_force_reg(exprasmlist,left.location,
  912. def_cgsize(left.resulttype.def),false);
  913. if (left.location.loc = LOC_REGISTER) then
  914. location.register64 := left.location.register64
  915. else if (location.registerlow = NR_NO) then
  916. begin
  917. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  918. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  919. end;
  920. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  921. right.location.register64,left.location.register64,
  922. location.register64);
  923. end;
  924. end;
  925. else
  926. internalerror(2002072803);
  927. end;
  928. end
  929. else
  930. begin
  931. case nodetype of
  932. addn:
  933. begin
  934. op1 := A_ADDC;
  935. op2 := A_ADDEO_;
  936. end;
  937. subn:
  938. begin
  939. op1 := A_SUBC;
  940. op2 := A_SUBFEO_;
  941. end;
  942. else
  943. internalerror(2002072806);
  944. end;
  945. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
  946. left.location.registerlow,right.location.registerlow));
  947. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
  948. right.location.registerhigh,left.location.registerhigh));
  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. release_reg_left_right;
  958. end;
  959. {*****************************************************************************
  960. AddMMX
  961. *****************************************************************************}
  962. {$ifdef SUPPORT_MMX}
  963. procedure ti386addnode.second_addmmx;
  964. var
  965. op : TAsmOp;
  966. cmpop : boolean;
  967. mmxbase : tmmxtype;
  968. hregister : tregister;
  969. begin
  970. pass_left_and_right;
  971. cmpop:=false;
  972. mmxbase:=mmx_type(left.resulttype.def);
  973. case nodetype of
  974. addn :
  975. begin
  976. if (cs_mmx_saturation in aktlocalswitches) then
  977. begin
  978. case mmxbase of
  979. mmxs8bit:
  980. op:=A_PADDSB;
  981. mmxu8bit:
  982. op:=A_PADDUSB;
  983. mmxs16bit,mmxfixed16:
  984. op:=A_PADDSB;
  985. mmxu16bit:
  986. op:=A_PADDUSW;
  987. end;
  988. end
  989. else
  990. begin
  991. case mmxbase of
  992. mmxs8bit,mmxu8bit:
  993. op:=A_PADDB;
  994. mmxs16bit,mmxu16bit,mmxfixed16:
  995. op:=A_PADDW;
  996. mmxs32bit,mmxu32bit:
  997. op:=A_PADDD;
  998. end;
  999. end;
  1000. end;
  1001. muln :
  1002. begin
  1003. case mmxbase of
  1004. mmxs16bit,mmxu16bit:
  1005. op:=A_PMULLW;
  1006. mmxfixed16:
  1007. op:=A_PMULHW;
  1008. end;
  1009. end;
  1010. subn :
  1011. begin
  1012. if (cs_mmx_saturation in aktlocalswitches) then
  1013. begin
  1014. case mmxbase of
  1015. mmxs8bit:
  1016. op:=A_PSUBSB;
  1017. mmxu8bit:
  1018. op:=A_PSUBUSB;
  1019. mmxs16bit,mmxfixed16:
  1020. op:=A_PSUBSB;
  1021. mmxu16bit:
  1022. op:=A_PSUBUSW;
  1023. end;
  1024. end
  1025. else
  1026. begin
  1027. case mmxbase of
  1028. mmxs8bit,mmxu8bit:
  1029. op:=A_PSUBB;
  1030. mmxs16bit,mmxu16bit,mmxfixed16:
  1031. op:=A_PSUBW;
  1032. mmxs32bit,mmxu32bit:
  1033. op:=A_PSUBD;
  1034. end;
  1035. end;
  1036. end;
  1037. xorn:
  1038. op:=A_PXOR;
  1039. orn:
  1040. op:=A_POR;
  1041. andn:
  1042. op:=A_PAND;
  1043. else
  1044. CGMessage(type_e_mismatch);
  1045. end;
  1046. { left and right no register? }
  1047. { then one must be demanded }
  1048. if (left.location.loc<>LOC_MMXREGISTER) then
  1049. begin
  1050. if (right.location.loc=LOC_MMXREGISTER) then
  1051. begin
  1052. location_swap(left.location,right.location);
  1053. toggleflag(nf_swaped);
  1054. end
  1055. else
  1056. begin
  1057. { register variable ? }
  1058. if (left.location.loc=LOC_CMMXREGISTER) then
  1059. begin
  1060. hregister:=rg.getregistermm(exprasmlist);
  1061. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1062. end
  1063. else
  1064. begin
  1065. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1066. internalerror(200203245);
  1067. location_release(exprasmlist,left.location);
  1068. hregister:=rg.getregistermm(exprasmlist);
  1069. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1070. end;
  1071. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1072. left.location.register:=hregister;
  1073. end;
  1074. end;
  1075. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1076. if right.location.loc<>LOC_MMXREGISTER then
  1077. begin
  1078. if (nodetype=subn) and (nf_swaped in flags) then
  1079. begin
  1080. if right.location.loc=LOC_CMMXREGISTER then
  1081. begin
  1082. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1083. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1084. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1085. end
  1086. else
  1087. begin
  1088. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1089. internalerror(200203247);
  1090. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  1091. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1092. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1093. location_release(exprasmlist,right.location);
  1094. end;
  1095. end
  1096. else
  1097. begin
  1098. if (right.location.loc=LOC_CMMXREGISTER) then
  1099. begin
  1100. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1101. end
  1102. else
  1103. begin
  1104. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1105. internalerror(200203246);
  1106. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1107. location_release(exprasmlist,right.location);
  1108. end;
  1109. end;
  1110. end
  1111. else
  1112. begin
  1113. { right.location=LOC_MMXREGISTER }
  1114. if (nodetype=subn) and (nf_swaped in flags) then
  1115. begin
  1116. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1117. location_swap(left.location,right.location);
  1118. toggleflag(nf_swaped);
  1119. end
  1120. else
  1121. begin
  1122. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1123. end;
  1124. end;
  1125. location_freetemp(exprasmlist,right.location);
  1126. location_release(exprasmlist,right.location);
  1127. if cmpop then
  1128. begin
  1129. location_freetemp(exprasmlist,left.location);
  1130. location_release(exprasmlist,left.location);
  1131. end;
  1132. set_result_location(cmpop,true);
  1133. end;
  1134. {$endif SUPPORT_MMX}
  1135. {*****************************************************************************
  1136. pass_2
  1137. *****************************************************************************}
  1138. procedure tppcaddnode.pass_2;
  1139. { is also being used for xor, and "mul", "sub, or and comparative }
  1140. { operators }
  1141. var
  1142. cmpop : boolean;
  1143. cgop : topcg;
  1144. op : tasmop;
  1145. tmpreg : tregister;
  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 := rg.getregisterint(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. aword(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. aword(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 := rg.getregisterint(exprasmlist,OS_INT);
  1274. cg.a_load_const_reg(exprasmlist,OS_INT,
  1275. aword(left.location.value),tmpreg);
  1276. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1277. right.location.register,tmpreg,location.register);
  1278. rg.ungetregisterint(exprasmlist,tmpreg);
  1279. end;
  1280. end;
  1281. ltn,lten,gtn,gten,equaln,unequaln :
  1282. begin
  1283. emit_compare(unsigned);
  1284. end;
  1285. end;
  1286. end
  1287. else
  1288. // overflow checking is on and we have an addn, subn or muln
  1289. begin
  1290. case nodetype of
  1291. addn:
  1292. op := A_ADDO_;
  1293. subn:
  1294. op := A_SUBO_;
  1295. muln:
  1296. op := A_MULLWO_;
  1297. else
  1298. internalerror(2002072601);
  1299. end;
  1300. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1301. left.location.register,right.location.register));
  1302. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1303. end;
  1304. release_reg_left_right;
  1305. end;
  1306. begin
  1307. caddnode:=tppcaddnode;
  1308. end.
  1309. {
  1310. $Log$
  1311. Revision 1.35 2003-09-03 19:39:16 peter
  1312. * removed empty cga unit
  1313. Revision 1.34 2003/09/03 19:35:24 peter
  1314. * powerpc compiles again
  1315. Revision 1.33 2003/06/14 22:32:43 jonas
  1316. * ppc compiles with -dnewra, haven't tried to compile anything with it
  1317. yet though
  1318. Revision 1.32 2003/06/04 11:58:58 jonas
  1319. * calculate localsize also in g_return_from_proc since it's now called
  1320. before g_stackframe_entry (still have to fix macos)
  1321. * compilation fixes (cycle doesn't work yet though)
  1322. Revision 1.31 2003/06/01 21:38:06 peter
  1323. * getregisterfpu size parameter added
  1324. * op_const_reg size parameter added
  1325. * sparc updates
  1326. Revision 1.30 2003/05/30 18:49:14 jonas
  1327. * fixed problem where sometimes no register was allocated for the result
  1328. of an addnode when using regvars
  1329. Revision 1.29 2003/04/27 11:55:34 jonas
  1330. * fixed overflow checking form of 64bit add instruction
  1331. Revision 1.28 2003/04/27 11:06:06 jonas
  1332. * fixed 64bit "const - reg/ref" bugs
  1333. Revision 1.27 2003/04/24 22:29:58 florian
  1334. * fixed a lot of PowerPC related stuff
  1335. Revision 1.26 2003/04/23 22:18:01 peter
  1336. * fixes to get rtl compiled
  1337. Revision 1.25 2003/04/23 12:35:35 florian
  1338. * fixed several issues with powerpc
  1339. + applied a patch from Jonas for nested function calls (PowerPC only)
  1340. * ...
  1341. Revision 1.24 2003/03/11 21:46:24 jonas
  1342. * lots of new regallocator fixes, both in generic and ppc-specific code
  1343. (ppc compiler still can't compile the linux system unit though)
  1344. Revision 1.23 2003/03/10 18:11:41 olle
  1345. * changed ungetregister to ungetregisterint in tppcaddnode.clear_left_right
  1346. Revision 1.22 2003/02/19 22:00:16 daniel
  1347. * Code generator converted to new register notation
  1348. - Horribily outdated todo.txt removed
  1349. Revision 1.21 2003/01/08 18:43:58 daniel
  1350. * Tregister changed into a record
  1351. Revision 1.20 2002/11/25 17:43:27 peter
  1352. * splitted defbase in defutil,symutil,defcmp
  1353. * merged isconvertable and is_equal into compare_defs(_ext)
  1354. * made operator search faster by walking the list only once
  1355. Revision 1.19 2002/10/21 18:08:05 jonas
  1356. * some range errors fixed
  1357. Revision 1.18 2002/09/08 14:14:49 jonas
  1358. * more optimizations for 64bit compares
  1359. Revision 1.17 2002/09/07 22:15:48 jonas
  1360. * fixed optimized 64 compares
  1361. Revision 1.16 2002/09/04 19:42:45 jonas
  1362. * fixed bugs in 64bit operations (registers weren't always allocated for
  1363. the result)
  1364. * optimized 'const64 - reg64/mem64'
  1365. * optimized equaln/unequaln with 64bit values (change them to
  1366. '(left.hi xor right.hi) or (left.lo xor right.lo)' so there are less
  1367. branches and the result can be returned in the flags this way. Could
  1368. be done for the i386 too probably.
  1369. Revision 1.15 2002/08/31 21:30:46 florian
  1370. * fixed several problems caused by Jonas' commit :)
  1371. Revision 1.14 2002/08/31 19:26:20 jonas
  1372. * fixed 64bit comparisons
  1373. Revision 1.13 2002/08/17 22:09:47 florian
  1374. * result type handling in tcgcal.pass_2 overhauled
  1375. * better tnode.dowrite
  1376. * some ppc stuff fixed
  1377. Revision 1.12 2002/08/14 18:41:48 jonas
  1378. - remove valuelow/valuehigh fields from tlocation, because they depend
  1379. on the endianess of the host operating system -> difficult to get
  1380. right. Use lo/hi(location.valueqword) instead (remember to use
  1381. valueqword and not value!!)
  1382. Revision 1.11 2002/08/11 14:32:32 peter
  1383. * renamed current_library to objectlibrary
  1384. Revision 1.10 2002/08/11 13:24:18 peter
  1385. * saving of asmsymbols in ppu supported
  1386. * asmsymbollist global is removed and moved into a new class
  1387. tasmlibrarydata that will hold the info of a .a file which
  1388. corresponds with a single module. Added librarydata to tmodule
  1389. to keep the library info stored for the module. In the future the
  1390. objectfiles will also be stored to the tasmlibrarydata class
  1391. * all getlabel/newasmsymbol and friends are moved to the new class
  1392. Revision 1.9 2002/08/11 11:40:16 jonas
  1393. * some overflow checking fixes
  1394. Revision 1.8 2002/08/11 06:14:40 florian
  1395. * fixed powerpc compilation problems
  1396. Revision 1.7 2002/08/10 17:15:31 jonas
  1397. * various fixes and optimizations
  1398. Revision 1.6 2002/08/06 20:55:24 florian
  1399. * first part of ppc calling conventions fix
  1400. Revision 1.5 2002/08/05 08:58:54 jonas
  1401. * fixed compilation problems
  1402. Revision 1.4 2002/08/04 12:57:56 jonas
  1403. * more misc. fixes, mostly constant-related
  1404. Revision 1.3 2002/07/28 16:02:49 jonas
  1405. + 64 bit operations (badly tested), everything is implemented now!
  1406. * some small fixes
  1407. Revision 1.2 2002/07/27 20:00:59 jonas
  1408. + second_addboolean(), second_addfloat() and second_addsmallset()
  1409. (64bit stuff is all that's left to do)
  1410. Revision 1.1 2002/07/26 12:31:57 jonas
  1411. + intial implementation of add nodes, only integer/enumeration/pointer/...
  1412. handling is finished
  1413. }