nppcadd.pas 54 KB

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