nppcadd.pas 54 KB

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