nppcadd.pas 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  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.valuehigh) <> 0) 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. (longint(right.location.value) < low(smallint)) or
  184. (longint(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. ((right.location.value) <= high(word))) or
  190. (not(unsigned) and
  191. (longint(right.location.value) >= low(smallint)) and
  192. (longint(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,longint(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. objectlibrary.getlabel(truelabel);
  264. ofl:=falselabel;
  265. objectlibrary.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. objectlibrary.getlabel(truelabel);
  281. ofl:=falselabel;
  282. objectlibrary.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,longint(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. objectlibrary.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. objectlibrary.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.valueqword := left.location.valueqword shr 32
  631. else
  632. left.location.registerlow := left.location.registerhigh;
  633. if right.location.loc = LOC_CONSTANT then
  634. right.location.valueqword := right.location.valueqword 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. (longint(left.location.value) >= low(smallint)) and
  769. (longint(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,right.location.valueqword,
  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.11 2002-08-11 14:32:32 peter
  1194. * renamed current_library to objectlibrary
  1195. Revision 1.10 2002/08/11 13:24:18 peter
  1196. * saving of asmsymbols in ppu supported
  1197. * asmsymbollist global is removed and moved into a new class
  1198. tasmlibrarydata that will hold the info of a .a file which
  1199. corresponds with a single module. Added librarydata to tmodule
  1200. to keep the library info stored for the module. In the future the
  1201. objectfiles will also be stored to the tasmlibrarydata class
  1202. * all getlabel/newasmsymbol and friends are moved to the new class
  1203. Revision 1.9 2002/08/11 11:40:16 jonas
  1204. * some overflow checking fixes
  1205. Revision 1.8 2002/08/11 06:14:40 florian
  1206. * fixed powerpc compilation problems
  1207. Revision 1.7 2002/08/10 17:15:31 jonas
  1208. * various fixes and optimizations
  1209. Revision 1.6 2002/08/06 20:55:24 florian
  1210. * first part of ppc calling conventions fix
  1211. Revision 1.5 2002/08/05 08:58:54 jonas
  1212. * fixed compilation problems
  1213. Revision 1.4 2002/08/04 12:57:56 jonas
  1214. * more misc. fixes, mostly constant-related
  1215. Revision 1.3 2002/07/28 16:02:49 jonas
  1216. + 64 bit operations (badly tested), everything is implemented now!
  1217. * some small fixes
  1218. Revision 1.2 2002/07/27 20:00:59 jonas
  1219. + second_addboolean(), second_addfloat() and second_addsmallset()
  1220. (64bit stuff is all that's left to do)
  1221. Revision 1.1 2002/07/26 12:31:57 jonas
  1222. + intial implementation of add nodes, only integer/enumeration/pointer/...
  1223. handling is finished
  1224. }