nppcadd.pas 54 KB

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