nppcadd.pas 57 KB

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