nppcadd.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  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. procedure pass_2;override;
  26. private
  27. procedure pass_left_and_right;
  28. procedure load_left_right(cmpop, load_constants: boolean);
  29. procedure clear_left_right(cmpop: boolean);
  30. function getresflags : tresflags;
  31. procedure emit_compare(unsigned : boolean);
  32. procedure second_addboolean;
  33. procedure second_addfloat;
  34. procedure second_addsmallset;
  35. {$ifdef SUPPORT_MMX}
  36. procedure second_addmmx;
  37. {$endif SUPPORT_MMX}
  38. procedure second_add64bit;
  39. end;
  40. implementation
  41. uses
  42. globtype,systems,
  43. cutils,verbose,globals,
  44. symconst,symdef,paramgr,
  45. aasmbase,aasmtai,aasmcpu,defbase,htypechk,
  46. cgbase,cpuinfo,pass_2,regvars,
  47. cpupara,
  48. ncon,nset,
  49. cga,ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
  50. {*****************************************************************************
  51. Helpers
  52. *****************************************************************************}
  53. procedure tppcaddnode.pass_left_and_right;
  54. var
  55. pushedregs : tmaybesave;
  56. tmpreg : tregister;
  57. pushedfpu : boolean;
  58. begin
  59. { calculate the operator which is more difficult }
  60. firstcomplex(self);
  61. { in case of constant put it to the left }
  62. if (left.nodetype=ordconstn) then
  63. swapleftright;
  64. secondpass(left);
  65. { are too few registers free? }
  66. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  67. if location.loc=LOC_FPUREGISTER then
  68. pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
  69. else
  70. pushedfpu:=false;
  71. secondpass(right);
  72. maybe_restore(exprasmlist,left.location,pushedregs);
  73. if pushedfpu then
  74. begin
  75. tmpreg := rg.getregisterfpu(exprasmlist);
  76. cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
  77. location_reset(left.location,LOC_FPUREGISTER,left.location.size);
  78. left.location.register := tmpreg;
  79. end;
  80. end;
  81. procedure tppcaddnode.load_left_right(cmpop, load_constants: boolean);
  82. procedure load_node(var n: tnode);
  83. begin
  84. case n.location.loc of
  85. LOC_REGISTER:
  86. if not cmpop then
  87. begin
  88. location.register := n.location.register;
  89. if is_64bitint(n.resulttype.def) then
  90. location.registerhigh := n.location.registerhigh;
  91. end;
  92. LOC_REFERENCE,LOC_CREFERENCE:
  93. begin
  94. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  95. if not cmpop then
  96. location.register := n.location.register;
  97. if is_64bitint(n.resulttype.def) then
  98. location.registerhigh := n.location.registerhigh;
  99. end;
  100. LOC_CONSTANT:
  101. begin
  102. if load_constants then
  103. begin
  104. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  105. if not cmpop then
  106. location.register := n.location.register;
  107. if is_64bitint(n.resulttype.def) then
  108. location.registerhigh := n.location.registerhigh;
  109. end;
  110. end;
  111. end;
  112. end;
  113. begin
  114. load_node(left);
  115. load_node(right);
  116. end;
  117. procedure tppcaddnode.clear_left_right(cmpop: boolean);
  118. begin
  119. if (right.location.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  120. (cmpop or
  121. (location.register <> right.location.register)) then
  122. begin
  123. rg.ungetregister(exprasmlist,right.location.register);
  124. if is_64bitint(right.resulttype.def) then
  125. rg.ungetregister(exprasmlist,right.location.registerhigh);
  126. end;
  127. if (left.location.loc in [LOC_REGISTER,LOC_FPUREGISTER]) and
  128. (cmpop or
  129. (location.register <> left.location.register)) then
  130. begin
  131. rg.ungetregister(exprasmlist,left.location.register);
  132. if is_64bitint(left.resulttype.def) then
  133. rg.ungetregister(exprasmlist,left.location.registerhigh);
  134. end;
  135. end;
  136. function tppcaddnode.getresflags : tresflags;
  137. begin
  138. if (left.resulttype.def.deftype <> floatdef) then
  139. result.cr := R_CR0
  140. else
  141. result.cr := R_CR1;
  142. case nodetype of
  143. equaln : result.flag:=F_EQ;
  144. unequaln : result.flag:=F_NE;
  145. else
  146. if nf_swaped in flags then
  147. case nodetype of
  148. ltn : result.flag:=F_GT;
  149. lten : result.flag:=F_GE;
  150. gtn : result.flag:=F_LT;
  151. gten : result.flag:=F_LE;
  152. end
  153. else
  154. case nodetype of
  155. ltn : result.flag:=F_LT;
  156. lten : result.flag:=F_LE;
  157. gtn : result.flag:=F_GT;
  158. gten : result.flag:=F_GE;
  159. end;
  160. end
  161. end;
  162. procedure tppcaddnode.emit_compare(unsigned: boolean);
  163. var
  164. op : tasmop;
  165. tmpreg : tregister;
  166. useconst : boolean;
  167. begin
  168. // get the constant on the right if there is one
  169. if (left.location.loc = LOC_CONSTANT) then
  170. swapleftright;
  171. // can we use an immediate, or do we have to load the
  172. // constant in a register first?
  173. if (right.location.loc = LOC_CONSTANT) then
  174. begin
  175. {$ifdef extdebug}
  176. if (qword(right.location.value) > high(cardinal)) then
  177. internalerror(2002080301);
  178. {$endif extdebug}
  179. if (nodetype in [equaln,unequaln]) then
  180. if (unsigned and
  181. (right.location.value > high(word))) or
  182. (not unsigned and
  183. (right.location.value < low(smallint)) or
  184. (right.location.value > high(smallint))) then
  185. // we can then maybe use a constant in the 'othersigned' case
  186. // (the sign doesn't matter for // equal/unequal)
  187. unsigned := not unsigned;
  188. if (unsigned and
  189. (qword(right.location.value) <= high(word))) or
  190. (not(unsigned) and
  191. (right.location.value >= low(smallint)) and
  192. (right.location.value <= high(smallint))) then
  193. useconst := true
  194. else
  195. begin
  196. useconst := false;
  197. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  198. cg.a_load_const_reg(exprasmlist,OS_INT,
  199. aword(right.location.value),tmpreg);
  200. end
  201. end
  202. else
  203. useconst := false;
  204. location.loc := LOC_FLAGS;
  205. location.resflags := getresflags;
  206. if not unsigned then
  207. if useconst then
  208. op := A_CMPWI
  209. else
  210. op := A_CMPW
  211. else
  212. if useconst then
  213. op := A_CMPLWI
  214. else
  215. op := A_CMPLW;
  216. if (right.location.loc = LOC_CONSTANT) then
  217. if useconst then
  218. exprasmlist.concat(taicpu.op_reg_const(op,
  219. left.location.register,right.location.value))
  220. else
  221. begin
  222. exprasmlist.concat(taicpu.op_reg_reg(op,
  223. left.location.register,tmpreg));
  224. cg.free_scratch_reg(exprasmlist,tmpreg);
  225. end
  226. else
  227. exprasmlist.concat(taicpu.op_reg_reg(op,
  228. left.location.register,right.location.register));
  229. end;
  230. {*****************************************************************************
  231. AddBoolean
  232. *****************************************************************************}
  233. procedure tppcaddnode.second_addboolean;
  234. var
  235. cgop : TOpCg;
  236. cgsize : TCgSize;
  237. cmpop,
  238. isjump : boolean;
  239. otl,ofl : tasmlabel;
  240. pushedregs : tmaybesave;
  241. begin
  242. { calculate the operator which is more difficult }
  243. firstcomplex(self);
  244. cmpop:=false;
  245. if (torddef(left.resulttype.def).typ=bool8bit) or
  246. (torddef(right.resulttype.def).typ=bool8bit) then
  247. cgsize:=OS_8
  248. else
  249. if (torddef(left.resulttype.def).typ=bool16bit) or
  250. (torddef(right.resulttype.def).typ=bool16bit) then
  251. cgsize:=OS_16
  252. else
  253. cgsize:=OS_32;
  254. if (cs_full_boolean_eval in aktlocalswitches) or
  255. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn]) then
  256. begin
  257. if left.nodetype in [ordconstn,realconstn] then
  258. swapleftright;
  259. isjump:=(left.location.loc=LOC_JUMP);
  260. if isjump then
  261. begin
  262. otl:=truelabel;
  263. getlabel(truelabel);
  264. ofl:=falselabel;
  265. getlabel(falselabel);
  266. end;
  267. secondpass(left);
  268. if left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  269. location_force_reg(exprasmlist,left.location,cgsize,false);
  270. if isjump then
  271. begin
  272. truelabel:=otl;
  273. falselabel:=ofl;
  274. end;
  275. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  276. isjump:=(right.location.loc=LOC_JUMP);
  277. if isjump then
  278. begin
  279. otl:=truelabel;
  280. getlabel(truelabel);
  281. ofl:=falselabel;
  282. getlabel(falselabel);
  283. end;
  284. secondpass(right);
  285. maybe_restore(exprasmlist,left.location,pushedregs);
  286. if right.location.loc in [LOC_FLAGS,LOC_JUMP] then
  287. location_force_reg(exprasmlist,right.location,cgsize,false);
  288. if isjump then
  289. begin
  290. truelabel:=otl;
  291. falselabel:=ofl;
  292. end;
  293. cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  294. { set result location }
  295. if not cmpop then
  296. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  297. else
  298. location_reset(location,LOC_FLAGS,OS_NO);
  299. load_left_right(cmpop,false);
  300. if (left.location.loc = LOC_CONSTANT) then
  301. swapleftright;
  302. { compare the }
  303. case nodetype of
  304. ltn,lten,gtn,gten,
  305. equaln,unequaln :
  306. begin
  307. if (right.location.loc <> LOC_CONSTANT) then
  308. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,
  309. left.location.register,right.location.register))
  310. else
  311. exprasmlist.concat(taicpu.op_reg_const(A_CMPLWI,
  312. left.location.register,right.location.value));
  313. location.resflags := getresflags;
  314. end;
  315. else
  316. begin
  317. case nodetype of
  318. xorn :
  319. cgop:=OP_XOR;
  320. orn :
  321. cgop:=OP_OR;
  322. andn :
  323. cgop:=OP_AND;
  324. else
  325. internalerror(200203247);
  326. end;
  327. if right.location.loc <> LOC_CONSTANT then
  328. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  329. left.location.register,right.location.register,
  330. location.register)
  331. else
  332. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  333. aword(right.location.value),left.location.register,
  334. location.register);
  335. end;
  336. end;
  337. end
  338. else
  339. begin
  340. // just to make sure we free the right registers
  341. cmpop := true;
  342. case nodetype of
  343. andn,
  344. orn :
  345. begin
  346. location_reset(location,LOC_JUMP,OS_NO);
  347. case nodetype of
  348. andn :
  349. begin
  350. otl:=truelabel;
  351. getlabel(truelabel);
  352. secondpass(left);
  353. maketojumpbool(exprasmlist,left,lr_load_regvars);
  354. cg.a_label(exprasmlist,truelabel);
  355. truelabel:=otl;
  356. end;
  357. orn :
  358. begin
  359. ofl:=falselabel;
  360. getlabel(falselabel);
  361. secondpass(left);
  362. maketojumpbool(exprasmlist,left,lr_load_regvars);
  363. cg.a_label(exprasmlist,falselabel);
  364. falselabel:=ofl;
  365. end;
  366. else
  367. CGMessage(type_e_mismatch);
  368. end;
  369. secondpass(right);
  370. maketojumpbool(exprasmlist,right,lr_load_regvars);
  371. end;
  372. end;
  373. end;
  374. clear_left_right(cmpop);
  375. end;
  376. {*****************************************************************************
  377. AddFloat
  378. *****************************************************************************}
  379. procedure tppcaddnode.second_addfloat;
  380. var
  381. reg : tregister;
  382. op : TAsmOp;
  383. cmpop : boolean;
  384. procedure location_force_fpureg(var l: tlocation);
  385. begin
  386. if not(l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
  387. begin
  388. reg := rg.getregisterfpu(exprasmlist);
  389. cg.a_loadfpu_loc_reg(exprasmlist,l,reg);
  390. location_freetemp(exprasmlist,l);
  391. location_release(exprasmlist,l);
  392. location_reset(l,LOC_FPUREGISTER,l.size);
  393. l.register := reg;
  394. end;
  395. end;
  396. begin
  397. pass_left_and_right;
  398. cmpop:=false;
  399. case nodetype of
  400. addn :
  401. op:=A_FADD;
  402. muln :
  403. op:=A_FMUL;
  404. subn :
  405. op:=A_FSUB;
  406. slashn :
  407. op:=A_FDIV;
  408. ltn,lten,gtn,gten,
  409. equaln,unequaln :
  410. begin
  411. op:=A_FCMPO;
  412. cmpop:=true;
  413. end;
  414. else
  415. CGMessage(type_e_mismatch);
  416. end;
  417. // get the operands in the correct order, there are no special cases
  418. // here, everything is register-based
  419. if nf_swaped in flags then
  420. swapleftright;
  421. // put both operands in a register
  422. location_force_fpureg(right.location);
  423. location_force_fpureg(left.location);
  424. // initialize de result
  425. if not cmpop then
  426. begin
  427. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  428. if left.location.loc = LOC_FPUREGISTER then
  429. location.register := left.location.register
  430. else if right.location.loc = LOC_FPUREGISTER then
  431. location.register := right.location.register
  432. else
  433. location.register := rg.getregisterfpu(exprasmlist);
  434. end
  435. else
  436. begin
  437. location_reset(location,LOC_FLAGS,OS_NO);
  438. location.resflags := getresflags;
  439. end;
  440. // emit the actual operation
  441. if not cmpop then
  442. begin
  443. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  444. location.register,left.location.register,
  445. right.location.register))
  446. end
  447. else
  448. begin
  449. exprasmlist.concat(taicpu.op_reg_reg(op,
  450. left.location.register,right.location.register))
  451. end;
  452. clear_left_right(cmpop);
  453. end;
  454. {*****************************************************************************
  455. AddSmallSet
  456. *****************************************************************************}
  457. procedure tppcaddnode.second_addsmallset;
  458. var
  459. cgop : TOpCg;
  460. tmpreg : tregister;
  461. opdone,
  462. cmpop : boolean;
  463. begin
  464. pass_left_and_right;
  465. { when a setdef is passed, it has to be a smallset }
  466. if ((left.resulttype.def.deftype=setdef) and
  467. (tsetdef(left.resulttype.def).settype<>smallset)) or
  468. ((right.resulttype.def.deftype=setdef) and
  469. (tsetdef(right.resulttype.def).settype<>smallset)) then
  470. internalerror(200203301);
  471. opdone := false;
  472. cmpop:=nodetype in [equaln,unequaln,lten,gten];
  473. { set result location }
  474. if not cmpop then
  475. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  476. else
  477. location_reset(location,LOC_FLAGS,OS_NO);
  478. load_left_right(cmpop,false);
  479. if not(cmpop) and
  480. (location.register = R_NO) then
  481. location.register := rg.getregisterint(exprasmlist);
  482. case nodetype of
  483. addn :
  484. begin
  485. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  486. swapleftright;
  487. { are we adding set elements ? }
  488. if right.nodetype=setelementn then
  489. begin
  490. { no range support for smallsets! }
  491. if assigned(tsetelementnode(right).right) then
  492. internalerror(43244);
  493. if (right.location.loc = LOC_CONSTANT) then
  494. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  495. aword(1 shl aword(right.location.value)),
  496. left.location.register,location.register)
  497. else
  498. begin
  499. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  500. cg.a_load_const_reg(exprasmlist,OS_INT,1,tmpreg);
  501. cg.a_op_reg_reg(exprasmlist,OP_SHL,OS_INT,
  502. right.location.register,tmpreg);
  503. if left.location.loc <> LOC_CONSTANT then
  504. cg.a_op_reg_reg_reg(exprasmlist,OP_OR,OS_INT,tmpreg,
  505. left.location.register,location.register)
  506. else
  507. cg.a_op_const_reg_reg(exprasmlist,OP_OR,OS_INT,
  508. aword(left.location.value),tmpreg,location.register);
  509. cg.free_scratch_reg(exprasmlist,tmpreg);
  510. end;
  511. opdone := true;
  512. end
  513. else
  514. cgop := OP_OR;
  515. end;
  516. symdifn :
  517. cgop:=OP_XOR;
  518. muln :
  519. cgop:=OP_AND;
  520. subn :
  521. begin
  522. cgop:=OP_AND;
  523. if (not(nf_swaped in flags)) then
  524. if (right.location.loc=LOC_CONSTANT) then
  525. right.location.value := not(right.location.value)
  526. else
  527. opdone := true
  528. else if (left.location.loc=LOC_CONSTANT) then
  529. left.location.value := not(left.location.value)
  530. else
  531. begin
  532. swapleftright;
  533. opdone := true;
  534. end;
  535. if opdone then
  536. begin
  537. if left.location.loc = LOC_CONSTANT then
  538. begin
  539. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  540. cg.a_load_const_reg(exprasmlist,OS_INT,
  541. aword(left.location.value),tmpreg);
  542. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  543. location.register,tmpreg,right.location.register));
  544. cg.free_scratch_reg(exprasmlist,tmpreg);
  545. end
  546. else
  547. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC,
  548. location.register,left.location.register,
  549. right.location.register));
  550. end;
  551. end;
  552. equaln,
  553. unequaln :
  554. begin
  555. emit_compare(true);
  556. opdone := true;
  557. end;
  558. lten,gten:
  559. begin
  560. If (not(nf_swaped in flags) and
  561. (nodetype = lten)) or
  562. ((nf_swaped in flags) and
  563. (nodetype = gten)) then
  564. swapleftright;
  565. // now we have to check whether left >= right
  566. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  567. if left.location.loc = LOC_CONSTANT then
  568. begin
  569. cg.a_op_const_reg_reg(exprasmlist,OP_AND,OS_INT,
  570. not(left.location.value),right.location.register,tmpreg);
  571. exprasmlist.concat(taicpu.op_reg_const(A_CMPWI,tmpreg,0));
  572. // the two instructions above should be folded together by
  573. // the peepholeoptimizer
  574. end
  575. else
  576. begin
  577. if right.location.loc = LOC_CONSTANT then
  578. begin
  579. cg.a_load_const_reg(exprasmlist,OS_INT,
  580. aword(right.location.value),tmpreg);
  581. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  582. tmpreg,left.location.register));
  583. end
  584. else
  585. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ANDC_,tmpreg,
  586. right.location.register,left.location.register));
  587. end;
  588. cg.free_scratch_reg(exprasmlist,tmpreg);
  589. location.resflags.cr := R_CR0;
  590. location.resflags.flag := F_EQ;
  591. opdone := true;
  592. end;
  593. else
  594. internalerror(2002072701);
  595. end;
  596. if not opdone then
  597. begin
  598. // these are all commutative operations
  599. if (left.location.loc = LOC_CONSTANT) then
  600. swapleftright;
  601. if (right.location.loc = LOC_CONSTANT) then
  602. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  603. aword(right.location.value),left.location.register,
  604. location.register)
  605. else
  606. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  607. right.location.register,left.location.register,
  608. location.register);
  609. end;
  610. clear_left_right(cmpop);
  611. end;
  612. {*****************************************************************************
  613. Add64bit
  614. *****************************************************************************}
  615. procedure tppcaddnode.second_add64bit;
  616. var
  617. op : TOpCG;
  618. op1,op2 : TAsmOp;
  619. hl4 : tasmlabel;
  620. cmpop,
  621. unsigned : boolean;
  622. procedure emit_cmp64_hi;
  623. var
  624. oldleft, oldright: tlocation;
  625. begin
  626. // put the high part of the location in the low part
  627. location_copy(oldleft,left.location);
  628. location_copy(oldright,right.location);
  629. if left.location.loc = LOC_CONSTANT then
  630. left.location.value := left.location.value shr 32
  631. else
  632. left.location.registerlow := left.location.registerhigh;
  633. if right.location.loc = LOC_CONSTANT then
  634. right.location.value := right.location.value shr 32
  635. else
  636. right.location.registerlow := right.location.registerhigh;
  637. // and call the normal emit_compare
  638. emit_compare(unsigned);
  639. location_copy(left.location,oldleft);
  640. location_copy(right.location,oldright);
  641. end;
  642. procedure emit_cmp64_lo;
  643. begin
  644. emit_compare(true);
  645. end;
  646. procedure firstjmp64bitcmp;
  647. var
  648. oldnodetype: tnodetype;
  649. begin
  650. load_all_regvars(exprasmlist);
  651. { the jump the sequence is a little bit hairy }
  652. case nodetype of
  653. ltn,gtn:
  654. begin
  655. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  656. { cheat a little bit for the negative test }
  657. toggleflag(nf_swaped);
  658. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  659. toggleflag(nf_swaped);
  660. end;
  661. lten,gten:
  662. begin
  663. oldnodetype:=nodetype;
  664. if nodetype=lten then
  665. nodetype:=ltn
  666. else
  667. nodetype:=gtn;
  668. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  669. { cheat for the negative test }
  670. if nodetype=ltn then
  671. nodetype:=gtn
  672. else
  673. nodetype:=ltn;
  674. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  675. nodetype:=oldnodetype;
  676. end;
  677. equaln:
  678. begin
  679. nodetype := unequaln;
  680. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  681. nodetype := equaln;
  682. end;
  683. unequaln:
  684. begin
  685. nodetype := equaln;
  686. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  687. nodetype := unequaln;
  688. end;
  689. end;
  690. end;
  691. procedure secondjmp64bitcmp;
  692. begin
  693. { the jump the sequence is a little bit hairy }
  694. case nodetype of
  695. ltn,gtn,lten,gten:
  696. begin
  697. { the comparisaion of the low dword have to be }
  698. { always unsigned! }
  699. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  700. cg.a_jmp_always(exprasmlist,falselabel);
  701. end;
  702. equaln:
  703. begin
  704. nodetype := unequaln;
  705. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  706. cg.a_jmp_always(exprasmlist,truelabel);
  707. nodetype := equaln;
  708. end;
  709. unequaln:
  710. begin
  711. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  712. cg.a_jmp_always(exprasmlist,falselabel);
  713. end;
  714. end;
  715. end;
  716. begin
  717. firstcomplex(self);
  718. pass_left_and_right;
  719. cmpop:=false;
  720. unsigned:=((left.resulttype.def.deftype=orddef) and
  721. (torddef(left.resulttype.def).typ=u64bit)) or
  722. ((right.resulttype.def.deftype=orddef) and
  723. (torddef(right.resulttype.def).typ=u64bit));
  724. case nodetype of
  725. addn :
  726. begin
  727. op:=OP_ADD;
  728. end;
  729. subn :
  730. begin
  731. op:=OP_SUB;
  732. end;
  733. ltn,lten,
  734. gtn,gten,
  735. equaln,unequaln:
  736. begin
  737. op:=OP_NONE;
  738. cmpop:=true;
  739. end;
  740. xorn:
  741. op:=OP_XOR;
  742. orn:
  743. op:=OP_OR;
  744. andn:
  745. op:=OP_AND;
  746. muln:
  747. begin
  748. { should be handled in pass_1 (JM) }
  749. internalerror(200109051);
  750. end;
  751. else
  752. internalerror(2002072705);
  753. end;
  754. { set result location }
  755. if not cmpop then
  756. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  757. else
  758. location_reset(location,LOC_JUMP,OS_NO);
  759. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  760. (nodetype in [addn,subn]));
  761. // can't do much with a constant on the left side here
  762. if (nodetype = subn) then
  763. begin
  764. if (nf_swaped in flags) then
  765. swapleftright;
  766. if left.location.loc = LOC_CONSTANT then
  767. if not(cs_check_overflow in aktlocalswitches) and
  768. (left.location.value >= low(smallint)) and
  769. (left.location.value <= high(smallint)) then
  770. begin
  771. // optimize
  772. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  773. location.register,right.location.registerlow,
  774. left.location.value));
  775. exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
  776. location.register,right.location.registerhigh));
  777. clear_left_right(false);
  778. exit;
  779. end
  780. else
  781. begin
  782. // load constant in register
  783. location_force_reg(exprasmlist,left.location,
  784. def_cgsize(left.resulttype.def),false);
  785. location.register64 := left.location.register64;
  786. end;
  787. end;
  788. if not(cs_check_overflow in aktlocalswitches) or
  789. not(nodetype in [addn,subn]) then
  790. begin
  791. case nodetype of
  792. ltn,lten,
  793. gtn,gten,
  794. equaln,unequaln:
  795. begin
  796. emit_cmp64_hi;
  797. firstjmp64bitcmp;
  798. emit_cmp64_lo;
  799. secondjmp64bitcmp;
  800. end;
  801. xorn,orn,andn,addn,subn:
  802. begin
  803. if left.location.loc = LOC_CONSTANT then
  804. swapleftright;
  805. if (right.location.loc = LOC_CONSTANT) then
  806. cg64.a_op64_const_reg_reg(exprasmlist,op,qword(right.location.value),
  807. left.location.register64,location.register64)
  808. else
  809. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  810. left.location.register64,location.register64);
  811. end;
  812. else
  813. internalerror(2002072803);
  814. end;
  815. end
  816. else
  817. begin
  818. case nodetype of
  819. addn:
  820. begin
  821. op1 := A_ADDC;
  822. op2 := A_ADDZEO;
  823. end;
  824. subn:
  825. begin
  826. op1 := A_SUBC;
  827. op2 := A_SUBFEO;
  828. end;
  829. else
  830. internalerror(2002072806);
  831. end;
  832. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
  833. left.location.registerlow,right.location.registerlow));
  834. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
  835. right.location.registerhigh,left.location.registerhigh));
  836. cg.g_overflowcheck(exprasmlist,self);
  837. end;
  838. clear_left_right(cmpop);
  839. end;
  840. {*****************************************************************************
  841. AddMMX
  842. *****************************************************************************}
  843. {$ifdef SUPPORT_MMX}
  844. procedure ti386addnode.second_addmmx;
  845. var
  846. op : TAsmOp;
  847. cmpop : boolean;
  848. mmxbase : tmmxtype;
  849. hregister : tregister;
  850. begin
  851. pass_left_and_right;
  852. cmpop:=false;
  853. mmxbase:=mmx_type(left.resulttype.def);
  854. case nodetype of
  855. addn :
  856. begin
  857. if (cs_mmx_saturation in aktlocalswitches) then
  858. begin
  859. case mmxbase of
  860. mmxs8bit:
  861. op:=A_PADDSB;
  862. mmxu8bit:
  863. op:=A_PADDUSB;
  864. mmxs16bit,mmxfixed16:
  865. op:=A_PADDSB;
  866. mmxu16bit:
  867. op:=A_PADDUSW;
  868. end;
  869. end
  870. else
  871. begin
  872. case mmxbase of
  873. mmxs8bit,mmxu8bit:
  874. op:=A_PADDB;
  875. mmxs16bit,mmxu16bit,mmxfixed16:
  876. op:=A_PADDW;
  877. mmxs32bit,mmxu32bit:
  878. op:=A_PADDD;
  879. end;
  880. end;
  881. end;
  882. muln :
  883. begin
  884. case mmxbase of
  885. mmxs16bit,mmxu16bit:
  886. op:=A_PMULLW;
  887. mmxfixed16:
  888. op:=A_PMULHW;
  889. end;
  890. end;
  891. subn :
  892. begin
  893. if (cs_mmx_saturation in aktlocalswitches) then
  894. begin
  895. case mmxbase of
  896. mmxs8bit:
  897. op:=A_PSUBSB;
  898. mmxu8bit:
  899. op:=A_PSUBUSB;
  900. mmxs16bit,mmxfixed16:
  901. op:=A_PSUBSB;
  902. mmxu16bit:
  903. op:=A_PSUBUSW;
  904. end;
  905. end
  906. else
  907. begin
  908. case mmxbase of
  909. mmxs8bit,mmxu8bit:
  910. op:=A_PSUBB;
  911. mmxs16bit,mmxu16bit,mmxfixed16:
  912. op:=A_PSUBW;
  913. mmxs32bit,mmxu32bit:
  914. op:=A_PSUBD;
  915. end;
  916. end;
  917. end;
  918. xorn:
  919. op:=A_PXOR;
  920. orn:
  921. op:=A_POR;
  922. andn:
  923. op:=A_PAND;
  924. else
  925. CGMessage(type_e_mismatch);
  926. end;
  927. { left and right no register? }
  928. { then one must be demanded }
  929. if (left.location.loc<>LOC_MMXREGISTER) then
  930. begin
  931. if (right.location.loc=LOC_MMXREGISTER) then
  932. begin
  933. location_swap(left.location,right.location);
  934. toggleflag(nf_swaped);
  935. end
  936. else
  937. begin
  938. { register variable ? }
  939. if (left.location.loc=LOC_CMMXREGISTER) then
  940. begin
  941. hregister:=rg.getregistermm(exprasmlist);
  942. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  943. end
  944. else
  945. begin
  946. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  947. internalerror(200203245);
  948. location_release(exprasmlist,left.location);
  949. hregister:=rg.getregistermm(exprasmlist);
  950. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  951. end;
  952. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  953. left.location.register:=hregister;
  954. end;
  955. end;
  956. { at this point, left.location.loc should be LOC_MMXREGISTER }
  957. if right.location.loc<>LOC_MMXREGISTER then
  958. begin
  959. if (nodetype=subn) and (nf_swaped in flags) then
  960. begin
  961. if right.location.loc=LOC_CMMXREGISTER then
  962. begin
  963. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  964. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  965. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  966. end
  967. else
  968. begin
  969. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  970. internalerror(200203247);
  971. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  972. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  973. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  974. location_release(exprasmlist,right.location);
  975. end;
  976. end
  977. else
  978. begin
  979. if (right.location.loc=LOC_CMMXREGISTER) then
  980. begin
  981. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  982. end
  983. else
  984. begin
  985. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  986. internalerror(200203246);
  987. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  988. location_release(exprasmlist,right.location);
  989. end;
  990. end;
  991. end
  992. else
  993. begin
  994. { right.location=LOC_MMXREGISTER }
  995. if (nodetype=subn) and (nf_swaped in flags) then
  996. begin
  997. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  998. location_swap(left.location,right.location);
  999. toggleflag(nf_swaped);
  1000. end
  1001. else
  1002. begin
  1003. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1004. end;
  1005. end;
  1006. location_freetemp(exprasmlist,right.location);
  1007. location_release(exprasmlist,right.location);
  1008. if cmpop then
  1009. begin
  1010. location_freetemp(exprasmlist,left.location);
  1011. location_release(exprasmlist,left.location);
  1012. end;
  1013. set_result_location(cmpop,true);
  1014. end;
  1015. {$endif SUPPORT_MMX}
  1016. {*****************************************************************************
  1017. pass_2
  1018. *****************************************************************************}
  1019. procedure tppcaddnode.pass_2;
  1020. { is also being used for xor, and "mul", "sub, or and comparative }
  1021. { operators }
  1022. var
  1023. cmpop : boolean;
  1024. cgop : topcg;
  1025. op : tasmop;
  1026. tmpreg : tregister;
  1027. { true, if unsigned types are compared }
  1028. unsigned : boolean;
  1029. regstopush: tregisterset;
  1030. begin
  1031. { to make it more readable, string and set (not smallset!) have their
  1032. own procedures }
  1033. case left.resulttype.def.deftype of
  1034. orddef :
  1035. begin
  1036. { handling boolean expressions }
  1037. if is_boolean(left.resulttype.def) and
  1038. is_boolean(right.resulttype.def) then
  1039. begin
  1040. second_addboolean;
  1041. exit;
  1042. end
  1043. { 64bit operations }
  1044. else if is_64bitint(left.resulttype.def) then
  1045. begin
  1046. second_add64bit;
  1047. exit;
  1048. end;
  1049. end;
  1050. stringdef :
  1051. begin
  1052. internalerror(2002072402);
  1053. exit;
  1054. end;
  1055. setdef :
  1056. begin
  1057. { normalsets are already handled in pass1 }
  1058. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1059. internalerror(200109041);
  1060. second_addsmallset;
  1061. exit;
  1062. end;
  1063. arraydef :
  1064. begin
  1065. {$ifdef SUPPORT_MMX}
  1066. if is_mmx_able_array(left.resulttype.def) then
  1067. begin
  1068. second_addmmx;
  1069. exit;
  1070. end;
  1071. {$endif SUPPORT_MMX}
  1072. end;
  1073. floatdef :
  1074. begin
  1075. second_addfloat;
  1076. exit;
  1077. end;
  1078. end;
  1079. { defaults }
  1080. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1081. unsigned:=not(is_signed(left.resulttype.def)) or
  1082. not(is_signed(right.resulttype.def));
  1083. pass_left_and_right;
  1084. { Convert flags to register first }
  1085. { can any of these things be in the flags actually?? (JM) }
  1086. if (left.location.loc = LOC_FLAGS) or
  1087. (right.location.loc = LOC_FLAGS) then
  1088. internalerror(2002072602);
  1089. { set result location }
  1090. if not cmpop then
  1091. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1092. else
  1093. location_reset(location,LOC_FLAGS,OS_NO);
  1094. load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
  1095. (nodetype in [addn,subn,muln]));
  1096. if (location.register = R_NO) and
  1097. not(cmpop) then
  1098. location.register := rg.getregisterint(exprasmlist);
  1099. if not(cs_check_overflow in aktlocalswitches) or
  1100. (cmpop) or
  1101. (nodetype in [orn,andn,xorn]) then
  1102. begin
  1103. case nodetype of
  1104. addn, muln, xorn, orn, andn:
  1105. begin
  1106. case nodetype of
  1107. addn:
  1108. cgop := OP_ADD;
  1109. muln:
  1110. if unsigned then
  1111. cgop := OP_MUL
  1112. else
  1113. cgop := OP_IMUL;
  1114. xorn:
  1115. cgop := OP_XOR;
  1116. orn:
  1117. cgop := OP_OR;
  1118. andn:
  1119. cgop := OP_AND;
  1120. end;
  1121. if (left.location.loc = LOC_CONSTANT) then
  1122. swapleftright;
  1123. if (right.location.loc <> LOC_CONSTANT) then
  1124. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  1125. left.location.register,right.location.register,
  1126. location.register)
  1127. else
  1128. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  1129. aword(right.location.value),left.location.register,
  1130. location.register);
  1131. end;
  1132. subn:
  1133. begin
  1134. if (nf_swaped in flags) then
  1135. swapleftright;
  1136. if left.location.loc <> LOC_CONSTANT then
  1137. if right.location.loc <> LOC_CONSTANT then
  1138. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1139. right.location.register,left.location.register,
  1140. location.register)
  1141. else
  1142. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1143. aword(right.location.value),left.location.register,
  1144. location.register)
  1145. else
  1146. if (longint(left.location.value) >= low(smallint)) and
  1147. (longint(left.location.value) <= high(smallint)) then
  1148. begin
  1149. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  1150. location.register,right.location.register,
  1151. left.location.value));
  1152. end
  1153. else
  1154. begin
  1155. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  1156. cg.a_load_const_reg(exprasmlist,OS_INT,
  1157. aword(left.location.value),tmpreg);
  1158. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1159. right.location.register,tmpreg,location.register);
  1160. cg.free_scratch_reg(exprasmlist,tmpreg);
  1161. end;
  1162. end;
  1163. ltn,lten,gtn,gten,equaln,unequaln :
  1164. begin
  1165. emit_compare(unsigned);
  1166. end;
  1167. end;
  1168. end
  1169. else
  1170. // overflow checking is on and we have an addn, subn or muln
  1171. begin
  1172. case nodetype of
  1173. addn:
  1174. op := A_ADDO;
  1175. subn:
  1176. op := A_SUBO;
  1177. muln:
  1178. op := A_MULLWO;
  1179. else
  1180. internalerror(2002072601);
  1181. end;
  1182. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1183. left.location.register,right.location.register));
  1184. cg.g_overflowcheck(exprasmlist,self);
  1185. end;
  1186. clear_left_right(cmpop);
  1187. end;
  1188. begin
  1189. caddnode:=tppcaddnode;
  1190. end.
  1191. {
  1192. $Log$
  1193. Revision 1.6 2002-08-06 20:55:24 florian
  1194. * first part of ppc calling conventions fix
  1195. Revision 1.5 2002/08/05 08:58:54 jonas
  1196. * fixed compilation problems
  1197. Revision 1.4 2002/08/04 12:57:56 jonas
  1198. * more misc. fixes, mostly constant-related
  1199. Revision 1.3 2002/07/28 16:02:49 jonas
  1200. + 64 bit operations (badly tested), everything is implemented now!
  1201. * some small fixes
  1202. Revision 1.2 2002/07/27 20:00:59 jonas
  1203. + second_addboolean(), second_addfloat() and second_addsmallset()
  1204. (64bit stuff is all that's left to do)
  1205. Revision 1.1 2002/07/26 12:31:57 jonas
  1206. + intial implementation of add nodes, only integer/enumeration/pointer/...
  1207. handling is finished
  1208. }