nppcadd.pas 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555
  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,defutil,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.enum <> right.location.register.enum)) 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.enum <> left.location.register.enum)) 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. r : Tregister;
  405. procedure location_force_fpureg(var l: tlocation);
  406. begin
  407. if not(l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
  408. begin
  409. reg := rg.getregisterfpu(exprasmlist);
  410. cg.a_loadfpu_loc_reg(exprasmlist,l,reg);
  411. location_freetemp(exprasmlist,l);
  412. location_release(exprasmlist,l);
  413. location_reset(l,LOC_FPUREGISTER,l.size);
  414. l.register := reg;
  415. end;
  416. end;
  417. begin
  418. pass_left_and_right;
  419. cmpop:=false;
  420. case nodetype of
  421. addn :
  422. op:=A_FADD;
  423. muln :
  424. op:=A_FMUL;
  425. subn :
  426. op:=A_FSUB;
  427. slashn :
  428. op:=A_FDIV;
  429. ltn,lten,gtn,gten,
  430. equaln,unequaln :
  431. begin
  432. op:=A_FCMPO;
  433. cmpop:=true;
  434. end;
  435. else
  436. CGMessage(type_e_mismatch);
  437. end;
  438. // get the operands in the correct order, there are no special cases
  439. // here, everything is register-based
  440. if nf_swaped in flags then
  441. swapleftright;
  442. // put both operands in a register
  443. location_force_fpureg(right.location);
  444. location_force_fpureg(left.location);
  445. // initialize de result
  446. if not cmpop then
  447. begin
  448. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  449. if left.location.loc = LOC_FPUREGISTER then
  450. location.register := left.location.register
  451. else if right.location.loc = LOC_FPUREGISTER then
  452. location.register := right.location.register
  453. else
  454. location.register := rg.getregisterfpu(exprasmlist);
  455. end
  456. else
  457. begin
  458. location_reset(location,LOC_FLAGS,OS_NO);
  459. location.resflags := getresflags;
  460. end;
  461. // emit the actual operation
  462. if not cmpop then
  463. begin
  464. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  465. location.register,left.location.register,
  466. right.location.register))
  467. end
  468. else
  469. begin
  470. r.enum:=location.resflags.cr;
  471. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  472. r,left.location.register,right.location.register))
  473. end;
  474. clear_left_right(cmpop);
  475. end;
  476. {*****************************************************************************
  477. AddSmallSet
  478. *****************************************************************************}
  479. procedure tppcaddnode.second_addsmallset;
  480. var
  481. cgop : TOpCg;
  482. tmpreg : tregister;
  483. opdone,
  484. cmpop : boolean;
  485. begin
  486. pass_left_and_right;
  487. { when a setdef is passed, it has to be a smallset }
  488. if ((left.resulttype.def.deftype=setdef) and
  489. (tsetdef(left.resulttype.def).settype<>smallset)) or
  490. ((right.resulttype.def.deftype=setdef) and
  491. (tsetdef(right.resulttype.def).settype<>smallset)) then
  492. internalerror(200203301);
  493. opdone := false;
  494. cmpop:=nodetype in [equaln,unequaln,lten,gten];
  495. { set result location }
  496. if not cmpop then
  497. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  498. else
  499. location_reset(location,LOC_FLAGS,OS_NO);
  500. load_left_right(cmpop,false);
  501. if not(cmpop) and
  502. (location.register.enum = R_NO) then
  503. location.register := rg.getregisterint(exprasmlist);
  504. case nodetype of
  505. addn :
  506. begin
  507. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  508. swapleftright;
  509. { are we adding set elements ? }
  510. if right.nodetype=setelementn then
  511. begin
  512. { no range support for smallsets! }
  513. if assigned(tsetelementnode(right).right) then
  514. internalerror(43244);
  515. if (right.location.loc = LOC_CONSTANT) then
  516. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  517. aword(1 shl aword(right.location.value)),
  518. left.location.register,location.register)
  519. else
  520. begin
  521. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  522. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  523. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  524. right.location.register,tmpreg);
  525. if left.location.loc <> LOC_CONSTANT then
  526. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  527. left.location.register,location.register)
  528. else
  529. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  530. aword(left.location.value),tmpreg,location.register);
  531. cg.free_scratch_reg(exprasmlist,tmpreg);
  532. end;
  533. opdone := true;
  534. end
  535. else
  536. cgop := OP_OR;
  537. end;
  538. symdifn :
  539. cgop:=OP_XOR;
  540. muln :
  541. cgop:=OP_AND;
  542. subn :
  543. begin
  544. cgop:=OP_AND;
  545. if (not(nf_swaped in flags)) then
  546. if (right.location.loc=LOC_CONSTANT) then
  547. right.location.value := not(right.location.value)
  548. else
  549. opdone := true
  550. else if (left.location.loc=LOC_CONSTANT) then
  551. left.location.value := not(left.location.value)
  552. else
  553. begin
  554. swapleftright;
  555. opdone := true;
  556. end;
  557. if opdone then
  558. begin
  559. if left.location.loc = LOC_CONSTANT then
  560. begin
  561. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  562. cg.a_load_const_reg(exprasmlist,OS_INT,
  563. aword(left.location.value),tmpreg);
  564. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  565. location.register,tmpreg,right.location.register));
  566. cg.free_scratch_reg(exprasmlist,tmpreg);
  567. end
  568. else
  569. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  570. location.register,left.location.register,
  571. right.location.register));
  572. end;
  573. end;
  574. equaln,
  575. unequaln :
  576. begin
  577. emit_compare(true);
  578. opdone := true;
  579. end;
  580. lten,gten:
  581. begin
  582. If (not(nf_swaped in flags) and
  583. (nodetype = lten)) or
  584. ((nf_swaped in flags) and
  585. (nodetype = gten)) then
  586. swapleftright;
  587. // now we have to check whether left >= right
  588. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  589. if left.location.loc = LOC_CONSTANT then
  590. begin
  591. cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
  592. not(left.location.value),right.location.register,tmpreg);
  593. exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
  594. // the two instructions above should be folded together by
  595. // the peepholeoptimizer
  596. end
  597. else
  598. begin
  599. if right.location.loc = LOC_CONSTANT then
  600. begin
  601. cg.a_load_const_reg(exprasmlist,OS_INT,
  602. aword(right.location.value),tmpreg);
  603. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  604. tmpreg,left.location.register));
  605. end
  606. else
  607. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  608. right.location.register,left.location.register));
  609. end;
  610. cg.free_scratch_reg(exprasmlist,tmpreg);
  611. location.resflags.cr := R_CR0;
  612. location.resflags.flag := F_EQ;
  613. opdone := true;
  614. end;
  615. else
  616. internalerror(2002072701);
  617. end;
  618. if not opdone then
  619. begin
  620. // these are all commutative operations
  621. if (left.location.loc = LOC_CONSTANT) then
  622. swapleftright;
  623. if (right.location.loc = LOC_CONSTANT) then
  624. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  625. aword(right.location.value),left.location.register,
  626. location.register)
  627. else
  628. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  629. right.location.register,left.location.register,
  630. location.register);
  631. end;
  632. clear_left_right(cmpop);
  633. end;
  634. {*****************************************************************************
  635. Add64bit
  636. *****************************************************************************}
  637. procedure tppcaddnode.second_add64bit;
  638. var
  639. op : TOpCG;
  640. op1,op2 : TAsmOp;
  641. hl4 : tasmlabel;
  642. cmpop,
  643. unsigned : boolean;
  644. r : Tregister;
  645. procedure emit_cmp64_hi;
  646. var
  647. oldleft, oldright: tlocation;
  648. begin
  649. // put the high part of the location in the low part
  650. location_copy(oldleft,left.location);
  651. location_copy(oldright,right.location);
  652. if left.location.loc = LOC_CONSTANT then
  653. left.location.valueqword := left.location.valueqword shr 32
  654. else
  655. left.location.registerlow := left.location.registerhigh;
  656. if right.location.loc = LOC_CONSTANT then
  657. right.location.valueqword := right.location.valueqword shr 32
  658. else
  659. right.location.registerlow := right.location.registerhigh;
  660. // and call the normal emit_compare
  661. emit_compare(unsigned);
  662. location_copy(left.location,oldleft);
  663. location_copy(right.location,oldright);
  664. end;
  665. procedure emit_cmp64_lo;
  666. begin
  667. emit_compare(true);
  668. end;
  669. procedure firstjmp64bitcmp;
  670. var
  671. oldnodetype: tnodetype;
  672. begin
  673. load_all_regvars(exprasmlist);
  674. { the jump the sequence is a little bit hairy }
  675. case nodetype of
  676. ltn,gtn:
  677. begin
  678. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  679. { cheat a little bit for the negative test }
  680. toggleflag(nf_swaped);
  681. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  682. toggleflag(nf_swaped);
  683. end;
  684. lten,gten:
  685. begin
  686. oldnodetype:=nodetype;
  687. if nodetype=lten then
  688. nodetype:=ltn
  689. else
  690. nodetype:=gtn;
  691. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  692. { cheat for the negative test }
  693. if nodetype=ltn then
  694. nodetype:=gtn
  695. else
  696. nodetype:=ltn;
  697. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  698. nodetype:=oldnodetype;
  699. end;
  700. equaln:
  701. begin
  702. nodetype := unequaln;
  703. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  704. nodetype := equaln;
  705. end;
  706. unequaln:
  707. begin
  708. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  709. end;
  710. end;
  711. end;
  712. procedure secondjmp64bitcmp;
  713. begin
  714. { the jump the sequence is a little bit hairy }
  715. case nodetype of
  716. ltn,gtn,lten,gten:
  717. begin
  718. { the comparison of the low dword always has }
  719. { to be always unsigned! }
  720. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  721. cg.a_jmp_always(exprasmlist,falselabel);
  722. end;
  723. equaln:
  724. begin
  725. nodetype := unequaln;
  726. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  727. cg.a_jmp_always(exprasmlist,truelabel);
  728. nodetype := equaln;
  729. end;
  730. unequaln:
  731. begin
  732. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  733. cg.a_jmp_always(exprasmlist,falselabel);
  734. end;
  735. end;
  736. end;
  737. var
  738. tempreg64: tregister64;
  739. begin
  740. firstcomplex(self);
  741. pass_left_and_right;
  742. cmpop:=false;
  743. unsigned:=((left.resulttype.def.deftype=orddef) and
  744. (torddef(left.resulttype.def).typ=u64bit)) or
  745. ((right.resulttype.def.deftype=orddef) and
  746. (torddef(right.resulttype.def).typ=u64bit));
  747. case nodetype of
  748. addn :
  749. begin
  750. op:=OP_ADD;
  751. end;
  752. subn :
  753. begin
  754. op:=OP_SUB;
  755. end;
  756. ltn,lten,
  757. gtn,gten,
  758. equaln,unequaln:
  759. begin
  760. op:=OP_NONE;
  761. cmpop:=true;
  762. end;
  763. xorn:
  764. op:=OP_XOR;
  765. orn:
  766. op:=OP_OR;
  767. andn:
  768. op:=OP_AND;
  769. muln:
  770. begin
  771. { should be handled in pass_1 (JM) }
  772. internalerror(200109051);
  773. end;
  774. else
  775. internalerror(2002072705);
  776. end;
  777. if not cmpop then
  778. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  779. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  780. (nodetype in [addn,subn]));
  781. if not(cs_check_overflow in aktlocalswitches) or
  782. not(nodetype in [addn,subn]) then
  783. begin
  784. case nodetype of
  785. ltn,lten,
  786. gtn,gten:
  787. begin
  788. emit_cmp64_hi;
  789. firstjmp64bitcmp;
  790. emit_cmp64_lo;
  791. secondjmp64bitcmp;
  792. end;
  793. equaln,unequaln:
  794. begin
  795. // instead of doing a complicated compare, do
  796. // (left.hi xor right.hi) or (left.lo xor right.lo)
  797. // (somewhate optimized so that no superfluous 'mr's are
  798. // generated)
  799. if (left.location.loc = LOC_CONSTANT) then
  800. swapleftright;
  801. if (right.location.loc = LOC_CONSTANT) then
  802. begin
  803. if left.location.loc = LOC_REGISTER then
  804. begin
  805. tempreg64.reglo := left.location.registerlow;
  806. tempreg64.reghi := left.location.registerhigh;
  807. end
  808. else
  809. begin
  810. if (aword(right.location.valueqword) <> 0) then
  811. tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist)
  812. else
  813. tempreg64.reglo := left.location.registerlow;
  814. if ((right.location.valueqword shr 32) <> 0) then
  815. tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist)
  816. else
  817. tempreg64.reghi := left.location.registerhigh;
  818. end;
  819. if (aword(right.location.valueqword) <> 0) then
  820. { negative values can be handled using SUB, }
  821. { positive values < 65535 using XOR. }
  822. if (longint(right.location.valueqword) >= -32767) and
  823. (longint(right.location.valueqword) < 0) then
  824. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  825. aword(right.location.valueqword),
  826. left.location.registerlow,tempreg64.reglo)
  827. else
  828. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  829. aword(right.location.valueqword),
  830. left.location.registerlow,tempreg64.reglo);
  831. if ((right.location.valueqword shr 32) <> 0) then
  832. if (longint(right.location.valueqword shr 32) >= -32767) and
  833. (longint(right.location.valueqword shr 32) < 0) then
  834. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  835. aword(right.location.valueqword shr 32),
  836. left.location.registerhigh,tempreg64.reghi)
  837. else
  838. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  839. aword(right.location.valueqword shr 32),
  840. left.location.registerhigh,tempreg64.reghi);
  841. end
  842. else
  843. begin
  844. tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist);
  845. tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist);
  846. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
  847. left.location.register64,right.location.register64,
  848. tempreg64);
  849. end;
  850. r.enum:=R_0;
  851. cg.a_reg_alloc(exprasmlist,r);
  852. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,r,
  853. tempreg64.reglo,tempreg64.reghi));
  854. cg.a_reg_dealloc(exprasmlist,r);
  855. if (tempreg64.reglo.enum <> left.location.registerlow.enum) then
  856. cg.free_scratch_reg(exprasmlist,tempreg64.reglo);
  857. if (tempreg64.reghi.enum <> left.location.registerhigh.enum) then
  858. cg.free_scratch_reg(exprasmlist,tempreg64.reghi);
  859. location_reset(location,LOC_FLAGS,OS_NO);
  860. location.resflags := getresflags;
  861. end;
  862. xorn,orn,andn,addn:
  863. begin
  864. if (location.registerlow.enum = R_NO) then
  865. begin
  866. location.registerlow := rg.getregisterint(exprasmlist);
  867. location.registerhigh := rg.getregisterint(exprasmlist);
  868. end;
  869. if (left.location.loc = LOC_CONSTANT) then
  870. swapleftright;
  871. if (right.location.loc = LOC_CONSTANT) then
  872. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
  873. left.location.register64,location.register64)
  874. else
  875. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  876. left.location.register64,location.register64);
  877. end;
  878. subn:
  879. begin
  880. if (nf_swaped in flags) then
  881. swapleftright;
  882. if left.location.loc <> LOC_CONSTANT then
  883. begin
  884. if (location.registerlow.enum = R_NO) then
  885. begin
  886. location.registerlow := rg.getregisterint(exprasmlist);
  887. location.registerhigh := rg.getregisterint(exprasmlist);
  888. end;
  889. if right.location.loc <> LOC_CONSTANT then
  890. // reg64 - reg64
  891. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  892. right.location.register64,left.location.register64,
  893. location.register64)
  894. else
  895. // reg64 - const64
  896. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  897. right.location.valueqword,left.location.register64,
  898. location.register64)
  899. end
  900. else if ((left.location.valueqword shr 32) = 0) then
  901. begin
  902. if (location.registerlow.enum = R_NO) then
  903. begin
  904. location.registerlow := rg.getregisterint(exprasmlist);
  905. location.registerhigh := rg.getregisterint(exprasmlist);
  906. end;
  907. if (int64(left.location.valueqword) >= low(smallint)) and
  908. (int64(left.location.valueqword) <= high(smallint)) then
  909. begin
  910. // consts16 - reg64
  911. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  912. location.registerlow,right.location.registerlow,
  913. aword(left.location.value)));
  914. end
  915. else
  916. begin
  917. // const32 - reg64
  918. cg.a_load_const_reg(exprasmlist,OS_32,
  919. aword(left.location.valueqword),location.registerlow);
  920. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
  921. location.registerlow,location.registerlow,
  922. right.location.registerlow));
  923. end;
  924. exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
  925. location.registerhigh,right.location.registerhigh));
  926. end
  927. else if (aword(left.location.valueqword) = 0) then
  928. begin
  929. // (const32 shl 32) - reg64
  930. if (location.registerlow.enum = R_NO) then
  931. begin
  932. location.registerlow := rg.getregisterint(exprasmlist);
  933. location.registerhigh := rg.getregisterint(exprasmlist);
  934. end;
  935. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  936. location.registerlow,right.location.registerlow,0));
  937. cg.a_load_const_reg(exprasmlist,OS_INT,
  938. left.location.valueqword shr 32,location.registerhigh);
  939. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
  940. location.registerhigh,right.location.registerhigh,
  941. location.registerhigh));
  942. end
  943. else
  944. begin
  945. // const64 - reg64
  946. location_force_reg(exprasmlist,left.location,
  947. def_cgsize(left.resulttype.def),true);
  948. if (left.location.loc = LOC_REGISTER) then
  949. location.register64 := left.location.register64
  950. else if (location.registerlow.enum = R_NO) then
  951. begin
  952. location.registerlow := rg.getregisterint(exprasmlist);
  953. location.registerhigh := rg.getregisterint(exprasmlist);
  954. end;
  955. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  956. right.location.register64,left.location.register64,
  957. location.register64);
  958. end;
  959. end;
  960. else
  961. internalerror(2002072803);
  962. end;
  963. end
  964. else
  965. begin
  966. case nodetype of
  967. addn:
  968. begin
  969. op1 := A_ADDC;
  970. op2 := A_ADDZEO_;
  971. end;
  972. subn:
  973. begin
  974. op1 := A_SUBC;
  975. op2 := A_SUBFEO_;
  976. end;
  977. else
  978. internalerror(2002072806);
  979. end;
  980. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
  981. left.location.registerlow,right.location.registerlow));
  982. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
  983. right.location.registerhigh,left.location.registerhigh));
  984. cg.g_overflowcheck(exprasmlist,self);
  985. end;
  986. { set result location }
  987. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  988. { real location only now) (JM) }
  989. if cmpop and
  990. not(nodetype in [equaln,unequaln]) then
  991. location_reset(location,LOC_JUMP,OS_NO);
  992. clear_left_right(cmpop);
  993. end;
  994. {*****************************************************************************
  995. AddMMX
  996. *****************************************************************************}
  997. {$ifdef SUPPORT_MMX}
  998. procedure ti386addnode.second_addmmx;
  999. var
  1000. op : TAsmOp;
  1001. cmpop : boolean;
  1002. mmxbase : tmmxtype;
  1003. hregister : tregister;
  1004. begin
  1005. pass_left_and_right;
  1006. cmpop:=false;
  1007. mmxbase:=mmx_type(left.resulttype.def);
  1008. case nodetype of
  1009. addn :
  1010. begin
  1011. if (cs_mmx_saturation in aktlocalswitches) then
  1012. begin
  1013. case mmxbase of
  1014. mmxs8bit:
  1015. op:=A_PADDSB;
  1016. mmxu8bit:
  1017. op:=A_PADDUSB;
  1018. mmxs16bit,mmxfixed16:
  1019. op:=A_PADDSB;
  1020. mmxu16bit:
  1021. op:=A_PADDUSW;
  1022. end;
  1023. end
  1024. else
  1025. begin
  1026. case mmxbase of
  1027. mmxs8bit,mmxu8bit:
  1028. op:=A_PADDB;
  1029. mmxs16bit,mmxu16bit,mmxfixed16:
  1030. op:=A_PADDW;
  1031. mmxs32bit,mmxu32bit:
  1032. op:=A_PADDD;
  1033. end;
  1034. end;
  1035. end;
  1036. muln :
  1037. begin
  1038. case mmxbase of
  1039. mmxs16bit,mmxu16bit:
  1040. op:=A_PMULLW;
  1041. mmxfixed16:
  1042. op:=A_PMULHW;
  1043. end;
  1044. end;
  1045. subn :
  1046. begin
  1047. if (cs_mmx_saturation in aktlocalswitches) then
  1048. begin
  1049. case mmxbase of
  1050. mmxs8bit:
  1051. op:=A_PSUBSB;
  1052. mmxu8bit:
  1053. op:=A_PSUBUSB;
  1054. mmxs16bit,mmxfixed16:
  1055. op:=A_PSUBSB;
  1056. mmxu16bit:
  1057. op:=A_PSUBUSW;
  1058. end;
  1059. end
  1060. else
  1061. begin
  1062. case mmxbase of
  1063. mmxs8bit,mmxu8bit:
  1064. op:=A_PSUBB;
  1065. mmxs16bit,mmxu16bit,mmxfixed16:
  1066. op:=A_PSUBW;
  1067. mmxs32bit,mmxu32bit:
  1068. op:=A_PSUBD;
  1069. end;
  1070. end;
  1071. end;
  1072. xorn:
  1073. op:=A_PXOR;
  1074. orn:
  1075. op:=A_POR;
  1076. andn:
  1077. op:=A_PAND;
  1078. else
  1079. CGMessage(type_e_mismatch);
  1080. end;
  1081. { left and right no register? }
  1082. { then one must be demanded }
  1083. if (left.location.loc<>LOC_MMXREGISTER) then
  1084. begin
  1085. if (right.location.loc=LOC_MMXREGISTER) then
  1086. begin
  1087. location_swap(left.location,right.location);
  1088. toggleflag(nf_swaped);
  1089. end
  1090. else
  1091. begin
  1092. { register variable ? }
  1093. if (left.location.loc=LOC_CMMXREGISTER) then
  1094. begin
  1095. hregister:=rg.getregistermm(exprasmlist);
  1096. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1097. end
  1098. else
  1099. begin
  1100. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1101. internalerror(200203245);
  1102. location_release(exprasmlist,left.location);
  1103. hregister:=rg.getregistermm(exprasmlist);
  1104. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1105. end;
  1106. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1107. left.location.register:=hregister;
  1108. end;
  1109. end;
  1110. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1111. if right.location.loc<>LOC_MMXREGISTER then
  1112. begin
  1113. if (nodetype=subn) and (nf_swaped in flags) then
  1114. begin
  1115. if right.location.loc=LOC_CMMXREGISTER then
  1116. begin
  1117. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1118. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1119. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1120. end
  1121. else
  1122. begin
  1123. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1124. internalerror(200203247);
  1125. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  1126. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1127. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1128. location_release(exprasmlist,right.location);
  1129. end;
  1130. end
  1131. else
  1132. begin
  1133. if (right.location.loc=LOC_CMMXREGISTER) then
  1134. begin
  1135. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1136. end
  1137. else
  1138. begin
  1139. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1140. internalerror(200203246);
  1141. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1142. location_release(exprasmlist,right.location);
  1143. end;
  1144. end;
  1145. end
  1146. else
  1147. begin
  1148. { right.location=LOC_MMXREGISTER }
  1149. if (nodetype=subn) and (nf_swaped in flags) then
  1150. begin
  1151. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1152. location_swap(left.location,right.location);
  1153. toggleflag(nf_swaped);
  1154. end
  1155. else
  1156. begin
  1157. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1158. end;
  1159. end;
  1160. location_freetemp(exprasmlist,right.location);
  1161. location_release(exprasmlist,right.location);
  1162. if cmpop then
  1163. begin
  1164. location_freetemp(exprasmlist,left.location);
  1165. location_release(exprasmlist,left.location);
  1166. end;
  1167. set_result_location(cmpop,true);
  1168. end;
  1169. {$endif SUPPORT_MMX}
  1170. {*****************************************************************************
  1171. pass_2
  1172. *****************************************************************************}
  1173. procedure tppcaddnode.pass_2;
  1174. { is also being used for xor, and "mul", "sub, or and comparative }
  1175. { operators }
  1176. var
  1177. cmpop : boolean;
  1178. cgop : topcg;
  1179. op : tasmop;
  1180. tmpreg : tregister;
  1181. { true, if unsigned types are compared }
  1182. unsigned : boolean;
  1183. regstopush: tregisterset;
  1184. begin
  1185. { to make it more readable, string and set (not smallset!) have their
  1186. own procedures }
  1187. case left.resulttype.def.deftype of
  1188. orddef :
  1189. begin
  1190. { handling boolean expressions }
  1191. if is_boolean(left.resulttype.def) and
  1192. is_boolean(right.resulttype.def) then
  1193. begin
  1194. second_addboolean;
  1195. exit;
  1196. end
  1197. { 64bit operations }
  1198. else if is_64bitint(left.resulttype.def) then
  1199. begin
  1200. second_add64bit;
  1201. exit;
  1202. end;
  1203. end;
  1204. stringdef :
  1205. begin
  1206. internalerror(2002072402);
  1207. exit;
  1208. end;
  1209. setdef :
  1210. begin
  1211. { normalsets are already handled in pass1 }
  1212. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1213. internalerror(200109041);
  1214. second_addsmallset;
  1215. exit;
  1216. end;
  1217. arraydef :
  1218. begin
  1219. {$ifdef SUPPORT_MMX}
  1220. if is_mmx_able_array(left.resulttype.def) then
  1221. begin
  1222. second_addmmx;
  1223. exit;
  1224. end;
  1225. {$endif SUPPORT_MMX}
  1226. end;
  1227. floatdef :
  1228. begin
  1229. second_addfloat;
  1230. exit;
  1231. end;
  1232. end;
  1233. { defaults }
  1234. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1235. unsigned:=not(is_signed(left.resulttype.def)) or
  1236. not(is_signed(right.resulttype.def));
  1237. pass_left_and_right;
  1238. { Convert flags to register first }
  1239. { can any of these things be in the flags actually?? (JM) }
  1240. if (left.location.loc = LOC_FLAGS) or
  1241. (right.location.loc = LOC_FLAGS) then
  1242. internalerror(2002072602);
  1243. { set result location }
  1244. if not cmpop then
  1245. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1246. else
  1247. location_reset(location,LOC_FLAGS,OS_NO);
  1248. load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
  1249. (nodetype in [addn,subn,muln]));
  1250. if (location.register.enum = R_NO) and
  1251. not(cmpop) then
  1252. location.register := rg.getregisterint(exprasmlist);
  1253. if not(cs_check_overflow in aktlocalswitches) or
  1254. (cmpop) or
  1255. (nodetype in [orn,andn,xorn]) then
  1256. begin
  1257. case nodetype of
  1258. addn, muln, xorn, orn, andn:
  1259. begin
  1260. case nodetype of
  1261. addn:
  1262. cgop := OP_ADD;
  1263. muln:
  1264. if unsigned then
  1265. cgop := OP_MUL
  1266. else
  1267. cgop := OP_IMUL;
  1268. xorn:
  1269. cgop := OP_XOR;
  1270. orn:
  1271. cgop := OP_OR;
  1272. andn:
  1273. cgop := OP_AND;
  1274. end;
  1275. if (left.location.loc = LOC_CONSTANT) then
  1276. swapleftright;
  1277. if (right.location.loc <> LOC_CONSTANT) then
  1278. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  1279. left.location.register,right.location.register,
  1280. location.register)
  1281. else
  1282. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  1283. aword(right.location.value),left.location.register,
  1284. location.register);
  1285. end;
  1286. subn:
  1287. begin
  1288. if (nf_swaped in flags) then
  1289. swapleftright;
  1290. if left.location.loc <> LOC_CONSTANT then
  1291. if right.location.loc <> LOC_CONSTANT then
  1292. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1293. right.location.register,left.location.register,
  1294. location.register)
  1295. else
  1296. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1297. aword(right.location.value),left.location.register,
  1298. location.register)
  1299. else
  1300. if (longint(left.location.value) >= low(smallint)) and
  1301. (longint(left.location.value) <= high(smallint)) then
  1302. begin
  1303. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  1304. location.register,right.location.register,
  1305. longint(left.location.value)));
  1306. end
  1307. else
  1308. begin
  1309. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  1310. cg.a_load_const_reg(exprasmlist,OS_INT,
  1311. aword(left.location.value),tmpreg);
  1312. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1313. right.location.register,tmpreg,location.register);
  1314. cg.free_scratch_reg(exprasmlist,tmpreg);
  1315. end;
  1316. end;
  1317. ltn,lten,gtn,gten,equaln,unequaln :
  1318. begin
  1319. emit_compare(unsigned);
  1320. end;
  1321. end;
  1322. end
  1323. else
  1324. // overflow checking is on and we have an addn, subn or muln
  1325. begin
  1326. case nodetype of
  1327. addn:
  1328. op := A_ADDO_;
  1329. subn:
  1330. op := A_SUBO_;
  1331. muln:
  1332. op := A_MULLWO_;
  1333. else
  1334. internalerror(2002072601);
  1335. end;
  1336. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1337. left.location.register,right.location.register));
  1338. cg.g_overflowcheck(exprasmlist,self);
  1339. end;
  1340. clear_left_right(cmpop);
  1341. end;
  1342. begin
  1343. caddnode:=tppcaddnode;
  1344. end.
  1345. {
  1346. $Log$
  1347. Revision 1.21 2003-01-08 18:43:58 daniel
  1348. * Tregister changed into a record
  1349. Revision 1.20 2002/11/25 17:43:27 peter
  1350. * splitted defbase in defutil,symutil,defcmp
  1351. * merged isconvertable and is_equal into compare_defs(_ext)
  1352. * made operator search faster by walking the list only once
  1353. Revision 1.19 2002/10/21 18:08:05 jonas
  1354. * some range errors fixed
  1355. Revision 1.18 2002/09/08 14:14:49 jonas
  1356. * more optimizations for 64bit compares
  1357. Revision 1.17 2002/09/07 22:15:48 jonas
  1358. * fixed optimized 64 compares
  1359. Revision 1.16 2002/09/04 19:42:45 jonas
  1360. * fixed bugs in 64bit operations (registers weren't always allocated for
  1361. the result)
  1362. * optimized 'const64 - reg64/mem64'
  1363. * optimized equaln/unequaln with 64bit values (change them to
  1364. '(left.hi xor right.hi) or (left.lo xor right.lo)' so there are less
  1365. branches and the result can be returned in the flags this way. Could
  1366. be done for the i386 too probably.
  1367. Revision 1.15 2002/08/31 21:30:46 florian
  1368. * fixed several problems caused by Jonas' commit :)
  1369. Revision 1.14 2002/08/31 19:26:20 jonas
  1370. * fixed 64bit comparisons
  1371. Revision 1.13 2002/08/17 22:09:47 florian
  1372. * result type handling in tcgcal.pass_2 overhauled
  1373. * better tnode.dowrite
  1374. * some ppc stuff fixed
  1375. Revision 1.12 2002/08/14 18:41:48 jonas
  1376. - remove valuelow/valuehigh fields from tlocation, because they depend
  1377. on the endianess of the host operating system -> difficult to get
  1378. right. Use lo/hi(location.valueqword) instead (remember to use
  1379. valueqword and not value!!)
  1380. Revision 1.11 2002/08/11 14:32:32 peter
  1381. * renamed current_library to objectlibrary
  1382. Revision 1.10 2002/08/11 13:24:18 peter
  1383. * saving of asmsymbols in ppu supported
  1384. * asmsymbollist global is removed and moved into a new class
  1385. tasmlibrarydata that will hold the info of a .a file which
  1386. corresponds with a single module. Added librarydata to tmodule
  1387. to keep the library info stored for the module. In the future the
  1388. objectfiles will also be stored to the tasmlibrarydata class
  1389. * all getlabel/newasmsymbol and friends are moved to the new class
  1390. Revision 1.9 2002/08/11 11:40:16 jonas
  1391. * some overflow checking fixes
  1392. Revision 1.8 2002/08/11 06:14:40 florian
  1393. * fixed powerpc compilation problems
  1394. Revision 1.7 2002/08/10 17:15:31 jonas
  1395. * various fixes and optimizations
  1396. Revision 1.6 2002/08/06 20:55:24 florian
  1397. * first part of ppc calling conventions fix
  1398. Revision 1.5 2002/08/05 08:58:54 jonas
  1399. * fixed compilation problems
  1400. Revision 1.4 2002/08/04 12:57:56 jonas
  1401. * more misc. fixes, mostly constant-related
  1402. Revision 1.3 2002/07/28 16:02:49 jonas
  1403. + 64 bit operations (badly tested), everything is implemented now!
  1404. * some small fixes
  1405. Revision 1.2 2002/07/27 20:00:59 jonas
  1406. + second_addboolean(), second_addfloat() and second_addsmallset()
  1407. (64bit stuff is all that's left to do)
  1408. Revision 1.1 2002/07/26 12:31:57 jonas
  1409. + intial implementation of add nodes, only integer/enumeration/pointer/...
  1410. handling is finished
  1411. }