nx86add.pas 27 KB

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