nppcadd.pas 60 KB

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