ncpuadd.pas 43 KB

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