nppcadd.pas 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573
  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,
  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.36 2003-10-01 20:34:49 peter
  1312. * procinfo unit contains tprocinfo
  1313. * cginfo renamed to cgbase
  1314. * moved cgmessage to verbose
  1315. * fixed ppc and sparc compiles
  1316. Revision 1.35 2003/09/03 19:39:16 peter
  1317. * removed empty cga unit
  1318. Revision 1.34 2003/09/03 19:35:24 peter
  1319. * powerpc compiles again
  1320. Revision 1.33 2003/06/14 22:32:43 jonas
  1321. * ppc compiles with -dnewra, haven't tried to compile anything with it
  1322. yet though
  1323. Revision 1.32 2003/06/04 11:58:58 jonas
  1324. * calculate localsize also in g_return_from_proc since it's now called
  1325. before g_stackframe_entry (still have to fix macos)
  1326. * compilation fixes (cycle doesn't work yet though)
  1327. Revision 1.31 2003/06/01 21:38:06 peter
  1328. * getregisterfpu size parameter added
  1329. * op_const_reg size parameter added
  1330. * sparc updates
  1331. Revision 1.30 2003/05/30 18:49:14 jonas
  1332. * fixed problem where sometimes no register was allocated for the result
  1333. of an addnode when using regvars
  1334. Revision 1.29 2003/04/27 11:55:34 jonas
  1335. * fixed overflow checking form of 64bit add instruction
  1336. Revision 1.28 2003/04/27 11:06:06 jonas
  1337. * fixed 64bit "const - reg/ref" bugs
  1338. Revision 1.27 2003/04/24 22:29:58 florian
  1339. * fixed a lot of PowerPC related stuff
  1340. Revision 1.26 2003/04/23 22:18:01 peter
  1341. * fixes to get rtl compiled
  1342. Revision 1.25 2003/04/23 12:35:35 florian
  1343. * fixed several issues with powerpc
  1344. + applied a patch from Jonas for nested function calls (PowerPC only)
  1345. * ...
  1346. Revision 1.24 2003/03/11 21:46:24 jonas
  1347. * lots of new regallocator fixes, both in generic and ppc-specific code
  1348. (ppc compiler still can't compile the linux system unit though)
  1349. Revision 1.23 2003/03/10 18:11:41 olle
  1350. * changed ungetregister to ungetregisterint in tppcaddnode.clear_left_right
  1351. Revision 1.22 2003/02/19 22:00:16 daniel
  1352. * Code generator converted to new register notation
  1353. - Horribily outdated todo.txt removed
  1354. Revision 1.21 2003/01/08 18:43:58 daniel
  1355. * Tregister changed into a record
  1356. Revision 1.20 2002/11/25 17:43:27 peter
  1357. * splitted defbase in defutil,symutil,defcmp
  1358. * merged isconvertable and is_equal into compare_defs(_ext)
  1359. * made operator search faster by walking the list only once
  1360. Revision 1.19 2002/10/21 18:08:05 jonas
  1361. * some range errors fixed
  1362. Revision 1.18 2002/09/08 14:14:49 jonas
  1363. * more optimizations for 64bit compares
  1364. Revision 1.17 2002/09/07 22:15:48 jonas
  1365. * fixed optimized 64 compares
  1366. Revision 1.16 2002/09/04 19:42:45 jonas
  1367. * fixed bugs in 64bit operations (registers weren't always allocated for
  1368. the result)
  1369. * optimized 'const64 - reg64/mem64'
  1370. * optimized equaln/unequaln with 64bit values (change them to
  1371. '(left.hi xor right.hi) or (left.lo xor right.lo)' so there are less
  1372. branches and the result can be returned in the flags this way. Could
  1373. be done for the i386 too probably.
  1374. Revision 1.15 2002/08/31 21:30:46 florian
  1375. * fixed several problems caused by Jonas' commit :)
  1376. Revision 1.14 2002/08/31 19:26:20 jonas
  1377. * fixed 64bit comparisons
  1378. Revision 1.13 2002/08/17 22:09:47 florian
  1379. * result type handling in tcgcal.pass_2 overhauled
  1380. * better tnode.dowrite
  1381. * some ppc stuff fixed
  1382. Revision 1.12 2002/08/14 18:41:48 jonas
  1383. - remove valuelow/valuehigh fields from tlocation, because they depend
  1384. on the endianess of the host operating system -> difficult to get
  1385. right. Use lo/hi(location.valueqword) instead (remember to use
  1386. valueqword and not value!!)
  1387. Revision 1.11 2002/08/11 14:32:32 peter
  1388. * renamed current_library to objectlibrary
  1389. Revision 1.10 2002/08/11 13:24:18 peter
  1390. * saving of asmsymbols in ppu supported
  1391. * asmsymbollist global is removed and moved into a new class
  1392. tasmlibrarydata that will hold the info of a .a file which
  1393. corresponds with a single module. Added librarydata to tmodule
  1394. to keep the library info stored for the module. In the future the
  1395. objectfiles will also be stored to the tasmlibrarydata class
  1396. * all getlabel/newasmsymbol and friends are moved to the new class
  1397. Revision 1.9 2002/08/11 11:40:16 jonas
  1398. * some overflow checking fixes
  1399. Revision 1.8 2002/08/11 06:14:40 florian
  1400. * fixed powerpc compilation problems
  1401. Revision 1.7 2002/08/10 17:15:31 jonas
  1402. * various fixes and optimizations
  1403. Revision 1.6 2002/08/06 20:55:24 florian
  1404. * first part of ppc calling conventions fix
  1405. Revision 1.5 2002/08/05 08:58:54 jonas
  1406. * fixed compilation problems
  1407. Revision 1.4 2002/08/04 12:57:56 jonas
  1408. * more misc. fixes, mostly constant-related
  1409. Revision 1.3 2002/07/28 16:02:49 jonas
  1410. + 64 bit operations (badly tested), everything is implemented now!
  1411. * some small fixes
  1412. Revision 1.2 2002/07/27 20:00:59 jonas
  1413. + second_addboolean(), second_addfloat() and second_addsmallset()
  1414. (64bit stuff is all that's left to do)
  1415. Revision 1.1 2002/07/26 12:31:57 jonas
  1416. + intial implementation of add nodes, only integer/enumeration/pointer/...
  1417. handling is finished
  1418. }