nppcadd.pas 58 KB

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