ncpuadd.pas 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  1. {******************************************************************************
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. Code generation for add nodes on the i386
  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. unit ncpuadd;
  18. {$INCLUDE fpcdefs.inc}
  19. interface
  20. uses
  21. node,nadd,cpubase,cginfo;
  22. type
  23. TSparcAddNode=class(TAddNode)
  24. procedure pass_2;override;
  25. private
  26. procedure clear_left_right(cmpop:Boolean);
  27. procedure second_addboolean;
  28. procedure second_add64bit;
  29. procedure second_addfloat;
  30. function GetResFlags(unsigned:Boolean):TResFlags;
  31. procedure emit_compare(unsigned:boolean);
  32. procedure left_must_be_reg(OpSize:TcgSize;NoSwap:Boolean);
  33. procedure emit_generic_code(op:TAsmOp;OpSize:TcgSize;unsigned,extra_not,mboverflow:Boolean);
  34. procedure emit_op_right_left(op:TAsmOp);
  35. procedure Load_left_right(cmpop,load_constants:Boolean);
  36. procedure pass_left_and_right;
  37. procedure set_result_location(cmpOp,unsigned:Boolean);
  38. end;
  39. implementation
  40. uses
  41. globtype,systems,
  42. cutils,verbose,globals,
  43. symconst,symdef,SymType,paramgr,
  44. aasmbase,aasmtai,aasmcpu,defutil,htypechk,
  45. cpuinfo,cgbase,pass_2,regvars,
  46. cpupara,
  47. ncon,nset,
  48. ncgutil,tgobj,rgobj,rgcpu,cgobj,cg64f32;
  49. procedure TSparcAddNode.clear_left_right(cmpop:Boolean);
  50. begin
  51. if(right.location.loc in [LOC_REGISTER,LOC_FPUREGISTER])and(cmpop or(location.register.enum <> right.location.register.enum))
  52. then
  53. begin
  54. rg.UnGetRegisterInt(exprasmlist,right.location.register);
  55. if is_64bitint(right.resulttype.def)
  56. then
  57. rg.UnGetRegisterInt(exprasmlist,right.location.registerhigh);
  58. end;
  59. if(left.location.loc in [LOC_REGISTER,LOC_FPUREGISTER])and(cmpop or(location.register.enum <> left.location.register.enum))
  60. then
  61. begin
  62. rg.UnGetRegisterInt(exprasmlist,left.location.register);
  63. if is_64bitint(left.resulttype.def)
  64. then
  65. rg.UnGetRegisterInt(exprasmlist,left.location.registerhigh);
  66. end;
  67. end;
  68. procedure TSparcAddNode.second_addboolean;
  69. var
  70. cgop:TOpCg;
  71. cgsize:TCgSize;
  72. cmpop,isjump:boolean;
  73. otl,ofl:tasmlabel;
  74. pushedregs:TMaybeSave;
  75. begin
  76. { calculate the operator which is more difficult }
  77. firstcomplex(self);
  78. cmpop:=false;
  79. if (torddef(left.resulttype.def).typ=bool8bit) or
  80. (torddef(right.resulttype.def).typ=bool8bit)
  81. then
  82. cgsize:=OS_8
  83. else if (torddef(left.resulttype.def).typ=bool16bit) or
  84. (torddef(right.resulttype.def).typ=bool16bit)
  85. then
  86. cgsize:=OS_16
  87. else
  88. cgsize:=OS_32;
  89. if (cs_full_boolean_eval in aktlocalswitches) or
  90. (nodetype in [unequaln,ltn,lten,gtn,gten,equaln,xorn])
  91. then
  92. begin
  93. if left.nodetype in [ordconstn,realconstn]
  94. then
  95. swapleftright;
  96. isjump:=(left.location.loc=LOC_JUMP);
  97. if isjump
  98. then
  99. begin
  100. otl:=truelabel;
  101. objectlibrary.getlabel(truelabel);
  102. ofl:=falselabel;
  103. objectlibrary.getlabel(falselabel);
  104. end;
  105. secondpass(left);
  106. if left.location.loc in [LOC_FLAGS,LOC_JUMP]
  107. then
  108. location_force_reg(exprasmlist,left.location,cgsize,false);
  109. if isjump
  110. then
  111. begin
  112. truelabel:=otl;
  113. falselabel:=ofl;
  114. end;
  115. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  116. isjump:=(right.location.loc=LOC_JUMP);
  117. if isjump
  118. then
  119. begin
  120. otl:=truelabel;
  121. objectlibrary.getlabel(truelabel);
  122. ofl:=falselabel;
  123. objectlibrary.getlabel(falselabel);
  124. end;
  125. secondpass(right);
  126. maybe_restore(exprasmlist,left.location,pushedregs);
  127. if right.location.loc in [LOC_FLAGS,LOC_JUMP]
  128. then
  129. location_force_reg(exprasmlist,right.location,cgsize,false);
  130. if isjump
  131. then
  132. begin
  133. truelabel:=otl;
  134. falselabel:=ofl;
  135. end;
  136. cmpop := nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  137. { set result location }
  138. if not cmpop
  139. then
  140. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  141. else
  142. location_reset(location,LOC_FLAGS,OS_NO);
  143. load_left_right(cmpop,false);
  144. if (left.location.loc = LOC_CONSTANT)
  145. then
  146. swapleftright;
  147. { compare the }
  148. case nodetype of
  149. ltn,lten,gtn,gten,
  150. equaln,unequaln :
  151. begin
  152. if (right.location.loc <> LOC_CONSTANT)
  153. then
  154. exprasmlist.concat(taicpu.op_reg_reg(A_JMPL,left.location.register,right.location.register))
  155. else
  156. exprasmlist.concat(taicpu.op_reg_const(A_JMPL,left.location.register,right.location.value));
  157. location.resflags := GetResFlags(true);
  158. end;
  159. else
  160. begin
  161. case nodetype of
  162. xorn :
  163. cgop:=OP_XOR;
  164. orn :
  165. cgop:=OP_OR;
  166. andn :
  167. cgop:=OP_AND;
  168. else
  169. internalerror(200203247);
  170. end;
  171. if right.location.loc <> LOC_CONSTANT
  172. then
  173. cg.a_op_reg_reg_reg(exprasmlist,cgop,OS_INT,left.location.register,right.location.register,location.register)
  174. else
  175. cg.a_op_const_reg_reg(exprasmlist,cgop,OS_INT,right.location.value,left.location.register,location.register);
  176. end;
  177. end;
  178. end
  179. else
  180. begin
  181. // just to make sure we free the right registers
  182. cmpop := true;
  183. case nodetype of
  184. andn,
  185. orn :
  186. begin
  187. location_reset(location,LOC_JUMP,OS_NO);
  188. case nodetype of
  189. andn :
  190. begin
  191. otl:=truelabel;
  192. objectlibrary.getlabel(truelabel);
  193. secondpass(left);
  194. maketojumpbool(exprasmlist,left,lr_load_regvars);
  195. cg.a_label(exprasmlist,truelabel);
  196. truelabel:=otl;
  197. end;
  198. orn :
  199. begin
  200. ofl:=falselabel;
  201. objectlibrary.getlabel(falselabel);
  202. secondpass(left);
  203. maketojumpbool(exprasmlist,left,lr_load_regvars);
  204. cg.a_label(exprasmlist,falselabel);
  205. falselabel:=ofl;
  206. end;
  207. else
  208. CGMessage(type_e_mismatch);
  209. end;
  210. secondpass(right);
  211. maketojumpbool(exprasmlist,right,lr_load_regvars);
  212. end;
  213. end;
  214. end;
  215. clear_left_right(CmpOp);
  216. end;
  217. function TSparcAddNode.GetResFlags(unsigned:Boolean):TResFlags;
  218. begin
  219. case NodeType of
  220. equaln:
  221. GetResFlags:=F_E;
  222. unequaln:
  223. GetResFlags:=F_NE;
  224. else
  225. if not(unsigned)
  226. then
  227. if nf_swaped IN flags
  228. then
  229. case NodeType of
  230. ltn:
  231. GetResFlags:=F_G;
  232. lten:
  233. GetResFlags:=F_GE;
  234. gtn:
  235. GetResFlags:=F_L;
  236. gten:
  237. GetResFlags:=F_LE;
  238. end
  239. else
  240. case NodeType of
  241. ltn:
  242. GetResFlags:=F_L;
  243. lten:
  244. GetResFlags:=F_LE;
  245. gtn:
  246. GetResFlags:=F_G;
  247. gten:
  248. GetResFlags:=F_GE;
  249. end
  250. else
  251. if nf_swaped IN Flags
  252. then
  253. case NodeType of
  254. ltn:
  255. GetResFlags:=F_A;
  256. lten:
  257. GetResFlags:=F_AE;
  258. gtn:
  259. GetResFlags:=F_B;
  260. gten:
  261. GetResFlags:=F_BE;
  262. end
  263. else
  264. case NodeType of
  265. ltn:
  266. GetResFlags:=F_B;
  267. lten:
  268. GetResFlags:=F_BE;
  269. gtn:
  270. GetResFlags:=F_A;
  271. gten:
  272. GetResFlags:=F_AE;
  273. end;
  274. end;
  275. end;
  276. procedure TSparcAddNode.left_must_be_reg(OpSize:TcgSize;NoSwap:Boolean);
  277. begin
  278. if(left.location.loc=LOC_REGISTER)
  279. then
  280. exit;
  281. {left location is not a register}
  282. if(not NoSwap)and(right.location.loc=LOC_REGISTER)
  283. then{right is register so we can swap the locations}
  284. begin
  285. location_swap(left.location,right.location);
  286. toggleflag(nf_swaped);
  287. end
  288. else
  289. begin
  290. {maybe we can reuse a constant register when the operation is a comparison that
  291. doesn't change the value of the register}
  292. location_force_reg(exprasmlist,left.location,opsize,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
  293. end;
  294. end;
  295. procedure TSparcAddNode.emit_generic_code(op:TAsmOp;OpSize:TcgSize;unsigned,extra_not,mboverflow:Boolean);
  296. var
  297. power:LongInt;
  298. hl4:TAsmLabel;
  299. begin
  300. { at this point, left.location.loc should be LOC_REGISTER }
  301. with ExprAsmList do
  302. if right.location.loc=LOC_REGISTER
  303. then
  304. begin
  305. { right.location is a LOC_REGISTER }
  306. { when swapped another result register }
  307. if(nodetype=subn)and(nf_swaped in flags)
  308. then
  309. begin
  310. if extra_not
  311. then
  312. Concat(Taicpu.Op_reg(A_NOT,left.location.register));
  313. Concat(Taicpu.Op_reg_reg_reg(Op,right.location.register,left.location.register,right.location.register));
  314. { newly swapped also set swapped flag }
  315. location_swap(left.location,right.location);
  316. toggleflag(nf_swaped);
  317. end
  318. else
  319. begin
  320. if extra_not
  321. then
  322. Concat(Taicpu.Op_reg(A_NOT,right.location.register));
  323. // emit_reg_reg(op,opsize,right.location.register,left.location.register);
  324. exprasmList.concat(Taicpu.Op_reg_reg_reg(Op,right.location.register,left.location.register,right.location.register));
  325. end;
  326. end
  327. ELSE
  328. begin
  329. { right.location is not a LOC_REGISTER }
  330. IF(nodetype=subn)AND(nf_swaped IN flags)
  331. THEN
  332. begin
  333. IF extra_not
  334. THEN
  335. exprasmList.concat(Taicpu.Op_reg(A_NOT,left.location.register));
  336. // rg.getexplicitregisterint(exprasmlist,R_EDI);
  337. // cg.a_load_loc_reg(exprasmlist,right.location,R_EDI);
  338. // emit_reg_reg(op,opsize,left.location.register,R_EDI);
  339. // emit_reg_reg(A_MOV,opsize,R_EDI,left.location.register);
  340. // rg.ungetregisterint(exprasmlist,R_EDI);
  341. end
  342. ELSE
  343. begin
  344. { Optimizations when right.location is a constant value }
  345. IF(op=A_CMP)AND(nodetype IN [equaln,unequaln])AND(right.location.loc=LOC_CONSTANT)AND(right.location.value=0)
  346. THEN
  347. begin
  348. // emit_reg_reg(A_TEST,opsize,left.location.register,left.location.register);
  349. end
  350. ELSE IF(op=A_ADD)AND(right.location.loc=LOC_CONSTANT)AND(right.location.value=1)AND NOT(cs_check_overflow in aktlocalswitches)
  351. THEN
  352. with ExprAsmList,left.location do
  353. begin
  354. concat(TAiCpu.op_reg_const_reg(A_ADD,register,1,register));
  355. end
  356. ELSE IF(op=A_SUB)AND(right.location.loc=LOC_CONSTANT)AND(right.location.value=1)AND NOT(cs_check_overflow in aktlocalswitches)
  357. THEN
  358. begin
  359. exprasmList.concat(Taicpu.Op_reg(A_DEC,left.location.register));
  360. end
  361. ELSE IF(op=A_SMUL)AND(right.location.loc=LOC_CONSTANT)AND(ispowerof2(right.location.value,power))AND NOT(cs_check_overflow in aktlocalswitches)
  362. THEN
  363. begin
  364. exprasmList.concat(Taicpu.Op_const_reg(A_SLL,power,left.location.register));
  365. end
  366. ELSE
  367. begin
  368. IF extra_not
  369. THEN
  370. begin
  371. // rg.getexplicitregisterint(exprasmlist,R_EDI);
  372. // cg.a_load_loc_reg(exprasmlist,right.location,R_EDI);
  373. // emit_reg(A_NOT,S_L,R_EDI);
  374. // emit_reg_reg(A_AND,S_L,R_EDI,left.location.register);
  375. // rg.ungetregisterint(exprasmlist,R_EDI);
  376. end
  377. ELSE
  378. begin
  379. emit_op_right_left(op);
  380. end;
  381. end;
  382. end;
  383. end;
  384. { only in case of overflow operations }
  385. { produce overflow code }
  386. { we must put it here directly, because sign of operation }
  387. { is in unsigned VAR!! }
  388. IF mboverflow
  389. THEN
  390. begin
  391. IF cs_check_overflow IN aktlocalswitches
  392. THEN
  393. begin
  394. objectlibrary.getlabel(hl4);
  395. IF unsigned
  396. THEN
  397. exprasmList.concat(Taicpu.Op_sym(A_JMPL,hl4))
  398. ELSE
  399. exprasmList.concat(Taicpu.Op_sym(A_JMPL,hl4));
  400. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  401. cg.a_label(exprasmlist,hl4);
  402. end;
  403. end;
  404. end;
  405. procedure TSparcAddNode.emit_compare(unsigned:boolean);
  406. var
  407. op:tasmop;
  408. tmpreg:tregister;
  409. useconst:boolean;
  410. begin
  411. // get the constant on the right if there is one
  412. if(left.location.loc=LOC_CONSTANT)
  413. then
  414. swapleftright;
  415. // can we use an immediate, or do we have to load the
  416. // constant in a register first?
  417. if(right.location.loc=LOC_CONSTANT)
  418. then
  419. begin
  420. {$ifdef ExtDebug}
  421. if (right.location.size in [OS_64,OS_S64]) and (hi(right.location.valueqword)<>0) and ((hi(right.location.valueqword)<>aword($ffffffff)) or unsigned)
  422. then
  423. internalerror(2002080301);
  424. {$endif extdebug}
  425. if (nodetype in [equaln,unequaln])
  426. then
  427. if (unsigned and
  428. (right.location.value > high(word))) or
  429. (not unsigned and
  430. (longint(right.location.value) < low(smallint)) or
  431. (longint(right.location.value) > high(smallint))) then
  432. { we can then maybe use a constant in the 'othersigned' case
  433. (the sign doesn't matter for // equal/unequal)}
  434. unsigned := not unsigned;
  435. if (unsigned and
  436. ((right.location.value) <= high(word))) or
  437. (not(unsigned) and
  438. (longint(right.location.value) >= low(smallint)) and
  439. (longint(right.location.value) <= high(smallint)))
  440. then
  441. useconst := true
  442. else
  443. begin
  444. useconst := false;
  445. tmpreg := cg.get_scratch_reg_int(exprasmlist,OS_INT);
  446. cg.a_load_const_reg(exprasmlist,OS_INT,right.location.value,tmpreg);
  447. end
  448. end
  449. else
  450. useconst := false;
  451. location.loc := LOC_FLAGS;
  452. location.resflags:=getresflags(False);
  453. op:=A_CMP;
  454. if (right.location.loc = LOC_CONSTANT)
  455. then
  456. if useconst
  457. then
  458. exprasmlist.concat(taicpu.op_reg_const(op,
  459. left.location.register,right.location.value))
  460. else
  461. begin
  462. exprasmlist.concat(taicpu.op_reg_reg(op,left.location.register,tmpreg));
  463. cg.free_scratch_reg(exprasmlist,tmpreg);
  464. end
  465. else
  466. exprasmlist.concat(taicpu.op_reg_reg(op,
  467. left.location.register,right.location.register));
  468. end;
  469. procedure TSparcAddNode.emit_op_right_left(op:TAsmOp);
  470. begin
  471. {left must be a register}
  472. with left,location,exprasmlist do
  473. case Right.Location.Loc of
  474. LOC_REGISTER,LOC_CREGISTER:
  475. concat(taicpu.op_reg_reg_reg(op,Register,Right.Location.register,register));
  476. LOC_REFERENCE,LOC_CREFERENCE :
  477. begin
  478. location_force_reg(exprasmlist,Right.Location,OS_32,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
  479. concat(taicpu.op_reg_reg_reg(op,register,Right.Location.register,register));
  480. end;
  481. LOC_CONSTANT:
  482. concat(taicpu.op_reg_const_reg(op,register,Right.Location.value,register));
  483. else
  484. InternalError(200203232);
  485. end;
  486. end;
  487. procedure TSparcAddNode.second_add64bit;
  488. var
  489. op : TOpCG;
  490. op1,op2 : TAsmOp;
  491. cmpop,
  492. unsigned : boolean;
  493. r : Tregister;
  494. procedure emit_cmp64_hi;
  495. var
  496. oldleft, oldright: tlocation;
  497. begin
  498. // put the high part of the location in the low part
  499. location_copy(oldleft,left.location);
  500. location_copy(oldright,right.location);
  501. if left.location.loc = LOC_CONSTANT
  502. then
  503. left.location.valueqword := left.location.valueqword shr 32
  504. else
  505. left.location.registerlow := left.location.registerhigh;
  506. if right.location.loc = LOC_CONSTANT
  507. then
  508. right.location.valueqword := right.location.valueqword shr 32
  509. else
  510. right.location.registerlow := right.location.registerhigh;
  511. // and call the normal emit_compare
  512. emit_compare(unsigned);
  513. location_copy(left.location,oldleft);
  514. location_copy(right.location,oldright);
  515. end;
  516. procedure emit_cmp64_lo;
  517. begin
  518. emit_compare(true);
  519. end;
  520. procedure firstjmp64bitcmp;
  521. var
  522. oldnodetype: tnodetype;
  523. begin
  524. load_all_regvars(exprasmlist);
  525. { the jump the sequence is a little bit hairy }
  526. case nodetype of
  527. ltn,gtn:
  528. begin
  529. cg.a_jmp_flags(exprasmlist,getresflags(false),truelabel);
  530. { cheat a little bit for the negative test }
  531. toggleflag(nf_swaped);
  532. cg.a_jmp_flags(exprasmlist,getresflags(false),falselabel);
  533. toggleflag(nf_swaped);
  534. end;
  535. lten,gten:
  536. begin
  537. oldnodetype:=nodetype;
  538. if nodetype=lten then
  539. nodetype:=ltn
  540. else
  541. nodetype:=gtn;
  542. cg.a_jmp_flags(exprasmlist,getresflags(false),truelabel);
  543. { cheat for the negative test }
  544. if nodetype=ltn then
  545. nodetype:=gtn
  546. else
  547. nodetype:=ltn;
  548. cg.a_jmp_flags(exprasmlist,getresflags(false),falselabel);
  549. nodetype:=oldnodetype;
  550. end;
  551. equaln:
  552. begin
  553. nodetype := unequaln;
  554. cg.a_jmp_flags(exprasmlist,getresflags(true),falselabel);
  555. nodetype := equaln;
  556. end;
  557. unequaln:
  558. begin
  559. cg.a_jmp_flags(exprasmlist,getresflags(true),truelabel);
  560. end;
  561. end;
  562. end;
  563. procedure secondjmp64bitcmp;
  564. begin
  565. { the jump the sequence is a little bit hairy }
  566. case nodetype of
  567. ltn,gtn,lten,gten:
  568. begin
  569. { the comparison of the low dword always has }
  570. { to be always unsigned! }
  571. cg.a_jmp_flags(exprasmlist,getresflags(false),truelabel);
  572. cg.a_jmp_always(exprasmlist,falselabel);
  573. end;
  574. equaln:
  575. begin
  576. nodetype := unequaln;
  577. cg.a_jmp_flags(exprasmlist,getresflags(true),falselabel);
  578. cg.a_jmp_always(exprasmlist,truelabel);
  579. nodetype := equaln;
  580. end;
  581. unequaln:
  582. begin
  583. cg.a_jmp_flags(exprasmlist,getresflags(true),truelabel);
  584. cg.a_jmp_always(exprasmlist,falselabel);
  585. end;
  586. end;
  587. end;
  588. var
  589. tempreg64: tregister64;
  590. zeroreg : tregister;
  591. begin
  592. firstcomplex(self);
  593. pass_left_and_right;
  594. cmpop:=false;
  595. unsigned:=((left.resulttype.def.deftype=orddef) and
  596. (torddef(left.resulttype.def).typ=u64bit)) or
  597. ((right.resulttype.def.deftype=orddef) and
  598. (torddef(right.resulttype.def).typ=u64bit));
  599. case nodetype of
  600. addn :
  601. begin
  602. op:=OP_ADD;
  603. end;
  604. subn :
  605. begin
  606. op:=OP_SUB;
  607. end;
  608. ltn,lten,
  609. gtn,gten,
  610. equaln,unequaln:
  611. begin
  612. op:=OP_NONE;
  613. cmpop:=true;
  614. end;
  615. xorn:
  616. op:=OP_XOR;
  617. orn:
  618. op:=OP_OR;
  619. andn:
  620. op:=OP_AND;
  621. muln:
  622. begin
  623. { should be handled in pass_1 (JM) }
  624. internalerror(200109051);
  625. end;
  626. else
  627. internalerror(2002072705);
  628. end;
  629. if not cmpop then
  630. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def));
  631. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches) and (nodetype in [addn,subn]));
  632. if not(cs_check_overflow in aktlocalswitches) or
  633. not(nodetype in [addn,subn]) then
  634. begin
  635. case nodetype of
  636. ltn,lten,
  637. gtn,gten:
  638. begin
  639. emit_cmp64_hi;
  640. firstjmp64bitcmp;
  641. emit_cmp64_lo;
  642. secondjmp64bitcmp;
  643. end;
  644. equaln,unequaln:
  645. begin
  646. // instead of doing a complicated compare, do
  647. // (left.hi xor right.hi) or (left.lo xor right.lo)
  648. // (somewhate optimized so that no superfluous 'mr's are
  649. // generated)
  650. if (left.location.loc = LOC_CONSTANT) then
  651. swapleftright;
  652. if (right.location.loc = LOC_CONSTANT) then
  653. begin
  654. if left.location.loc = LOC_REGISTER then
  655. begin
  656. tempreg64.reglo := left.location.registerlow;
  657. tempreg64.reghi := left.location.registerhigh;
  658. end
  659. else
  660. begin
  661. if (right.location.valueqword <> 0)
  662. then
  663. tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist,OS_INT)
  664. else
  665. tempreg64.reglo := left.location.registerlow;
  666. if (hi(right.location.valueqword) <> 0) then
  667. tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist,OS_INT)
  668. else
  669. tempreg64.reghi := left.location.registerhigh;
  670. end;
  671. if (right.location.valueqword <> 0) then
  672. { negative values can be handled using SUB, }
  673. { positive values < 65535 using XOR. }
  674. if (longint(lo(right.location.valueqword)) >= -32767) and
  675. (longint(lo(right.location.valueqword)) < 0) then
  676. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  677. lo(right.location.valueqword),
  678. left.location.registerlow,tempreg64.reglo)
  679. else
  680. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  681. lo(right.location.valueqword),
  682. left.location.registerlow,tempreg64.reglo);
  683. if (hi(right.location.valueqword)<>0) then
  684. if (longint(hi(right.location.valueqword))>= -32767) and
  685. (longint(hi(right.location.valueqword)) < 0) then
  686. cg.a_op_const_reg_reg(exprasmlist,OP_SUB,OS_INT,
  687. hi(right.location.valueqword),
  688. left.location.registerhigh,tempreg64.reghi)
  689. else
  690. cg.a_op_const_reg_reg(exprasmlist,OP_XOR,OS_INT,
  691. hi(right.location.valueqword),
  692. left.location.registerhigh,tempreg64.reghi);
  693. end
  694. else
  695. begin
  696. tempreg64.reglo := cg.get_scratch_reg_int(exprasmlist,OS_INT);
  697. tempreg64.reghi := cg.get_scratch_reg_int(exprasmlist,OS_INT);
  698. cg64.a_op64_reg_reg_reg(exprasmlist,OP_XOR,
  699. left.location.register64,right.location.register64,
  700. tempreg64);
  701. end;
  702. zeroreg.enum:=R_INTREGISTER;
  703. zeroreg.number:=NR_G0;
  704. cg.a_reg_alloc(exprasmlist,zeroreg);
  705. exprasmlist.concat(taicpu.op_reg_reg_reg(A_OR,zeroreg,tempreg64.reglo,tempreg64.reghi));
  706. cg.a_reg_dealloc(exprasmlist,zeroreg);
  707. if (tempreg64.reglo.number <> left.location.registerlow.number) then
  708. cg.free_scratch_reg(exprasmlist,tempreg64.reglo);
  709. if (tempreg64.reghi.number <> left.location.registerhigh.number) then
  710. cg.free_scratch_reg(exprasmlist,tempreg64.reghi);
  711. location_reset(location,LOC_FLAGS,OS_NO);
  712. location.resflags := getresflags(true);
  713. end;
  714. xorn,orn,andn,addn:
  715. begin
  716. if (location.registerlow.number = NR_NO) then
  717. begin
  718. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  719. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  720. end;
  721. if (left.location.loc = LOC_CONSTANT) then
  722. swapleftright;
  723. if (right.location.loc = LOC_CONSTANT) then
  724. cg64.a_op64_const_reg_reg(exprasmlist,op,right.location.valueqword,
  725. left.location.register64,location.register64)
  726. else
  727. cg64.a_op64_reg_reg_reg(exprasmlist,op,right.location.register64,
  728. left.location.register64,location.register64);
  729. end;
  730. subn:
  731. begin
  732. if (nf_swaped in flags) then
  733. swapleftright;
  734. if left.location.loc <> LOC_CONSTANT then
  735. begin
  736. if (location.registerlow.number = NR_NO) then
  737. begin
  738. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  739. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  740. end;
  741. if right.location.loc <> LOC_CONSTANT then
  742. // reg64 - reg64
  743. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  744. right.location.register64,left.location.register64,
  745. location.register64)
  746. else
  747. // reg64 - const64
  748. cg64.a_op64_const_reg_reg(exprasmlist,OP_SUB,
  749. right.location.valueqword,left.location.register64,
  750. location.register64)
  751. end
  752. else if ((left.location.valueqword shr 32) = 0) then
  753. begin
  754. if (location.registerlow.number = NR_NO) then
  755. begin
  756. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  757. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  758. end;
  759. if (int64(left.location.valueqword) >= low(smallint)) and
  760. (int64(left.location.valueqword) <= high(smallint))
  761. then
  762. begin
  763. // consts16 - reg64
  764. exprasmlist.concat(taicpu.op_reg_const_Reg(A_SUBcc,location.registerlow,left.location.value,right.location.registerlow));
  765. end
  766. else
  767. begin
  768. // const32 - reg64
  769. cg.a_load_const_reg(exprasmlist,OS_32,
  770. left.location.valueqword,location.registerlow);
  771. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBcc,
  772. location.registerlow,location.registerlow,
  773. right.location.registerlow));
  774. end;
  775. exprasmlist.concat(taicpu.op_reg_reg(A_SUBcc,
  776. location.registerhigh,right.location.registerhigh));
  777. end
  778. else if (left.location.valueqword = 0) then
  779. begin
  780. // (const32 shl 32) - reg64
  781. if (location.registerlow.number = NR_NO) then
  782. begin
  783. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  784. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  785. end;
  786. exprasmlist.concat(taicpu.op_reg_Const_reg(A_SUBcc,location.registerlow,0,right.location.registerlow));
  787. cg.a_load_const_reg(exprasmlist,OS_INT,
  788. left.location.valueqword shr 32,location.registerhigh);
  789. exprasmlist.concat(taicpu.op_reg_reg_reg(A_SUBcc,
  790. location.registerhigh,right.location.registerhigh,
  791. location.registerhigh));
  792. end
  793. else
  794. begin
  795. // const64 - reg64
  796. location_force_reg(exprasmlist,left.location,
  797. def_cgsize(left.resulttype.def),true);
  798. if (left.location.loc = LOC_REGISTER) then
  799. location.register64 := left.location.register64
  800. else if (location.registerlow.number = NR_NO) then
  801. begin
  802. location.registerlow := rg.getregisterint(exprasmlist,OS_INT);
  803. location.registerhigh := rg.getregisterint(exprasmlist,OS_INT);
  804. end;
  805. cg64.a_op64_reg_reg_reg(exprasmlist,OP_SUB,
  806. right.location.register64,left.location.register64,
  807. location.register64);
  808. end;
  809. end;
  810. else
  811. internalerror(2002072803);
  812. end;
  813. end
  814. else
  815. begin
  816. case nodetype of
  817. addn:
  818. begin
  819. op1 := A_ADDcc;
  820. op2 := A_ADDcc;
  821. end;
  822. subn:
  823. begin
  824. op1 := A_SUBcc;
  825. op2 := A_SUBcc;
  826. end;
  827. else
  828. internalerror(2002072806);
  829. end;
  830. exprasmlist.concat(taicpu.op_reg_reg_reg(op1,location.registerlow,
  831. left.location.registerlow,right.location.registerlow));
  832. exprasmlist.concat(taicpu.op_reg_reg_reg(op2,location.registerhigh,
  833. right.location.registerhigh,left.location.registerhigh));
  834. cg.g_overflowcheck(exprasmlist,self);
  835. end;
  836. { set result location }
  837. { (emit_compare sets it to LOC_FLAGS for compares, so set the }
  838. { real location only now) (JM) }
  839. if cmpop and
  840. not(nodetype in [equaln,unequaln]) then
  841. location_reset(location,LOC_JUMP,OS_NO);
  842. clear_left_right(cmpop);
  843. end;
  844. procedure TSparcAddNode.load_left_right(cmpop,load_constants:Boolean);
  845. procedure load_node(var n:tnode);
  846. begin
  847. case n.location.loc of
  848. LOC_REGISTER:
  849. if not cmpop
  850. then
  851. begin
  852. location.register := n.location.register;
  853. if is_64bitint(n.resulttype.def)
  854. then
  855. location.registerhigh := n.location.registerhigh;
  856. end;
  857. LOC_REFERENCE,LOC_CREFERENCE:
  858. begin
  859. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  860. if not cmpop
  861. then
  862. begin
  863. location.register := n.location.register;
  864. if is_64bitint(n.resulttype.def)
  865. then
  866. location.registerhigh := n.location.registerhigh;
  867. end;
  868. end;
  869. LOC_CONSTANT:
  870. begin
  871. if load_constants
  872. then
  873. begin
  874. location_force_reg(exprasmlist,n.location,def_cgsize(n.resulttype.def),false);
  875. if not cmpop
  876. then
  877. location.register := n.location.register;
  878. if is_64bitint(n.resulttype.def)
  879. then
  880. location.registerhigh := n.location.registerhigh;
  881. end;
  882. end;
  883. end;
  884. end;
  885. begin
  886. load_node(left);
  887. load_node(right);
  888. end;
  889. procedure TSparcAddNode.second_addfloat;
  890. var
  891. reg : tregister;
  892. op : TAsmOp;
  893. cmpop : boolean;
  894. r : Tregister;
  895. procedure location_force_fpureg(var l: tlocation);
  896. begin
  897. if not(l.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
  898. begin
  899. reg := rg.getregisterfpu(exprasmlist);
  900. cg.a_loadfpu_loc_reg(exprasmlist,l,reg);
  901. location_freetemp(exprasmlist,l);
  902. location_release(exprasmlist,l);
  903. location_reset(l,LOC_FPUREGISTER,l.size);
  904. l.register := reg;
  905. end;
  906. end;
  907. begin
  908. pass_left_and_right;
  909. cmpop:=false;
  910. case nodetype of
  911. addn :
  912. op:=A_FADDs;
  913. muln :
  914. op:=A_FMULs;
  915. subn :
  916. op:=A_FSUBs;
  917. slashn :
  918. op:=A_FDIVs;
  919. ltn,lten,gtn,gten,
  920. equaln,unequaln :
  921. begin
  922. op:=A_FCMPs;
  923. cmpop:=true;
  924. end;
  925. else
  926. CGMessage(type_e_mismatch);
  927. end;
  928. // get the operands in the correct order, there are no special cases
  929. // here, everything is register-based
  930. if nf_swaped in flags then
  931. swapleftright;
  932. // put both operands in a register
  933. location_force_fpureg(right.location);
  934. location_force_fpureg(left.location);
  935. // initialize de result
  936. if not cmpop then
  937. begin
  938. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  939. if left.location.loc = LOC_FPUREGISTER then
  940. location.register := left.location.register
  941. else if right.location.loc = LOC_FPUREGISTER then
  942. location.register := right.location.register
  943. else
  944. location.register := rg.getregisterfpu(exprasmlist);
  945. end
  946. else
  947. begin
  948. location_reset(location,LOC_FLAGS,OS_NO);
  949. location.resflags := getresflags(true);
  950. end;
  951. // emit the actual operation
  952. if not cmpop then
  953. begin
  954. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  955. location.register,left.location.register,
  956. right.location.register))
  957. end
  958. else
  959. begin
  960. r.enum:=R_PSR;
  961. exprasmlist.concat(taicpu.op_reg_reg_reg(op,
  962. r,left.location.register,right.location.register))
  963. end;
  964. // clear_left_right(cmpop);
  965. end;
  966. procedure TSparcAddNode.set_result_location(cmpOp,unsigned:Boolean);
  967. begin
  968. IF cmpOp
  969. THEN
  970. begin
  971. location_reset(location,LOC_FLAGS,OS_NO);
  972. location.resflags:=GetResFlags(unsigned);
  973. end
  974. ELSE
  975. location_copy(location,left.location);
  976. end;
  977. procedure TSparcAddNode.pass_2;
  978. {is also being used for "xor", and "mul", "sub", or and comparative operators}
  979. var
  980. popeax,popedx,pushedfpu,mboverflow,cmpop:Boolean;
  981. op:TAsmOp;
  982. power:LongInt;
  983. OpSize:TcgSize;
  984. unsigned:Boolean;{true, if unsigned types are compared}
  985. extra_not:Boolean;
  986. cgop:TOpCg;
  987. begin
  988. { to make it more readable, string and set (not smallset!) have their own
  989. procedures }
  990. case left.resulttype.def.deftype of
  991. orddef:
  992. if is_boolean(left.resulttype.def)and is_boolean(right.resulttype.def)
  993. then{handling boolean expressions}
  994. begin
  995. second_addboolean;
  996. exit;
  997. end
  998. else if is_64bitint(left.resulttype.def)
  999. then{64bit operations}
  1000. begin
  1001. second_add64bit;
  1002. exit;
  1003. end;
  1004. stringdef:
  1005. InternalError(20020726);//second_addstring;
  1006. setdef:
  1007. {normalsets are already handled in pass1}
  1008. if(tsetdef(left.resulttype.def).settype<>smallset)
  1009. then
  1010. internalerror(200109041)
  1011. else
  1012. InternalError(20020726);//second_addsmallset;
  1013. arraydef :
  1014. InternalError(2002110600);
  1015. floatdef :
  1016. begin
  1017. second_addfloat;
  1018. exit;
  1019. end;
  1020. end;
  1021. {defaults}
  1022. extra_not:=false;
  1023. mboverflow:=false;
  1024. cmpop:=nodetype in [ltn,lten,gtn,gten,equaln,unequaln];
  1025. unsigned:=not(is_signed(left.resulttype.def))or
  1026. not(is_signed(right.resulttype.def));
  1027. opsize:=def_cgsize(left.resulttype.def);
  1028. pass_left_and_right;
  1029. { set result location }
  1030. if not cmpop
  1031. then
  1032. location_reset(location,LOC_REGISTER,def_cgsize(resulttype.def))
  1033. else
  1034. location_reset(location,LOC_FLAGS,OS_NO);
  1035. load_left_right(cmpop,(cs_check_overflow in aktlocalswitches)and(nodetype in [addn,subn,muln]));
  1036. if (location.register.number = NR_NO) and not(cmpop) then
  1037. location.register := rg.getregisterint(exprasmlist,OS_INT);
  1038. if not(cs_check_overflow in aktlocalswitches)or cmpop or (nodetype in [orn,andn,xorn])
  1039. then
  1040. begin
  1041. case NodeType of
  1042. addn:
  1043. begin
  1044. op:=A_ADD;
  1045. mboverflow:=true;
  1046. end;
  1047. muln:
  1048. begin
  1049. IF unsigned
  1050. THEN
  1051. op:=A_UMUL
  1052. ELSE
  1053. op:=A_SMUL;
  1054. mboverflow:=true;
  1055. end;
  1056. subn:
  1057. begin
  1058. op:=A_SUB;
  1059. mboverflow:=true;
  1060. end;
  1061. ltn,lten,
  1062. gtn,gten,
  1063. equaln,unequaln:
  1064. begin
  1065. op:=A_CMP;
  1066. cmpop:=true;
  1067. end;
  1068. xorn:
  1069. op:=A_XOR;
  1070. orn:
  1071. op:=A_OR;
  1072. andn:
  1073. op:=A_AND;
  1074. else
  1075. CGMessage(type_e_mismatch);
  1076. end;
  1077. { Convert flags to register first }
  1078. if (left.location.loc=LOC_FLAGS) then
  1079. location_force_reg(exprasmlist,left.location,opsize,false);
  1080. if (right.location.loc=LOC_FLAGS) then
  1081. location_force_reg(exprasmlist,right.location,opsize,false);
  1082. left_must_be_reg(OpSize,false);
  1083. if not cmpOp then
  1084. emit_generic_code(op,opsize,unsigned,extra_not,mboverflow)
  1085. else
  1086. emit_compare(unsigned);
  1087. location_freetemp(exprasmlist,right.location);
  1088. location_release(exprasmlist,right.location);
  1089. if cmpop and (left.location.loc<>LOC_CREGISTER) then
  1090. begin
  1091. location_freetemp(exprasmlist,left.location);
  1092. location_release(exprasmlist,left.location);
  1093. end;
  1094. end;
  1095. clear_left_right(cmpop);
  1096. end;
  1097. procedure TSparcAddNode.pass_left_and_right;
  1098. var
  1099. pushedregs:tmaybesave;
  1100. tmpreg:tregister;
  1101. pushedfpu:boolean;
  1102. begin
  1103. { calculate the operator which is more difficult }
  1104. firstcomplex(self);
  1105. { in case of constant put it to the left }
  1106. if (left.nodetype=ordconstn)
  1107. then
  1108. swapleftright;
  1109. secondpass(left);
  1110. { are too few registers free? }
  1111. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  1112. if location.loc=LOC_FPUREGISTER
  1113. then
  1114. pushedfpu:=maybe_pushfpu(exprasmlist,right.registersfpu,left.location)
  1115. else
  1116. pushedfpu:=false;
  1117. secondpass(right);
  1118. maybe_restore(exprasmlist,left.location,pushedregs);
  1119. if pushedfpu
  1120. then
  1121. begin
  1122. tmpreg := rg.getregisterfpu(exprasmlist);
  1123. cg.a_loadfpu_loc_reg(exprasmlist,left.location,tmpreg);
  1124. location_reset(left.location,LOC_FPUREGISTER,left.location.size);
  1125. left.location.register := tmpreg;
  1126. end;
  1127. end;
  1128. begin
  1129. cAddNode:=TSparcAddNode;
  1130. end.
  1131. {
  1132. $Log$
  1133. Revision 1.14 2003-05-30 23:57:08 peter
  1134. * more sparc cleanup
  1135. * accumulator removed, splitted in function_return_reg (called) and
  1136. function_result_reg (caller)
  1137. Revision 1.13 2003/05/07 15:05:37 mazen
  1138. * fixed generated code for compare instructions
  1139. Revision 1.12 2003/05/06 21:37:58 mazen
  1140. * adding emit_compare trying fixing compare bugs
  1141. Revision 1.11 2003/03/10 21:59:54 mazen
  1142. * fixing index overflow in handling new registers arrays.
  1143. Revision 1.10 2003/02/19 22:00:17 daniel
  1144. * Code generator converted to new register notation
  1145. - Horribily outdated todo.txt removed
  1146. Revision 1.9 2003/02/13 21:15:18 mazen
  1147. + Load_left_right and clear_left_right implemented fixing test0001 register
  1148. allocation bug.
  1149. Revision 1.8 2003/01/22 20:45:15 mazen
  1150. * making math code in RTL compiling.
  1151. *NB : This does NOT mean necessary that it will generate correct code!
  1152. Revision 1.7 2003/01/20 22:21:36 mazen
  1153. * many stuff related to RTL fixed
  1154. Revision 1.6 2003/01/08 18:43:58 daniel
  1155. * Tregister changed into a record
  1156. Revision 1.5 2003/01/07 22:03:40 mazen
  1157. * adding unequaln node support to sparc compiler
  1158. Revision 1.4 2002/12/30 21:17:22 mazen
  1159. - unit cga no more used in sparc compiler.
  1160. Revision 1.3 2002/12/25 20:59:49 mazen
  1161. - many emitXXX removed from cga.pas in order to remove that file.
  1162. Revision 1.2 2002/12/22 19:26:32 mazen
  1163. * many internal errors related to unimplemented nodes are fixed
  1164. Revision 1.1 2002/12/21 23:21:47 mazen
  1165. + added support for the shift nodes
  1166. + added debug output on screen with -an command line option
  1167. Revision 1.10 2002/11/25 17:43:28 peter
  1168. * splitted defbase in defutil,symutil,defcmp
  1169. * merged isconvertable and is_equal into compare_defs(_ext)
  1170. * made operator search faster by walking the list only once
  1171. Revision 1.9 2002/11/10 19:07:46 mazen
  1172. * SPARC calling mechanism almost OK (as in GCC./mppcsparc )
  1173. Revision 1.8 2002/11/06 15:34:00 mazen
  1174. *** empty log message ***
  1175. Revision 1.7 2002/11/06 11:31:24 mazen
  1176. * op_reg_reg_reg don't need any more a TOpSize parameter
  1177. Revision 1.6 2002/11/05 16:15:00 mazen
  1178. *** empty log message ***
  1179. Revision 1.5 2002/10/22 13:43:01 mazen
  1180. - cga.pas redueced to an empty unit
  1181. Revision 1.4 2002/10/10 20:23:57 mazen
  1182. * tabs replaces by spaces
  1183. }