nppcadd.pas 55 KB

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