nppcadd.pas 58 KB

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