nppcadd.pas 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  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. (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.registerhigh := n.location.registerhigh;
  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.registerhigh := n.location.registerhigh;
  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.registerhigh := n.location.registerhigh;
  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.registerhigh := 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. (right.location.value > high(word))) or
  173. (not unsigned and
  174. (longint(right.location.value) < low(smallint)) or
  175. (longint(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. ((right.location.value) <= high(word))) or
  181. (not(unsigned) and
  182. (longint(right.location.value) >= low(smallint)) and
  183. (longint(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. aword(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. aword(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. 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. aword(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. aword(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. aword(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. aword(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. hl4 : tasmlabel;
  590. cmpop,
  591. unsigned : boolean;
  592. r : Tregister;
  593. procedure emit_cmp64_hi;
  594. var
  595. oldleft, oldright: tlocation;
  596. begin
  597. // put the high part of the location in the low part
  598. location_copy(oldleft,left.location);
  599. location_copy(oldright,right.location);
  600. if left.location.loc = LOC_CONSTANT then
  601. left.location.value64 := left.location.value64 shr 32
  602. else
  603. left.location.registerlow := left.location.registerhigh;
  604. if right.location.loc = LOC_CONSTANT then
  605. right.location.value64 := right.location.value64 shr 32
  606. else
  607. right.location.registerlow := right.location.registerhigh;
  608. // and call the normal emit_compare
  609. emit_compare(unsigned);
  610. location_copy(left.location,oldleft);
  611. location_copy(right.location,oldright);
  612. end;
  613. procedure emit_cmp64_lo;
  614. begin
  615. emit_compare(true);
  616. end;
  617. procedure firstjmp64bitcmp;
  618. var
  619. oldnodetype: tnodetype;
  620. begin
  621. {$ifdef OLDREGVARS}
  622. load_all_regvars(exprasmlist);
  623. {$endif OLDREGVARS}
  624. { the jump the sequence is a little bit hairy }
  625. case nodetype of
  626. ltn,gtn:
  627. begin
  628. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  629. { cheat a little bit for the negative test }
  630. toggleflag(nf_swaped);
  631. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  632. toggleflag(nf_swaped);
  633. end;
  634. lten,gten:
  635. begin
  636. oldnodetype:=nodetype;
  637. if nodetype=lten then
  638. nodetype:=ltn
  639. else
  640. nodetype:=gtn;
  641. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  642. { cheat for the negative test }
  643. if nodetype=ltn then
  644. nodetype:=gtn
  645. else
  646. nodetype:=ltn;
  647. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  648. nodetype:=oldnodetype;
  649. end;
  650. equaln:
  651. begin
  652. nodetype := unequaln;
  653. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  654. nodetype := equaln;
  655. end;
  656. unequaln:
  657. begin
  658. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  659. end;
  660. end;
  661. end;
  662. procedure secondjmp64bitcmp;
  663. begin
  664. { the jump the sequence is a little bit hairy }
  665. case nodetype of
  666. ltn,gtn,lten,gten:
  667. begin
  668. { the comparison of the low dword always has }
  669. { to be always unsigned! }
  670. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  671. cg.a_jmp_always(exprasmlist,falselabel);
  672. end;
  673. equaln:
  674. begin
  675. nodetype := unequaln;
  676. cg.a_jmp_flags(exprasmlist,getresflags,falselabel);
  677. cg.a_jmp_always(exprasmlist,truelabel);
  678. nodetype := equaln;
  679. end;
  680. unequaln:
  681. begin
  682. cg.a_jmp_flags(exprasmlist,getresflags,truelabel);
  683. cg.a_jmp_always(exprasmlist,falselabel);
  684. end;
  685. end;
  686. end;
  687. var
  688. tempreg64: tregister64;
  689. begin
  690. firstcomplex(self);
  691. pass_left_and_right;
  692. cmpop:=false;
  693. unsigned:=((left.resulttype.def.deftype=orddef) and
  694. (torddef(left.resulttype.def).typ=u64bit)) or
  695. ((right.resulttype.def.deftype=orddef) and
  696. (torddef(right.resulttype.def).typ=u64bit));
  697. case nodetype of
  698. addn :
  699. begin
  700. op:=OP_ADD;
  701. end;
  702. subn :
  703. begin
  704. op:=OP_SUB;
  705. end;
  706. ltn,lten,
  707. gtn,gten,
  708. equaln,unequaln:
  709. begin
  710. op:=OP_NONE;
  711. cmpop:=true;
  712. end;
  713. xorn:
  714. op:=OP_XOR;
  715. orn:
  716. op:=OP_OR;
  717. andn:
  718. op:=OP_AND;
  719. muln:
  720. begin
  721. { should be handled in pass_1 (JM) }
  722. internalerror(200109051);
  723. end;
  724. else
  725. internalerror(2002072705);
  726. end;
  727. if not cmpop then
  728. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  729. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and
  730. (nodetype in [addn,subn]));
  731. if not(cs_check_overflow in aktlocalswitches) or
  732. not(nodetype in [addn,subn]) then
  733. begin
  734. case nodetype of
  735. ltn,lten,
  736. gtn,gten:
  737. begin
  738. emit_cmp64_hi;
  739. firstjmp64bitcmp;
  740. emit_cmp64_lo;
  741. secondjmp64bitcmp;
  742. end;
  743. equaln,unequaln:
  744. begin
  745. // instead of doing a complicated compare, do
  746. // (left.hi xor right.hi) or (left.lo xor right.lo)
  747. // (somewhate optimized so that no superfluous 'mr's are
  748. // generated)
  749. if (left.location.loc = LOC_CONSTANT) then
  750. swapleftright;
  751. if (right.location.loc = LOC_CONSTANT) then
  752. begin
  753. if left.location.loc = LOC_REGISTER then
  754. begin
  755. tempreg64.reglo := left.location.registerlow;
  756. tempreg64.reghi := left.location.registerhigh;
  757. end
  758. else
  759. begin
  760. if (aword(right.location.value64) <> 0) then
  761. tempreg64.reglo := cg.getintregister(exprasmlist,OS_32)
  762. else
  763. tempreg64.reglo := left.location.registerlow;
  764. if ((right.location.value64 shr 32) <> 0) then
  765. tempreg64.reghi := cg.getintregister(exprasmlist,OS_32)
  766. else
  767. tempreg64.reghi := left.location.registerhigh;
  768. end;
  769. if (aword(right.location.value64) <> 0) then
  770. { negative values can be handled using SUB, }
  771. { positive values < 65535 using XOR. }
  772. if (longint(right.location.value64) >= -32767) and
  773. (longint(right.location.value64) < 0) then
  774. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  775. aword(right.location.value64),
  776. left.location.registerlow,tempreg64.reglo)
  777. else
  778. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  779. aword(right.location.value64),
  780. left.location.registerlow,tempreg64.reglo);
  781. if ((right.location.value64 shr 32) <> 0) then
  782. if (longint(right.location.value64 shr 32) >= -32767) and
  783. (longint(right.location.value64 shr 32) < 0) then
  784. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  785. aword(right.location.value64 shr 32),
  786. left.location.registerhigh,tempreg64.reghi)
  787. else
  788. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  789. aword(right.location.value64 shr 32),
  790. left.location.registerhigh,tempreg64.reghi);
  791. end
  792. else
  793. begin
  794. tempreg64.reglo := cg.getintregister(exprasmlist,OS_INT);
  795. tempreg64.reghi := cg.getintregister(exprasmlist,OS_INT);
  796. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
  797. left.location.register64,right.location.register64,
  798. tempreg64);
  799. end;
  800. cg.a_reg_alloc(exprasmlist,NR_R0);
  801. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR_,NR_R0,
  802. tempreg64.reglo,tempreg64.reghi));
  803. cg.a_reg_dealloc(exprasmlist,NR_R0);
  804. location_reset(location,LOC_FLAGS,OS_NO);
  805. location.resflags := getresflags;
  806. end;
  807. xorn,orn,andn,addn:
  808. begin
  809. if (location.registerlow = NR_NO) then
  810. begin
  811. location.registerlow := cg.getintregister(exprasmlist,OS_INT);
  812. location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
  813. end;
  814. if (left.location.loc = LOC_CONSTANT) then
  815. swapleftright;
  816. if (right.location.loc = LOC_CONSTANT) then
  817. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.value64,
  818. left.location.register64,location.register64)
  819. else
  820. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  821. left.location.register64,location.register64);
  822. end;
  823. subn:
  824. begin
  825. if (nf_swaped in flags) then
  826. swapleftright;
  827. if left.location.loc <> LOC_CONSTANT then
  828. begin
  829. if (location.registerlow = NR_NO) then
  830. begin
  831. location.registerlow := cg.getintregister(exprasmlist,OS_INT);
  832. location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
  833. end;
  834. if right.location.loc <> LOC_CONSTANT then
  835. // reg64 - reg64
  836. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  837. right.location.register64,left.location.register64,
  838. location.register64)
  839. else
  840. // reg64 - const64
  841. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  842. right.location.value64,left.location.register64,
  843. location.register64)
  844. end
  845. else if ((left.location.value64 shr 32) = 0) then
  846. begin
  847. if (location.registerlow = NR_NO) then
  848. begin
  849. location.registerlow := cg.getintregister(exprasmlist,OS_INT);
  850. location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
  851. end;
  852. if (int64(left.location.value64) >= low(smallint)) and
  853. (int64(left.location.value64) <= high(smallint)) then
  854. begin
  855. // consts16 - reg64
  856. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  857. location.registerlow,right.location.registerlow,
  858. aword(left.location.value)));
  859. end
  860. else
  861. begin
  862. // const32 - reg64
  863. location_force_reg(exprasmlist,left.location,
  864. OS_32,true);
  865. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBC,
  866. location.registerlow,left.location.registerlow,
  867. right.location.registerlow));
  868. end;
  869. exprasmlist.concat(taicpu.op_reg_reg(A_SUBFZE,
  870. location.registerhigh,right.location.registerhigh));
  871. end
  872. else if (aword(left.location.value64) = 0) then
  873. begin
  874. // (const32 shl 32) - reg64
  875. if (location.registerlow = NR_NO) then
  876. begin
  877. location.registerlow := cg.getintregister(exprasmlist,OS_INT);
  878. location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
  879. end;
  880. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  881. location.registerlow,right.location.registerlow,0));
  882. left.location.value64 := left.location.value64 shr 32;
  883. location_force_reg(exprasmlist,left.location,OS_32,true);
  884. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBFE,
  885. location.registerhigh,right.location.registerhigh,
  886. left.location.register));
  887. end
  888. else
  889. begin
  890. // const64 - reg64
  891. location_force_reg(exprasmlist,left.location,
  892. def_cgsize(left.resulttype.def),false);
  893. if (left.location.loc = LOC_REGISTER) then
  894. location.register64 := left.location.register64
  895. else if (location.registerlow = NR_NO) then
  896. begin
  897. location.registerlow := cg.getintregister(exprasmlist,OS_INT);
  898. location.registerhigh := cg.getintregister(exprasmlist,OS_INT);
  899. end;
  900. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  901. right.location.register64,left.location.register64,
  902. location.register64);
  903. end;
  904. end;
  905. else
  906. internalerror(2002072803);
  907. end;
  908. end
  909. else
  910. begin
  911. if is_signed(resulttype.def) then
  912. begin
  913. case nodetype of
  914. addn:
  915. begin
  916. op1 := A_ADDC;
  917. op2 := A_ADDEO;
  918. end;
  919. subn:
  920. begin
  921. op1 := A_SUBC;
  922. op2 := A_SUBFEO;
  923. end;
  924. else
  925. internalerror(2002072806);
  926. end
  927. end
  928. else
  929. begin
  930. case nodetype of
  931. addn:
  932. begin
  933. op1 := A_ADDC;
  934. op2 := A_ADDE;
  935. end;
  936. subn:
  937. begin
  938. op1 := A_SUBC;
  939. op2 := A_SUBFE;
  940. end;
  941. end;
  942. end;
  943. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
  944. left.location.registerlow,right.location.registerlow));
  945. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
  946. right.location.registerhigh,left.location.registerhigh));
  947. if not(is_signed(resulttype.def)) then
  948. if nodetype = addn then
  949. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.registerhigh,left.location.registerhigh))
  950. else
  951. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.registerhigh,location.registerhigh));
  952. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  953. end;
  954. { set result location }
  955. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  956. { real location only now) (JM) }
  957. if cmpop and
  958. not(nodetype in [equaln,unequaln]) then
  959. location_reset(location,LOC_JUMP,OS_NO);
  960. end;
  961. {*****************************************************************************
  962. AddMMX
  963. *****************************************************************************}
  964. {$ifdef SUPPORT_MMX}
  965. procedure ti386addnode.second_addmmx;
  966. var
  967. op : TAsmOp;
  968. cmpop : boolean;
  969. mmxbase : tmmxtype;
  970. hregister : tregister;
  971. begin
  972. pass_left_and_right;
  973. cmpop:=false;
  974. mmxbase:=mmx_type(left.resulttype.def);
  975. case nodetype of
  976. addn :
  977. begin
  978. if (cs_mmx_saturation in aktlocalswitches) then
  979. begin
  980. case mmxbase of
  981. mmxs8bit:
  982. op:=A_PADDSB;
  983. mmxu8bit:
  984. op:=A_PADDUSB;
  985. mmxs16bit,mmxfixed16:
  986. op:=A_PADDSB;
  987. mmxu16bit:
  988. op:=A_PADDUSW;
  989. end;
  990. end
  991. else
  992. begin
  993. case mmxbase of
  994. mmxs8bit,mmxu8bit:
  995. op:=A_PADDB;
  996. mmxs16bit,mmxu16bit,mmxfixed16:
  997. op:=A_PADDW;
  998. mmxs32bit,mmxu32bit:
  999. op:=A_PADDD;
  1000. end;
  1001. end;
  1002. end;
  1003. muln :
  1004. begin
  1005. case mmxbase of
  1006. mmxs16bit,mmxu16bit:
  1007. op:=A_PMULLW;
  1008. mmxfixed16:
  1009. op:=A_PMULHW;
  1010. end;
  1011. end;
  1012. subn :
  1013. begin
  1014. if (cs_mmx_saturation in aktlocalswitches) then
  1015. begin
  1016. case mmxbase of
  1017. mmxs8bit:
  1018. op:=A_PSUBSB;
  1019. mmxu8bit:
  1020. op:=A_PSUBUSB;
  1021. mmxs16bit,mmxfixed16:
  1022. op:=A_PSUBSB;
  1023. mmxu16bit:
  1024. op:=A_PSUBUSW;
  1025. end;
  1026. end
  1027. else
  1028. begin
  1029. case mmxbase of
  1030. mmxs8bit,mmxu8bit:
  1031. op:=A_PSUBB;
  1032. mmxs16bit,mmxu16bit,mmxfixed16:
  1033. op:=A_PSUBW;
  1034. mmxs32bit,mmxu32bit:
  1035. op:=A_PSUBD;
  1036. end;
  1037. end;
  1038. end;
  1039. xorn:
  1040. op:=A_PXOR;
  1041. orn:
  1042. op:=A_POR;
  1043. andn:
  1044. op:=A_PAND;
  1045. else
  1046. internalerror(200403183);
  1047. end;
  1048. { left and right no register? }
  1049. { then one must be demanded }
  1050. if (left.location.loc<>LOC_MMXREGISTER) then
  1051. begin
  1052. if (right.location.loc=LOC_MMXREGISTER) then
  1053. begin
  1054. location_swap(left.location,right.location);
  1055. toggleflag(nf_swaped);
  1056. end
  1057. else
  1058. begin
  1059. { register variable ? }
  1060. if (left.location.loc=LOC_CMMXREGISTER) then
  1061. begin
  1062. hregister:=rg.getregistermm(exprasmlist);
  1063. emit_reg_reg(A_MOVQ,S_NO,left.location.register,hregister);
  1064. end
  1065. else
  1066. begin
  1067. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1068. internalerror(200203245);
  1069. location_release(exprasmlist,left.location);
  1070. hregister:=rg.getregistermm(exprasmlist);
  1071. emit_ref_reg(A_MOVQ,S_NO,left.location.reference,hregister);
  1072. end;
  1073. location_reset(left.location,LOC_MMXREGISTER,OS_NO);
  1074. left.location.register:=hregister;
  1075. end;
  1076. end;
  1077. { at this point, left.location.loc should be LOC_MMXREGISTER }
  1078. if right.location.loc<>LOC_MMXREGISTER then
  1079. begin
  1080. if (nodetype=subn) and (nf_swaped in flags) then
  1081. begin
  1082. if right.location.loc=LOC_CMMXREGISTER then
  1083. begin
  1084. emit_reg_reg(A_MOVQ,S_NO,right.location.register,R_MM7);
  1085. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1086. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1087. end
  1088. else
  1089. begin
  1090. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1091. internalerror(200203247);
  1092. emit_ref_reg(A_MOVQ,S_NO,right.location.reference,R_MM7);
  1093. emit_reg_reg(op,S_NO,left.location.register,R_MM7);
  1094. emit_reg_reg(A_MOVQ,S_NO,R_MM7,left.location.register);
  1095. location_release(exprasmlist,right.location);
  1096. end;
  1097. end
  1098. else
  1099. begin
  1100. if (right.location.loc=LOC_CMMXREGISTER) then
  1101. begin
  1102. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1103. end
  1104. else
  1105. begin
  1106. if not(right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  1107. internalerror(200203246);
  1108. emit_ref_reg(op,S_NO,right.location.reference,left.location.register);
  1109. location_release(exprasmlist,right.location);
  1110. end;
  1111. end;
  1112. end
  1113. else
  1114. begin
  1115. { right.location=LOC_MMXREGISTER }
  1116. if (nodetype=subn) and (nf_swaped in flags) then
  1117. begin
  1118. emit_reg_reg(op,S_NO,left.location.register,right.location.register);
  1119. location_swap(left.location,right.location);
  1120. toggleflag(nf_swaped);
  1121. end
  1122. else
  1123. begin
  1124. emit_reg_reg(op,S_NO,right.location.register,left.location.register);
  1125. end;
  1126. end;
  1127. location_freetemp(exprasmlist,right.location);
  1128. location_release(exprasmlist,right.location);
  1129. if cmpop then
  1130. begin
  1131. location_freetemp(exprasmlist,left.location);
  1132. location_release(exprasmlist,left.location);
  1133. end;
  1134. set_result_location(cmpop,true);
  1135. end;
  1136. {$endif SUPPORT_MMX}
  1137. {*****************************************************************************
  1138. pass_2
  1139. *****************************************************************************}
  1140. procedure tppcaddnode.pass_2;
  1141. { is also being used for xor, and "mul", "sub, or and comparative }
  1142. { operators }
  1143. var
  1144. cgop : topcg;
  1145. op : tasmop;
  1146. tmpreg : tregister;
  1147. hl : tasmlabel;
  1148. cmpop : boolean;
  1149. { true, if unsigned types are compared }
  1150. unsigned : boolean;
  1151. begin
  1152. { to make it more readable, string and set (not smallset!) have their
  1153. own procedures }
  1154. case left.resulttype.def.deftype of
  1155. orddef :
  1156. begin
  1157. { handling boolean expressions }
  1158. if is_boolean(left.resulttype.def) and
  1159. is_boolean(right.resulttype.def) then
  1160. begin
  1161. second_addboolean;
  1162. exit;
  1163. end
  1164. { 64bit operations }
  1165. else if is_64bit(left.resulttype.def) then
  1166. begin
  1167. second_add64bit;
  1168. exit;
  1169. end;
  1170. end;
  1171. stringdef :
  1172. begin
  1173. internalerror(2002072402);
  1174. exit;
  1175. end;
  1176. setdef :
  1177. begin
  1178. { normalsets are already handled in pass1 }
  1179. if (tsetdef(left.resulttype.def).settype<>smallset) then
  1180. internalerror(200109041);
  1181. second_addsmallset;
  1182. exit;
  1183. end;
  1184. arraydef :
  1185. begin
  1186. {$ifdef SUPPORT_MMX}
  1187. if is_mmx_able_array(left.resulttype.def) then
  1188. begin
  1189. second_addmmx;
  1190. exit;
  1191. end;
  1192. {$endif SUPPORT_MMX}
  1193. end;
  1194. floatdef :
  1195. begin
  1196. second_addfloat;
  1197. exit;
  1198. end;
  1199. end;
  1200. { defaults }
  1201. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1202. unsigned:=not(is_signed(left.resulttype.def)) or
  1203. not(is_signed(right.resulttype.def));
  1204. pass_left_and_right;
  1205. { Convert flags to register first }
  1206. { can any of these things be in the flags actually?? (JM) }
  1207. if (left.location.loc = LOC_FLAGS) or
  1208. (right.location.loc = LOC_FLAGS) then
  1209. internalerror(2002072602);
  1210. { set result location }
  1211. if not cmpop then
  1212. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1213. else
  1214. location_reset(location,LOC_FLAGS,OS_NO);
  1215. load_left_right(cmpop, (cs_check_overflow in aktlocalswitches) and
  1216. (nodetype in [addn,subn,muln]));
  1217. if (location.register = NR_NO) and
  1218. not(cmpop) then
  1219. location.register := cg.getintregister(exprasmlist,OS_INT);
  1220. if not(cs_check_overflow in aktlocalswitches) or
  1221. (cmpop) or
  1222. (nodetype in [orn,andn,xorn]) then
  1223. begin
  1224. case nodetype of
  1225. addn, muln, xorn, orn, andn:
  1226. begin
  1227. case nodetype of
  1228. addn:
  1229. cgop := OP_ADD;
  1230. muln:
  1231. if unsigned then
  1232. cgop := OP_MUL
  1233. else
  1234. cgop := OP_IMUL;
  1235. xorn:
  1236. cgop := OP_XOR;
  1237. orn:
  1238. cgop := OP_OR;
  1239. andn:
  1240. cgop := OP_AND;
  1241. end;
  1242. if (left.location.loc = LOC_CONSTANT) then
  1243. swapleftright;
  1244. if (right.location.loc <> LOC_CONSTANT) then
  1245. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,
  1246. left.location.register,right.location.register,
  1247. location.register)
  1248. else
  1249. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,
  1250. aword(right.location.value),left.location.register,
  1251. location.register);
  1252. end;
  1253. subn:
  1254. begin
  1255. if (nf_swaped in flags) then
  1256. swapleftright;
  1257. if left.location.loc <> LOC_CONSTANT then
  1258. if right.location.loc <> LOC_CONSTANT then
  1259. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1260. right.location.register,left.location.register,
  1261. location.register)
  1262. else
  1263. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1264. aword(right.location.value),left.location.register,
  1265. location.register)
  1266. else
  1267. if (longint(left.location.value) >= low(smallint)) and
  1268. (longint(left.location.value) <= high(smallint)) then
  1269. begin
  1270. exprasmlist.concat(taicpu.op_reg_reg_const(A_SUBFIC,
  1271. location.register,right.location.register,
  1272. longint(left.location.value)));
  1273. end
  1274. else
  1275. begin
  1276. tmpreg := cg.getintregister(exprasmlist,OS_INT);
  1277. cg.a_load_const_reg(exprasmlist,OS_INT,
  1278. aword(left.location.value),tmpreg);
  1279. cg.a_op_reg_reg_reg(exprasmlist,OP_SUB,OS_INT,
  1280. right.location.register,tmpreg,location.register);
  1281. end;
  1282. end;
  1283. ltn,lten,gtn,gten,equaln,unequaln :
  1284. begin
  1285. emit_compare(unsigned);
  1286. end;
  1287. end;
  1288. end
  1289. else
  1290. // overflow checking is on and we have an addn, subn or muln
  1291. begin
  1292. if is_signed(resulttype.def) then
  1293. begin
  1294. case nodetype of
  1295. addn:
  1296. op := A_ADDO;
  1297. subn:
  1298. op := A_SUBO;
  1299. muln:
  1300. op := A_MULLWO;
  1301. else
  1302. internalerror(2002072601);
  1303. end;
  1304. exprasmlist.concat(taicpu.op_reg_reg_reg(op,location.register,
  1305. left.location.register,right.location.register));
  1306. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1307. end
  1308. else
  1309. begin
  1310. case nodetype of
  1311. addn:
  1312. begin
  1313. exprasmlist.concat(taicpu.op_reg_reg_reg(A_ADD,location.register,
  1314. left.location.register,right.location.register));
  1315. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,location.register,left.location.register));
  1316. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1317. end;
  1318. subn:
  1319. begin
  1320. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUB,location.register,
  1321. left.location.register,right.location.register));
  1322. exprasmlist.concat(taicpu.op_reg_reg(A_CMPLW,left.location.register,location.register));
  1323. cg.g_overflowcheck(exprasmlist,location,resulttype.def);
  1324. end;
  1325. muln:
  1326. begin
  1327. { calculate the upper 32 bits of the product, = 0 if no overflow }
  1328. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULHWU_,location.register,
  1329. left.location.register,right.location.register));
  1330. { calculate the real result }
  1331. exprasmlist.concat(taicpu.op_reg_reg_reg(A_MULLW,location.register,
  1332. left.location.register,right.location.register));
  1333. { g_overflowcheck generates a OC_AE instead of OC_EQ :/ }
  1334. objectlibrary.getlabel(hl);
  1335. tcgppc(cg).a_jmp_cond(exprasmlist,OC_EQ,hl);
  1336. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  1337. cg.a_label(exprasmlist,hl);
  1338. end;
  1339. end;
  1340. end;
  1341. end;
  1342. end;
  1343. begin
  1344. caddnode:=tppcaddnode;
  1345. end.
  1346. {
  1347. $Log$
  1348. Revision 1.49 2004-09-25 14:23:54 peter
  1349. * ungetregister is now only used for cpuregisters, renamed to
  1350. ungetcpuregister
  1351. * renamed (get|unget)explicitregister(s) to ..cpuregister
  1352. * removed location-release/reference_release
  1353. Revision 1.48 2004/08/30 09:28:40 jonas
  1354. * only specially handle 64bit operations on ordinals
  1355. Revision 1.47 2004/07/21 15:09:10 jonas
  1356. * do a resulttypepass of left in the overloaded pass_1 before checking
  1357. its resulttype
  1358. Revision 1.46 2004/07/17 14:47:16 jonas
  1359. - removed useless maybe_pushfpu code for ppc
  1360. Revision 1.45 2004/06/20 08:55:32 florian
  1361. * logs truncated
  1362. Revision 1.44 2004/06/17 16:55:46 peter
  1363. * powerpc compiles again
  1364. Revision 1.43 2004/03/18 16:19:03 peter
  1365. * fixed operator overload allowing for pointer-string
  1366. * replaced some type_e_mismatch with more informational messages
  1367. Revision 1.42 2004/01/06 21:37:41 peter
  1368. * fixed too long ie number
  1369. }