nppcadd.pas 55 KB

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