nppcadd.pas 60 KB

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