nx86add.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. Common code generation for add nodes on the i386 and x86
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {
  19. Common code generation for add nodes on the i386 and x86
  20. }
  21. unit nx86add;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cgbase,
  26. cpubase,
  27. node,nadd,ncgadd;
  28. type
  29. tx86addnode = class(tcgaddnode)
  30. protected
  31. function getresflags(unsigned : boolean) : tresflags;
  32. procedure left_must_be_reg(opsize:TCGSize;noswap:boolean);
  33. procedure left_and_right_must_be_fpureg;
  34. procedure emit_op_right_left(op:TAsmOp;opsize:TOpSize);
  35. procedure emit_generic_code(op:TAsmOp;opsize:TCgSize;unsigned,extra_not,mboverflow:boolean);
  36. procedure second_addfloatsse;
  37. procedure second_mul;virtual;abstract;
  38. public
  39. function first_addstring : tnode; override;
  40. procedure second_addstring;override;
  41. procedure second_addfloat;override;
  42. procedure second_addsmallset;override;
  43. procedure second_add64bit;override;
  44. procedure second_addordinal;override;
  45. procedure second_cmpfloat;override;
  46. procedure second_cmpsmallset;override;
  47. procedure second_cmp64bit;override;
  48. procedure second_cmpordinal;override;
  49. end;
  50. implementation
  51. uses
  52. globtype,globals,
  53. verbose,
  54. cutils,
  55. aasmbase,aasmtai,aasmcpu,
  56. symconst,symdef,
  57. cgobj,cgx86,cga,
  58. paramgr,
  59. htypechk,
  60. pass_2,ncgutil,
  61. ncon,nset,
  62. defutil;
  63. {*****************************************************************************
  64. Helpers
  65. *****************************************************************************}
  66. procedure tx86addnode.emit_generic_code(op:TAsmOp;opsize:TCGSize;unsigned,extra_not,mboverflow:boolean);
  67. var
  68. power : longint;
  69. hl4 : tasmlabel;
  70. r : Tregister;
  71. begin
  72. { at this point, left.location.loc should be LOC_REGISTER }
  73. if right.location.loc=LOC_REGISTER then
  74. begin
  75. { right.location is a LOC_REGISTER }
  76. { when swapped another result register }
  77. if (nodetype=subn) and (nf_swaped in flags) then
  78. begin
  79. if extra_not then
  80. emit_reg(A_NOT,TCGSize2Opsize[opsize],left.location.register);
  81. emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,right.location.register);
  82. { newly swapped also set swapped flag }
  83. location_swap(left.location,right.location);
  84. toggleflag(nf_swaped);
  85. end
  86. else
  87. begin
  88. if extra_not then
  89. emit_reg(A_NOT,TCGSize2Opsize[opsize],right.location.register);
  90. if (op=A_ADD) or (op=A_OR) or (op=A_AND) or (op=A_XOR) or (op=A_IMUL) then
  91. location_swap(left.location,right.location);
  92. emit_reg_reg(op,TCGSize2Opsize[opsize],right.location.register,left.location.register);
  93. end;
  94. end
  95. else
  96. begin
  97. { right.location is not a LOC_REGISTER }
  98. if (nodetype=subn) and (nf_swaped in flags) then
  99. begin
  100. if extra_not then
  101. emit_reg(A_NOT,TCGSize2Opsize[opsize],left.location.register);
  102. r:=cg.getintregister(exprasmlist,OS_INT);
  103. cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,r);
  104. emit_reg_reg(op,TCGSize2Opsize[opsize],left.location.register,r);
  105. emit_reg_reg(A_MOV,TCGSize2Opsize[opsize],r,left.location.register);
  106. cg.ungetregister(exprasmlist,r);
  107. end
  108. else
  109. begin
  110. { Optimizations when right.location is a constant value }
  111. if (op=A_CMP) and
  112. (nodetype in [equaln,unequaln]) and
  113. (right.location.loc=LOC_CONSTANT) and
  114. (right.location.value=0) then
  115. begin
  116. emit_reg_reg(A_TEST,TCGSize2Opsize[opsize],left.location.register,left.location.register);
  117. end
  118. else
  119. if (op=A_ADD) and
  120. (right.location.loc=LOC_CONSTANT) and
  121. (right.location.value=1) and
  122. not(cs_check_overflow in aktlocalswitches) then
  123. begin
  124. emit_reg(A_INC,TCGSize2Opsize[opsize],left.location.register);
  125. end
  126. else
  127. if (op=A_SUB) and
  128. (right.location.loc=LOC_CONSTANT) and
  129. (right.location.value=1) and
  130. not(cs_check_overflow in aktlocalswitches) then
  131. begin
  132. emit_reg(A_DEC,TCGSize2Opsize[opsize],left.location.register);
  133. end
  134. else
  135. if (op=A_IMUL) and
  136. (right.location.loc=LOC_CONSTANT) and
  137. (ispowerof2(right.location.value,power)) and
  138. not(cs_check_overflow in aktlocalswitches) then
  139. begin
  140. emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
  141. end
  142. else
  143. begin
  144. if extra_not then
  145. begin
  146. r:=cg.getintregister(exprasmlist,OS_INT);
  147. cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,r);
  148. emit_reg(A_NOT,TCGSize2Opsize[opsize],r);
  149. emit_reg_reg(A_AND,TCGSize2Opsize[opsize],r,left.location.register);
  150. cg.ungetregister(exprasmlist,r);
  151. end
  152. else
  153. begin
  154. emit_op_right_left(op,TCGSize2Opsize[opsize]);
  155. end;
  156. end;
  157. end;
  158. end;
  159. { only in case of overflow operations }
  160. { produce overflow code }
  161. { we must put it here directly, because sign of operation }
  162. { is in unsigned VAR!! }
  163. if mboverflow then
  164. begin
  165. if cs_check_overflow in aktlocalswitches then
  166. begin
  167. objectlibrary.getlabel(hl4);
  168. if unsigned then
  169. cg.a_jmp_flags(exprasmlist,F_AE,hl4)
  170. else
  171. cg.a_jmp_flags(exprasmlist,F_NO,hl4);
  172. cg.a_call_name(exprasmlist,'FPC_OVERFLOW');
  173. cg.a_label(exprasmlist,hl4);
  174. end;
  175. end;
  176. end;
  177. procedure tx86addnode.left_must_be_reg(opsize:TCGSize;noswap:boolean);
  178. begin
  179. { left location is not a register? }
  180. if (left.location.loc<>LOC_REGISTER) then
  181. begin
  182. { if right is register then we can swap the locations }
  183. if (not noswap) and
  184. (right.location.loc=LOC_REGISTER) then
  185. begin
  186. location_swap(left.location,right.location);
  187. toggleflag(nf_swaped);
  188. end
  189. else
  190. begin
  191. { maybe we can reuse a constant register when the
  192. operation is a comparison that doesn't change the
  193. value of the register }
  194. location_force_reg(exprasmlist,left.location,opsize,(nodetype in [ltn,lten,gtn,gten,equaln,unequaln]));
  195. end;
  196. end;
  197. end;
  198. procedure tx86addnode.left_and_right_must_be_fpureg;
  199. begin
  200. if (right.location.loc<>LOC_FPUREGISTER) then
  201. begin
  202. cg.a_loadfpu_loc_reg(exprasmlist,right.location,NR_ST);
  203. if (right.location.loc <> LOC_CFPUREGISTER) then
  204. location_freetemp(exprasmlist,left.location);
  205. if (left.location.loc<>LOC_FPUREGISTER) then
  206. begin
  207. cg.a_loadfpu_loc_reg(exprasmlist,left.location,NR_ST);
  208. if (left.location.loc <> LOC_CFPUREGISTER) then
  209. location_freetemp(exprasmlist,left.location);
  210. end
  211. else
  212. begin
  213. { left was on the stack => swap }
  214. toggleflag(nf_swaped);
  215. end;
  216. { releases the right reference }
  217. location_release(exprasmlist,right.location);
  218. end
  219. { the nominator in st0 }
  220. else if (left.location.loc<>LOC_FPUREGISTER) then
  221. begin
  222. cg.a_loadfpu_loc_reg(exprasmlist,left.location,NR_ST);
  223. if (left.location.loc <> LOC_CFPUREGISTER) then
  224. location_freetemp(exprasmlist,left.location);
  225. end
  226. else
  227. begin
  228. { fpu operands are always in the wrong order on the stack }
  229. toggleflag(nf_swaped);
  230. end;
  231. end;
  232. procedure tx86addnode.emit_op_right_left(op:TAsmOp;opsize:TOpsize);
  233. begin
  234. { left must be a register }
  235. case right.location.loc of
  236. LOC_REGISTER,
  237. LOC_CREGISTER :
  238. exprasmlist.concat(taicpu.op_reg_reg(op,opsize,right.location.register,left.location.register));
  239. LOC_REFERENCE,
  240. LOC_CREFERENCE :
  241. exprasmlist.concat(taicpu.op_ref_reg(op,opsize,right.location.reference,left.location.register));
  242. LOC_CONSTANT :
  243. exprasmlist.concat(taicpu.op_const_reg(op,opsize,right.location.value,left.location.register));
  244. else
  245. internalerror(200203232);
  246. end;
  247. end;
  248. function tx86addnode.getresflags(unsigned : boolean) : tresflags;
  249. begin
  250. case nodetype of
  251. equaln : getresflags:=F_E;
  252. unequaln : getresflags:=F_NE;
  253. else
  254. if not(unsigned) then
  255. begin
  256. if nf_swaped in flags then
  257. case nodetype of
  258. ltn : getresflags:=F_G;
  259. lten : getresflags:=F_GE;
  260. gtn : getresflags:=F_L;
  261. gten : getresflags:=F_LE;
  262. end
  263. else
  264. case nodetype of
  265. ltn : getresflags:=F_L;
  266. lten : getresflags:=F_LE;
  267. gtn : getresflags:=F_G;
  268. gten : getresflags:=F_GE;
  269. end;
  270. end
  271. else
  272. begin
  273. if nf_swaped in flags then
  274. case nodetype of
  275. ltn : getresflags:=F_A;
  276. lten : getresflags:=F_AE;
  277. gtn : getresflags:=F_B;
  278. gten : getresflags:=F_BE;
  279. end
  280. else
  281. case nodetype of
  282. ltn : getresflags:=F_B;
  283. lten : getresflags:=F_BE;
  284. gtn : getresflags:=F_A;
  285. gten : getresflags:=F_AE;
  286. end;
  287. end;
  288. end;
  289. end;
  290. {*****************************************************************************
  291. AddSmallSet
  292. *****************************************************************************}
  293. procedure tx86addnode.second_addsmallset;
  294. var
  295. opsize : TCGSize;
  296. op : TAsmOp;
  297. extra_not,
  298. noswap : boolean;
  299. begin
  300. pass_left_right;
  301. noswap:=false;
  302. extra_not:=false;
  303. opsize:=OS_32;
  304. case nodetype of
  305. addn :
  306. begin
  307. { this is a really ugly hack!!!!!!!!!! }
  308. { this could be done later using EDI }
  309. { as it is done for subn }
  310. { instead of two registers!!!! }
  311. { adding elements is not commutative }
  312. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  313. swapleftright;
  314. { are we adding set elements ? }
  315. if right.nodetype=setelementn then
  316. begin
  317. { no range support for smallsets! }
  318. if assigned(tsetelementnode(right).right) then
  319. internalerror(43244);
  320. { bts requires both elements to be registers }
  321. location_force_reg(exprasmlist,left.location,opsize,false);
  322. location_force_reg(exprasmlist,right.location,opsize,true);
  323. op:=A_BTS;
  324. noswap:=true;
  325. end
  326. else
  327. op:=A_OR;
  328. end;
  329. symdifn :
  330. op:=A_XOR;
  331. muln :
  332. op:=A_AND;
  333. subn :
  334. begin
  335. op:=A_AND;
  336. if (not(nf_swaped in flags)) and
  337. (right.location.loc=LOC_CONSTANT) then
  338. right.location.value := not(right.location.value)
  339. else if (nf_swaped in flags) and
  340. (left.location.loc=LOC_CONSTANT) then
  341. left.location.value := not(left.location.value)
  342. else
  343. extra_not:=true;
  344. end;
  345. xorn :
  346. op:=A_XOR;
  347. orn :
  348. op:=A_OR;
  349. andn :
  350. op:=A_AND;
  351. else
  352. internalerror(2003042215);
  353. end;
  354. { left must be a register }
  355. left_must_be_reg(opsize,noswap);
  356. emit_generic_code(op,opsize,true,extra_not,false);
  357. location_freetemp(exprasmlist,right.location);
  358. location_release(exprasmlist,right.location);
  359. set_result_location_reg;
  360. end;
  361. procedure tx86addnode.second_cmpsmallset;
  362. var
  363. opsize : TCGSize;
  364. op : TAsmOp;
  365. begin
  366. pass_left_right;
  367. opsize:=OS_32;
  368. case nodetype of
  369. equaln,
  370. unequaln :
  371. op:=A_CMP;
  372. lten,gten:
  373. begin
  374. if (not(nf_swaped in flags) and (nodetype = lten)) or
  375. ((nf_swaped in flags) and (nodetype = gten)) then
  376. swapleftright;
  377. location_force_reg(exprasmlist,left.location,opsize,true);
  378. emit_op_right_left(A_AND,TCGSize2Opsize[opsize]);
  379. op:=A_CMP;
  380. { warning: ugly hack, we need a JE so change the node to equaln }
  381. nodetype:=equaln;
  382. end;
  383. else
  384. internalerror(2003042215);
  385. end;
  386. { left must be a register }
  387. left_must_be_reg(opsize,false);
  388. emit_generic_code(op,opsize,true,false,false);
  389. location_freetemp(exprasmlist,right.location);
  390. location_release(exprasmlist,right.location);
  391. location_freetemp(exprasmlist,left.location);
  392. location_release(exprasmlist,left.location);
  393. location_reset(location,LOC_FLAGS,OS_NO);
  394. location.resflags:=getresflags(true);
  395. end;
  396. {*****************************************************************************
  397. AddFloat
  398. *****************************************************************************}
  399. procedure tx86addnode.second_addfloatsse;
  400. var
  401. op : topcg;
  402. begin
  403. pass_left_right;
  404. if (nf_swaped in flags) then
  405. swapleftright;
  406. case nodetype of
  407. addn :
  408. op:=OP_ADD;
  409. muln :
  410. op:=OP_MUL;
  411. subn :
  412. op:=OP_SUB;
  413. slashn :
  414. op:=OP_DIV;
  415. else
  416. internalerror(200312231);
  417. end;
  418. location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
  419. { we can use only right as left operand if the operation is commutative }
  420. if (right.location.loc=LOC_MMREGISTER) and (op in [OP_ADD,OP_MUL]) then
  421. begin
  422. location.register:=right.location.register;
  423. { force floating point reg. location to be written to memory,
  424. we don't force it to mm register because writing to memory
  425. allows probably shorter code because there is no direct fpu->mm register
  426. copy instruction
  427. }
  428. if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  429. location_force_mem(exprasmlist,left.location);
  430. cg.a_opmm_loc_reg(exprasmlist,op,location.size,left.location,location.register,mms_movescalar);
  431. location_release(exprasmlist,left.location);
  432. end
  433. else
  434. begin
  435. location_force_mmregscalar(exprasmlist,left.location,false);
  436. location.register:=left.location.register;
  437. { force floating point reg. location to be written to memory,
  438. we don't force it to mm register because writing to memory
  439. allows probably shorter code because there is no direct fpu->mm register
  440. copy instruction
  441. }
  442. if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  443. location_force_mem(exprasmlist,right.location);
  444. cg.a_opmm_loc_reg(exprasmlist,op,location.size,right.location,location.register,mms_movescalar);
  445. location_release(exprasmlist,right.location);
  446. end;
  447. end;
  448. procedure tx86addnode.second_addfloat;
  449. var
  450. op : TAsmOp;
  451. begin
  452. if use_sse(resulttype.def) then
  453. begin
  454. second_addfloatsse;
  455. exit;
  456. end;
  457. pass_left_right;
  458. case nodetype of
  459. addn :
  460. op:=A_FADDP;
  461. muln :
  462. op:=A_FMULP;
  463. subn :
  464. op:=A_FSUBP;
  465. slashn :
  466. op:=A_FDIVP;
  467. else
  468. internalerror(2003042214);
  469. end;
  470. left_and_right_must_be_fpureg;
  471. { releases the left reference }
  472. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  473. location_release(exprasmlist,left.location);
  474. { if we swaped the tree nodes, then use the reverse operator }
  475. if nf_swaped in flags then
  476. begin
  477. if (nodetype=slashn) then
  478. op:=A_FDIVRP
  479. else if (nodetype=subn) then
  480. op:=A_FSUBRP;
  481. end;
  482. emit_reg_reg(op,S_NO,NR_ST,NR_ST1);
  483. tcgx86(cg).dec_fpu_stack;
  484. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  485. location.register:=NR_ST;
  486. end;
  487. procedure tx86addnode.second_cmpfloat;
  488. var
  489. resflags : tresflags;
  490. begin
  491. if use_sse(resulttype.def) then
  492. begin
  493. second_addfloatsse;
  494. exit;
  495. end;
  496. pass_left_right;
  497. left_and_right_must_be_fpureg;
  498. { releases the left reference }
  499. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  500. location_release(exprasmlist,left.location);
  501. emit_none(A_FCOMPP,S_NO);
  502. tcgx86(cg).dec_fpu_stack;
  503. tcgx86(cg).dec_fpu_stack;
  504. { load fpu flags }
  505. cg.getexplicitregister(exprasmlist,NR_AX);
  506. emit_reg(A_FNSTSW,S_NO,NR_AX);
  507. emit_none(A_SAHF,S_NO);
  508. cg.ungetregister(exprasmlist,NR_AX);
  509. if nf_swaped in flags then
  510. begin
  511. case nodetype of
  512. equaln : resflags:=F_E;
  513. unequaln : resflags:=F_NE;
  514. ltn : resflags:=F_A;
  515. lten : resflags:=F_AE;
  516. gtn : resflags:=F_B;
  517. gten : resflags:=F_BE;
  518. end;
  519. end
  520. else
  521. begin
  522. case nodetype of
  523. equaln : resflags:=F_E;
  524. unequaln : resflags:=F_NE;
  525. ltn : resflags:=F_B;
  526. lten : resflags:=F_BE;
  527. gtn : resflags:=F_A;
  528. gten : resflags:=F_AE;
  529. end;
  530. end;
  531. location_reset(location,LOC_FLAGS,OS_NO);
  532. location.resflags:=resflags;
  533. end;
  534. {*****************************************************************************
  535. Addstring
  536. *****************************************************************************}
  537. { note: if you implemented an fpc_shortstr_concat similar to the }
  538. { one in i386.inc, you have to override first_addstring like in }
  539. { ti386addnode.first_string and implement the shortstring concat }
  540. { manually! The generic routine is different from the i386 one (JM) }
  541. function tx86addnode.first_addstring : tnode;
  542. begin
  543. { special cases for shortstrings, handled in pass_2 (JM) }
  544. { can't handle fpc_shortstr_compare with compilerproc either because it }
  545. { returns its results in the flags instead of in eax }
  546. if (nodetype in [ltn,lten,gtn,gten,equaln,unequaln]) and
  547. is_shortstring(left.resulttype.def) and
  548. not(((left.nodetype=stringconstn) and (str_length(left)=0)) or
  549. ((right.nodetype=stringconstn) and (str_length(right)=0))) then
  550. begin
  551. expectloc:=LOC_FLAGS;
  552. calcregisters(self,0,0,0);
  553. result := nil;
  554. exit;
  555. end;
  556. { otherwise, use the generic code }
  557. result := inherited first_addstring;
  558. end;
  559. procedure tx86addnode.second_addstring;
  560. var
  561. paraloc1,
  562. paraloc2 : tparalocation;
  563. hregister1,
  564. hregister2 : tregister;
  565. begin
  566. { string operations are not commutative }
  567. if nf_swaped in flags then
  568. swapleftright;
  569. case tstringdef(left.resulttype.def).string_typ of
  570. st_shortstring:
  571. begin
  572. case nodetype of
  573. ltn,lten,gtn,gten,equaln,unequaln :
  574. begin
  575. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  576. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  577. { process parameters }
  578. secondpass(left);
  579. location_release(exprasmlist,left.location);
  580. if paraloc2.loc=LOC_REGISTER then
  581. begin
  582. hregister2:=cg.getaddressregister(exprasmlist);
  583. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister2);
  584. end
  585. else
  586. begin
  587. paramanager.allocparaloc(exprasmlist,paraloc2);
  588. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paraloc2);
  589. end;
  590. secondpass(right);
  591. location_release(exprasmlist,right.location);
  592. if paraloc1.loc=LOC_REGISTER then
  593. begin
  594. hregister1:=cg.getaddressregister(exprasmlist);
  595. cg.a_loadaddr_ref_reg(exprasmlist,right.location.reference,hregister1);
  596. end
  597. else
  598. begin
  599. paramanager.allocparaloc(exprasmlist,paraloc1);
  600. cg.a_paramaddr_ref(exprasmlist,right.location.reference,paraloc1);
  601. end;
  602. { push parameters }
  603. if paraloc1.loc=LOC_REGISTER then
  604. begin
  605. cg.ungetregister(exprasmlist,hregister2);
  606. paramanager.allocparaloc(exprasmlist,paraloc2);
  607. cg.a_param_reg(exprasmlist,OS_ADDR,hregister2,paraloc2);
  608. end;
  609. if paraloc2.loc=LOC_REGISTER then
  610. begin
  611. cg.ungetregister(exprasmlist,hregister1);
  612. paramanager.allocparaloc(exprasmlist,paraloc1);
  613. cg.a_param_reg(exprasmlist,OS_ADDR,hregister1,paraloc1);
  614. end;
  615. paramanager.freeparaloc(exprasmlist,paraloc1);
  616. paramanager.freeparaloc(exprasmlist,paraloc2);
  617. cg.allocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  618. cg.a_call_name(exprasmlist,'FPC_SHORTSTR_COMPARE');
  619. cg.deallocexplicitregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  620. location_freetemp(exprasmlist,left.location);
  621. location_freetemp(exprasmlist,right.location);
  622. end;
  623. end;
  624. location_reset(location,LOC_FLAGS,OS_NO);
  625. location.resflags:=getresflags(true);
  626. end;
  627. else
  628. { rest should be handled in first pass (JM) }
  629. internalerror(200108303);
  630. end;
  631. end;
  632. {*****************************************************************************
  633. Add64bit
  634. *****************************************************************************}
  635. procedure tx86addnode.second_add64bit;
  636. begin
  637. {$ifdef cpu64bit}
  638. second_addordinal;
  639. {$else cpu64bit}
  640. { must be implemented separate }
  641. internalerror(200402042);
  642. {$endif cpu64bit}
  643. end;
  644. procedure tx86addnode.second_cmp64bit;
  645. begin
  646. {$ifdef cpu64bit}
  647. second_cmpordinal;
  648. {$else cpu64bit}
  649. { must be implemented separate }
  650. internalerror(200402043);
  651. {$endif cpu64bit}
  652. end;
  653. {*****************************************************************************
  654. AddOrdinal
  655. *****************************************************************************}
  656. procedure tx86addnode.second_addordinal;
  657. var
  658. mboverflow : boolean;
  659. op : tasmop;
  660. opsize : tcgsize;
  661. { true, if unsigned types are compared }
  662. unsigned : boolean;
  663. { true, if for sets subtractions the extra not should generated }
  664. extra_not : boolean;
  665. begin
  666. { defaults }
  667. extra_not:=false;
  668. mboverflow:=false;
  669. unsigned:=not(is_signed(left.resulttype.def)) or
  670. not(is_signed(right.resulttype.def));
  671. opsize:=def_cgsize(left.resulttype.def);
  672. pass_left_right;
  673. case nodetype of
  674. addn :
  675. begin
  676. op:=A_ADD;
  677. mboverflow:=true;
  678. end;
  679. muln :
  680. begin
  681. if unsigned then
  682. op:=A_MUL
  683. else
  684. op:=A_IMUL;
  685. mboverflow:=true;
  686. end;
  687. subn :
  688. begin
  689. op:=A_SUB;
  690. mboverflow:=true;
  691. end;
  692. xorn :
  693. op:=A_XOR;
  694. orn :
  695. op:=A_OR;
  696. andn :
  697. op:=A_AND;
  698. else
  699. internalerror(200304229);
  700. end;
  701. { filter MUL, which requires special handling }
  702. if op=A_MUL then
  703. begin
  704. second_mul;
  705. exit;
  706. end;
  707. left_must_be_reg(opsize,false);
  708. emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
  709. location_freetemp(exprasmlist,right.location);
  710. location_release(exprasmlist,right.location);
  711. set_result_location_reg;
  712. end;
  713. procedure tx86addnode.second_cmpordinal;
  714. var
  715. opsize : tcgsize;
  716. unsigned : boolean;
  717. begin
  718. unsigned:=not(is_signed(left.resulttype.def)) or
  719. not(is_signed(right.resulttype.def));
  720. opsize:=def_cgsize(left.resulttype.def);
  721. pass_left_right;
  722. left_must_be_reg(opsize,false);
  723. emit_generic_code(A_CMP,opsize,unsigned,false,false);
  724. location_freetemp(exprasmlist,right.location);
  725. location_release(exprasmlist,right.location);
  726. if (left.location.loc<>LOC_CREGISTER) then
  727. begin
  728. location_freetemp(exprasmlist,left.location);
  729. location_release(exprasmlist,left.location);
  730. end;
  731. location_reset(location,LOC_FLAGS,OS_NO);
  732. location.resflags:=getresflags(unsigned);
  733. end;
  734. begin
  735. caddnode:=tx86addnode;
  736. end.
  737. {
  738. $Log$
  739. Revision 1.7 2004-02-04 19:22:27 peter
  740. *** empty log message ***
  741. Revision 1.6 2004/01/20 12:59:37 florian
  742. * common addnode code for x86-64 and i386
  743. Revision 1.5 2003/12/26 13:19:16 florian
  744. * rtl and compiler compile with -Cfsse2
  745. Revision 1.4 2003/12/26 00:32:22 florian
  746. + fpu<->mm register conversion
  747. Revision 1.3 2003/12/25 01:07:09 florian
  748. + $fputype directive support
  749. + single data type operations with sse unit
  750. * fixed more x86-64 stuff
  751. Revision 1.2 2003/12/23 14:38:07 florian
  752. + second_floataddsse implemented
  753. Revision 1.1 2003/10/13 01:58:04 florian
  754. * some ideas for mm support implemented
  755. }