2
0

nppcadd.pas 57 KB

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