nppcadd.pas 54 KB

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