nppcadd.pas 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  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,cgcpu,
  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. if is_signed(resulttype.def) then
  934. begin
  935. case nodetype of
  936. addn:
  937. begin
  938. op1 := A_ADDC;
  939. op2 := A_ADDEO;
  940. end;
  941. subn:
  942. begin
  943. op1 := A_SUBC;
  944. op2 := A_SUBFEO;
  945. end;
  946. else
  947. internalerror(2002072806);
  948. end
  949. end
  950. else
  951. begin
  952. case nodetype of
  953. addn:
  954. begin
  955. op1 := A_ADDC;
  956. op2 := A_ADDE;
  957. end;
  958. subn:
  959. begin
  960. op1 := A_SUBC;
  961. op2 := A_SUBFE;
  962. end;
  963. end;
  964. end;
  965. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
  966. left.location.registerlow,right.location.registerlow));
  967. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
  968. right.location.registerhigh,left.location.registerhigh));
  969. if not(is_signed(resulttype.def)) then
  970. if nodetype = addn then
  971. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.registerhigh,left.location.registerhigh))
  972. else
  973. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.registerhigh,location.registerhigh));
  974. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  975. end;
  976. { set result location }
  977. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  978. { real location only now) (JM) }
  979. if cmpop and
  980. not(nodetype in [equaln,unequaln]) then
  981. location_reset(location,LOC_JUMP,OS_NO);
  982. release_reg_left_right;
  983. end;
  984. {*****************************************************************************
  985. AddMMX
  986. *****************************************************************************}
  987. {$ifdef SUPPORT_MMX}
  988. procedure ti386addnode.second_addmmx;
  989. var
  990. op : TAsmOp;
  991. cmpop : boolean;
  992. mmxbase : tmmxtype;
  993. hregister : tregister;
  994. begin
  995. pass_left_and_right;
  996. cmpop:=false;
  997. mmxbase:=mmx_type(left.resulttype.def);
  998. case nodetype of
  999. addn :
  1000. begin
  1001. if (cs_mmx_saturation in aktlocalswitches) then
  1002. begin
  1003. case mmxbase of
  1004. mmxs8bit:
  1005. op:=A_PADDSB;
  1006. mmxu8bit:
  1007. op:=A_PADDUSB;
  1008. mmxs16bit,mmxfixed16:
  1009. op:=A_PADDSB;
  1010. mmxu16bit:
  1011. op:=A_PADDUSW;
  1012. end;
  1013. end
  1014. else
  1015. begin
  1016. case mmxbase of
  1017. mmxs8bit,mmxu8bit:
  1018. op:=A_PADDB;
  1019. mmxs16bit,mmxu16bit,mmxfixed16:
  1020. op:=A_PADDW;
  1021. mmxs32bit,mmxu32bit:
  1022. op:=A_PADDD;
  1023. end;
  1024. end;
  1025. end;
  1026. muln :
  1027. begin
  1028. case mmxbase of
  1029. mmxs16bit,mmxu16bit:
  1030. op:=A_PMULLW;
  1031. mmxfixed16:
  1032. op:=A_PMULHW;
  1033. end;
  1034. end;
  1035. subn :
  1036. begin
  1037. if (cs_mmx_saturation in aktlocalswitches) then
  1038. begin
  1039. case mmxbase of
  1040. mmxs8bit:
  1041. op:=A_PSUBSB;
  1042. mmxu8bit:
  1043. op:=A_PSUBUSB;
  1044. mmxs16bit,mmxfixed16:
  1045. op:=A_PSUBSB;
  1046. mmxu16bit:
  1047. op:=A_PSUBUSW;
  1048. end;
  1049. end
  1050. else
  1051. begin
  1052. case mmxbase of
  1053. mmxs8bit,mmxu8bit:
  1054. op:=A_PSUBB;
  1055. mmxs16bit,mmxu16bit,mmxfixed16:
  1056. op:=A_PSUBW;
  1057. mmxs32bit,mmxu32bit:
  1058. op:=A_PSUBD;
  1059. end;
  1060. end;
  1061. end;
  1062. xorn:
  1063. op:=A_PXOR;
  1064. orn:
  1065. op:=A_POR;
  1066. andn:
  1067. op:=A_PAND;
  1068. else
  1069. CGMessage(type_e_mismatch);
  1070. end;
  1071. { left and right no register? }
  1072. { then one must be demanded }
  1073. if (left.location.loc<>LOC_MMXREGISTER) then
  1074. begin
  1075. if (right.location.loc=LOC_MMXREGISTER) then
  1076. begin
  1077. location_swap(left.location,right.location);
  1078. toggleflag(nf_swaped);
  1079. end
  1080. else
  1081. begin
  1082. { register variable ? }
  1083. if (left.location.loc=LOC_CMMXREGISTER) then
  1084. begin
  1085. hregister:=rg.getregistermm(exprasmlist);
  1086. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1087. end
  1088. else
  1089. begin
  1090. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1091. internalerror(200203245);
  1092. location_release(exprasmlist,left.location);
  1093. hregister:=rg.getregistermm(exprasmlist);
  1094. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1095. end;
  1096. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1097. left.location.register:=hregister;
  1098. end;
  1099. end;
  1100. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1101. if right.location.loc<>LOC_MMXREGISTER then
  1102. begin
  1103. if (nodetype=subn) and (nf_swaped in flags) then
  1104. begin
  1105. if right.location.loc=LOC_CMMXREGISTER then
  1106. begin
  1107. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1108. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1109. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1110. end
  1111. else
  1112. begin
  1113. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1114. internalerror(200203247);
  1115. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  1116. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1117. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1118. location_release(exprasmlist,right.location);
  1119. end;
  1120. end
  1121. else
  1122. begin
  1123. if (right.location.loc=LOC_CMMXREGISTER) then
  1124. begin
  1125. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1126. end
  1127. else
  1128. begin
  1129. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1130. internalerror(200203246);
  1131. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1132. location_release(exprasmlist,right.location);
  1133. end;
  1134. end;
  1135. end
  1136. else
  1137. begin
  1138. { right.location=LOC_MMXREGISTER }
  1139. if (nodetype=subn) and (nf_swaped in flags) then
  1140. begin
  1141. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1142. location_swap(left.location,right.location);
  1143. toggleflag(nf_swaped);
  1144. end
  1145. else
  1146. begin
  1147. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1148. end;
  1149. end;
  1150. location_freetemp(exprasmlist,right.location);
  1151. location_release(exprasmlist,right.location);
  1152. if cmpop then
  1153. begin
  1154. location_freetemp(exprasmlist,left.location);
  1155. location_release(exprasmlist,left.location);
  1156. end;
  1157. set_result_location(cmpop,true);
  1158. end;
  1159. {$endif SUPPORT_MMX}
  1160. {*****************************************************************************
  1161. pass_2
  1162. *****************************************************************************}
  1163. procedure tppcaddnode.pass_2;
  1164. { is also being used for xor, and "mul", "sub, or and comparative }
  1165. { operators }
  1166. var
  1167. cgop : topcg;
  1168. op : tasmop;
  1169. tmpreg : tregister;
  1170. hl : tasmlabel;
  1171. cmpop : boolean;
  1172. { true, if unsigned types are compared }
  1173. unsigned : boolean;
  1174. begin
  1175. { to make it more readable, string and set (not smallset!) have their
  1176. own procedures }
  1177. case left.resulttype.def.deftype of
  1178. orddef :
  1179. begin
  1180. { handling boolean expressions }
  1181. if is_boolean(left.resulttype.def) and
  1182. is_boolean(right.resulttype.def) then
  1183. begin
  1184. second_addboolean;
  1185. exit;
  1186. end
  1187. { 64bit operations }
  1188. else if is_64bit(left.resulttype.def) then
  1189. begin
  1190. second_add64bit;
  1191. exit;
  1192. end;
  1193. end;
  1194. stringdef :
  1195. begin
  1196. internalerror(2002072402);
  1197. exit;
  1198. end;
  1199. setdef :
  1200. begin
  1201. { normalsets are already handled in pass1 }
  1202. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1203. internalerror(200109041);
  1204. second_addsmallset;
  1205. exit;
  1206. end;
  1207. arraydef :
  1208. begin
  1209. {$ifdef SUPPORT_MMX}
  1210. if is_mmx_able_array(left.resulttype.def) then
  1211. begin
  1212. second_addmmx;
  1213. exit;
  1214. end;
  1215. {$endif SUPPORT_MMX}
  1216. end;
  1217. floatdef :
  1218. begin
  1219. second_addfloat;
  1220. exit;
  1221. end;
  1222. end;
  1223. { defaults }
  1224. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1225. unsigned:=not(is_signed(left.resulttype.def)) or
  1226. not(is_signed(right.resulttype.def));
  1227. pass_left_and_right;
  1228. { Convert flags to register first }
  1229. { can any of these things be in the flags actually?? (JM) }
  1230. if (left.location.loc = LOC_FLAGS) or
  1231. (right.location.loc = LOC_FLAGS) then
  1232. internalerror(2002072602);
  1233. { set result location }
  1234. if not cmpop then
  1235. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1236. else
  1237. location_reset(location,LOC_FLAGS,OS_NO);
  1238. load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
  1239. (nodetype in [addn,subn,muln]));
  1240. if (location.register = NR_NO) and
  1241. not(cmpop) then
  1242. location.register := cg.getintregister(exprasmlist,OS_INT);
  1243. if not(cs_check_overflow in aktlocalswitches) or
  1244. (cmpop) or
  1245. (nodetype in [orn,andn,xorn]) then
  1246. begin
  1247. case nodetype of
  1248. addn, muln, xorn, orn, andn:
  1249. begin
  1250. case nodetype of
  1251. addn:
  1252. cgop := OP_ADD;
  1253. muln:
  1254. if unsigned then
  1255. cgop := OP_MUL
  1256. else
  1257. cgop := OP_IMUL;
  1258. xorn:
  1259. cgop := OP_XOR;
  1260. orn:
  1261. cgop := OP_OR;
  1262. andn:
  1263. cgop := OP_AND;
  1264. end;
  1265. if (left.location.loc = LOC_CONSTANT) then
  1266. swapleftright;
  1267. if (right.location.loc <> LOC_CONSTANT) then
  1268. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  1269. left.location.register,right.location.register,
  1270. location.register)
  1271. else
  1272. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  1273. aword(right.location.value),left.location.register,
  1274. location.register);
  1275. end;
  1276. subn:
  1277. begin
  1278. if (nf_swaped in flags) then
  1279. swapleftright;
  1280. if left.location.loc <> LOC_CONSTANT then
  1281. if right.location.loc <> LOC_CONSTANT then
  1282. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1283. right.location.register,left.location.register,
  1284. location.register)
  1285. else
  1286. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1287. aword(right.location.value),left.location.register,
  1288. location.register)
  1289. else
  1290. if (longint(left.location.value) >= low(smallint)) and
  1291. (longint(left.location.value) <= high(smallint)) then
  1292. begin
  1293. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  1294. location.register,right.location.register,
  1295. longint(left.location.value)));
  1296. end
  1297. else
  1298. begin
  1299. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  1300. cg.a_load_const_reg(exprasmlist,OS_INT,
  1301. aword(left.location.value),tmpreg);
  1302. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1303. right.location.register,tmpreg,location.register);
  1304. cg.ungetregister(exprasmlist,tmpreg);
  1305. end;
  1306. end;
  1307. ltn,lten,gtn,gten,equaln,unequaln :
  1308. begin
  1309. emit_compare(unsigned);
  1310. end;
  1311. end;
  1312. end
  1313. else
  1314. // overflow checking is on and we have an addn, subn or muln
  1315. begin
  1316. if is_signed(resulttype.def) then
  1317. begin
  1318. case nodetype of
  1319. addn:
  1320. op := A_ADDO;
  1321. subn:
  1322. op := A_SUBO;
  1323. muln:
  1324. op := A_MULLWO;
  1325. else
  1326. internalerror(2002072601);
  1327. end;
  1328. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1329. left.location.register,right.location.register));
  1330. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1331. end
  1332. else
  1333. begin
  1334. case nodetype of
  1335. addn:
  1336. begin
  1337. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
  1338. left.location.register,right.location.register));
  1339. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
  1340. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1341. end;
  1342. subn:
  1343. begin
  1344. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
  1345. left.location.register,right.location.register));
  1346. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
  1347. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1348. end;
  1349. muln:
  1350. begin
  1351. { calculate the upper 32 bits of the product, = 0 if no overflow }
  1352. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,location.register,
  1353. left.location.register,right.location.register));
  1354. { calculate the real result }
  1355. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
  1356. left.location.register,right.location.register));
  1357. { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
  1358. objectlibrary.getlabel(hl);
  1359. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
  1360. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  1361. cg.a_label(exprasmlist,hl);
  1362. end;
  1363. end;
  1364. end;
  1365. end;
  1366. release_reg_left_right;
  1367. end;
  1368. begin
  1369. caddnode:=tppcaddnode;
  1370. end.
  1371. {
  1372. $Log$
  1373. Revision 1.40 2003-12-09 20:39:43 jonas
  1374. * forgot call to cg.g_overflowcheck() in nppcadd
  1375. * fixed overflow flag definition
  1376. * fixed cg.g_overflowcheck() for signed numbers (jump over call to
  1377. FPC_OVERFLOW if *no* overflow instead of if overflow :)
  1378. Revision 1.39 2003/12/08 21:18:44 jonas
  1379. * fixed usigned overflow checking
  1380. Revision 1.38 2003/10/17 14:52:07 peter
  1381. * fixed ppc build
  1382. Revision 1.37 2003/10/17 01:22:08 florian
  1383. * compilation of the powerpc compiler fixed
  1384. Revision 1.36 2003/10/01 20:34:49 peter
  1385. * procinfo unit contains tprocinfo
  1386. * cginfo renamed to cgbase
  1387. * moved cgmessage to verbose
  1388. * fixed ppc and sparc compiles
  1389. Revision 1.35 2003/09/03 19:39:16 peter
  1390. * removed empty cga unit
  1391. Revision 1.34 2003/09/03 19:35:24 peter
  1392. * powerpc compiles again
  1393. Revision 1.33 2003/06/14 22:32:43 jonas
  1394. * ppc compiles with -dnewra, haven't tried to compile anything with it
  1395. yet though
  1396. Revision 1.32 2003/06/04 11:58:58 jonas
  1397. * calculate localsize also in g_return_from_proc since it's now called
  1398. before g_stackframe_entry (still have to fix macos)
  1399. * compilation fixes (cycle doesn't work yet though)
  1400. Revision 1.31 2003/06/01 21:38:06 peter
  1401. * getregisterfpu size parameter added
  1402. * op_const_reg size parameter added
  1403. * sparc updates
  1404. Revision 1.30 2003/05/30 18:49:14 jonas
  1405. * fixed problem where sometimes no register was allocated for the result
  1406. of an addnode when using regvars
  1407. Revision 1.29 2003/04/27 11:55:34 jonas
  1408. * fixed overflow checking form of 64bit add instruction
  1409. Revision 1.28 2003/04/27 11:06:06 jonas
  1410. * fixed 64bit "const - reg/ref" bugs
  1411. Revision 1.27 2003/04/24 22:29:58 florian
  1412. * fixed a lot of PowerPC related stuff
  1413. Revision 1.26 2003/04/23 22:18:01 peter
  1414. * fixes to get rtl compiled
  1415. Revision 1.25 2003/04/23 12:35:35 florian
  1416. * fixed several issues with powerpc
  1417. + applied a patch from Jonas for nested function calls (PowerPC only)
  1418. * ...
  1419. Revision 1.24 2003/03/11 21:46:24 jonas
  1420. * lots of new regallocator fixes, both in generic and ppc-specific code
  1421. (ppc compiler still can't compile the linux system unit though)
  1422. Revision 1.23 2003/03/10 18:11:41 olle
  1423. * changed ungetregister to ungetregisterint in tppcaddnode.clear_left_right
  1424. Revision 1.22 2003/02/19 22:00:16 daniel
  1425. * Code generator converted to new register notation
  1426. - Horribily outdated todo.txt removed
  1427. Revision 1.21 2003/01/08 18:43:58 daniel
  1428. * Tregister changed into a record
  1429. Revision 1.20 2002/11/25 17:43:27 peter
  1430. * splitted defbase in defutil,symutil,defcmp
  1431. * merged isconvertable and is_equal into compare_defs(_ext)
  1432. * made operator search faster by walking the list only once
  1433. Revision 1.19 2002/10/21 18:08:05 jonas
  1434. * some range errors fixed
  1435. Revision 1.18 2002/09/08 14:14:49 jonas
  1436. * more optimizations for 64bit compares
  1437. Revision 1.17 2002/09/07 22:15:48 jonas
  1438. * fixed optimized 64 compares
  1439. Revision 1.16 2002/09/04 19:42:45 jonas
  1440. * fixed bugs in 64bit operations (registers weren't always allocated for
  1441. the result)
  1442. * optimized 'const64 - reg64/mem64'
  1443. * optimized equaln/unequaln with 64bit values (change them to
  1444. '(left.hi xor right.hi) or (left.lo xor right.lo)' so there are less
  1445. branches and the result can be returned in the flags this way. Could
  1446. be done for the i386 too probably.
  1447. Revision 1.15 2002/08/31 21:30:46 florian
  1448. * fixed several problems caused by Jonas' commit :)
  1449. Revision 1.14 2002/08/31 19:26:20 jonas
  1450. * fixed 64bit comparisons
  1451. Revision 1.13 2002/08/17 22:09:47 florian
  1452. * result type handling in tcgcal.pass_2 overhauled
  1453. * better tnode.dowrite
  1454. * some ppc stuff fixed
  1455. Revision 1.12 2002/08/14 18:41:48 jonas
  1456. - remove valuelow/valuehigh fields from tlocation, because they depend
  1457. on the endianess of the host operating system -> difficult to get
  1458. right. Use lo/hi(location.valueqword) instead (remember to use
  1459. valueqword and not value!!)
  1460. Revision 1.11 2002/08/11 14:32:32 peter
  1461. * renamed current_library to objectlibrary
  1462. Revision 1.10 2002/08/11 13:24:18 peter
  1463. * saving of asmsymbols in ppu supported
  1464. * asmsymbollist global is removed and moved into a new class
  1465. tasmlibrarydata that will hold the info of a .a file which
  1466. corresponds with a single module. Added librarydata to tmodule
  1467. to keep the library info stored for the module. In the future the
  1468. objectfiles will also be stored to the tasmlibrarydata class
  1469. * all getlabel/newasmsymbol and friends are moved to the new class
  1470. Revision 1.9 2002/08/11 11:40:16 jonas
  1471. * some overflow checking fixes
  1472. Revision 1.8 2002/08/11 06:14:40 florian
  1473. * fixed powerpc compilation problems
  1474. Revision 1.7 2002/08/10 17:15:31 jonas
  1475. * various fixes and optimizations
  1476. Revision 1.6 2002/08/06 20:55:24 florian
  1477. * first part of ppc calling conventions fix
  1478. Revision 1.5 2002/08/05 08:58:54 jonas
  1479. * fixed compilation problems
  1480. Revision 1.4 2002/08/04 12:57:56 jonas
  1481. * more misc. fixes, mostly constant-related
  1482. Revision 1.3 2002/07/28 16:02:49 jonas
  1483. + 64 bit operations (badly tested), everything is implemented now!
  1484. * some small fixes
  1485. Revision 1.2 2002/07/27 20:00:59 jonas
  1486. + second_addboolean(), second_addfloat() and second_addsmallset()
  1487. (64bit stuff is all that's left to do)
  1488. Revision 1.1 2002/07/26 12:31:57 jonas
  1489. + intial implementation of add nodes, only integer/enumeration/pointer/...
  1490. handling is finished
  1491. }