nx86add.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  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. exprasmlist.concat(taicpu.op_ref_reg(op,TCGSize2Opsize[opsize],right.location.reference,left.location.register));
  236. LOC_CONSTANT :
  237. begin
  238. {$ifdef x86_64}
  239. { x86_64 only supports signed 32 bits constants directly }
  240. if (opsize in [OS_S64,OS_64]) and
  241. ((right.location.value<low(longint)) or (right.location.value>high(longint))) then
  242. begin
  243. tmpreg:=cg.getintregister(exprasmlist,opsize);
  244. cg.a_load_const_reg(exprasmlist,opsize,right.location.value,tmpreg);
  245. exprasmlist.concat(taicpu.op_reg_reg(op,TCGSize2Opsize[opsize],tmpreg,left.location.register));
  246. end
  247. else
  248. {$endif x86_64}
  249. exprasmlist.concat(taicpu.op_const_reg(op,TCGSize2Opsize[opsize],right.location.value,left.location.register));
  250. end;
  251. else
  252. internalerror(200203232);
  253. end;
  254. end;
  255. function tx86addnode.getresflags(unsigned : boolean) : tresflags;
  256. begin
  257. case nodetype of
  258. equaln : getresflags:=F_E;
  259. unequaln : getresflags:=F_NE;
  260. else
  261. if not(unsigned) then
  262. begin
  263. if nf_swaped in flags then
  264. case nodetype of
  265. ltn : getresflags:=F_G;
  266. lten : getresflags:=F_GE;
  267. gtn : getresflags:=F_L;
  268. gten : getresflags:=F_LE;
  269. end
  270. else
  271. case nodetype of
  272. ltn : getresflags:=F_L;
  273. lten : getresflags:=F_LE;
  274. gtn : getresflags:=F_G;
  275. gten : getresflags:=F_GE;
  276. end;
  277. end
  278. else
  279. begin
  280. if nf_swaped in flags then
  281. case nodetype of
  282. ltn : getresflags:=F_A;
  283. lten : getresflags:=F_AE;
  284. gtn : getresflags:=F_B;
  285. gten : getresflags:=F_BE;
  286. end
  287. else
  288. case nodetype of
  289. ltn : getresflags:=F_B;
  290. lten : getresflags:=F_BE;
  291. gtn : getresflags:=F_A;
  292. gten : getresflags:=F_AE;
  293. end;
  294. end;
  295. end;
  296. end;
  297. {*****************************************************************************
  298. AddSmallSet
  299. *****************************************************************************}
  300. procedure tx86addnode.second_addsmallset;
  301. var
  302. opsize : TCGSize;
  303. op : TAsmOp;
  304. extra_not,
  305. noswap : boolean;
  306. begin
  307. pass_left_right;
  308. noswap:=false;
  309. extra_not:=false;
  310. opsize:=OS_32;
  311. case nodetype of
  312. addn :
  313. begin
  314. { this is a really ugly hack!!!!!!!!!! }
  315. { this could be done later using EDI }
  316. { as it is done for subn }
  317. { instead of two registers!!!! }
  318. { adding elements is not commutative }
  319. if (nf_swaped in flags) and (left.nodetype=setelementn) then
  320. swapleftright;
  321. { are we adding set elements ? }
  322. if right.nodetype=setelementn then
  323. begin
  324. { no range support for smallsets! }
  325. if assigned(tsetelementnode(right).right) then
  326. internalerror(43244);
  327. { bts requires both elements to be registers }
  328. location_force_reg(exprasmlist,left.location,opsize,false);
  329. location_force_reg(exprasmlist,right.location,opsize,true);
  330. op:=A_BTS;
  331. noswap:=true;
  332. end
  333. else
  334. op:=A_OR;
  335. end;
  336. symdifn :
  337. op:=A_XOR;
  338. muln :
  339. op:=A_AND;
  340. subn :
  341. begin
  342. op:=A_AND;
  343. if (not(nf_swaped in flags)) and
  344. (right.location.loc=LOC_CONSTANT) then
  345. right.location.value := not(right.location.value)
  346. else if (nf_swaped in flags) and
  347. (left.location.loc=LOC_CONSTANT) then
  348. left.location.value := not(left.location.value)
  349. else
  350. extra_not:=true;
  351. end;
  352. xorn :
  353. op:=A_XOR;
  354. orn :
  355. op:=A_OR;
  356. andn :
  357. op:=A_AND;
  358. else
  359. internalerror(2003042215);
  360. end;
  361. { left must be a register }
  362. left_must_be_reg(opsize,noswap);
  363. emit_generic_code(op,opsize,true,extra_not,false);
  364. location_freetemp(exprasmlist,right.location);
  365. set_result_location_reg;
  366. end;
  367. procedure tx86addnode.second_cmpsmallset;
  368. var
  369. opsize : TCGSize;
  370. op : TAsmOp;
  371. begin
  372. pass_left_right;
  373. opsize:=OS_32;
  374. case nodetype of
  375. equaln,
  376. unequaln :
  377. op:=A_CMP;
  378. lten,gten:
  379. begin
  380. if (not(nf_swaped in flags) and (nodetype = lten)) or
  381. ((nf_swaped in flags) and (nodetype = gten)) then
  382. swapleftright;
  383. location_force_reg(exprasmlist,left.location,opsize,true);
  384. emit_op_right_left(A_AND,opsize);
  385. op:=A_CMP;
  386. { warning: ugly hack, we need a JE so change the node to equaln }
  387. nodetype:=equaln;
  388. end;
  389. else
  390. internalerror(2003042215);
  391. end;
  392. { left must be a register }
  393. left_must_be_reg(opsize,false);
  394. emit_generic_code(op,opsize,true,false,false);
  395. location_freetemp(exprasmlist,right.location);
  396. location_freetemp(exprasmlist,left.location);
  397. location_reset(location,LOC_FLAGS,OS_NO);
  398. location.resflags:=getresflags(true);
  399. end;
  400. {*****************************************************************************
  401. AddFloat
  402. *****************************************************************************}
  403. procedure tx86addnode.second_addfloatsse;
  404. var
  405. op : topcg;
  406. begin
  407. pass_left_right;
  408. if (nf_swaped in flags) then
  409. swapleftright;
  410. case nodetype of
  411. addn :
  412. op:=OP_ADD;
  413. muln :
  414. op:=OP_MUL;
  415. subn :
  416. op:=OP_SUB;
  417. slashn :
  418. op:=OP_DIV;
  419. else
  420. internalerror(200312231);
  421. end;
  422. location_reset(location,LOC_MMREGISTER,def_cgsize(resulttype.def));
  423. { we can use only right as left operand if the operation is commutative }
  424. if (right.location.loc=LOC_MMREGISTER) and (op in [OP_ADD,OP_MUL]) then
  425. begin
  426. location.register:=right.location.register;
  427. { force floating point reg. location to be written to memory,
  428. we don't force it to mm register because writing to memory
  429. allows probably shorter code because there is no direct fpu->mm register
  430. copy instruction
  431. }
  432. if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  433. location_force_mem(exprasmlist,left.location);
  434. cg.a_opmm_loc_reg(exprasmlist,op,location.size,left.location,location.register,mms_movescalar);
  435. end
  436. else
  437. begin
  438. location_force_mmregscalar(exprasmlist,left.location,false);
  439. location.register:=left.location.register;
  440. { force floating point reg. location to be written to memory,
  441. we don't force it to mm register because writing to memory
  442. allows probably shorter code because there is no direct fpu->mm register
  443. copy instruction
  444. }
  445. if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  446. location_force_mem(exprasmlist,right.location);
  447. cg.a_opmm_loc_reg(exprasmlist,op,location.size,right.location,location.register,mms_movescalar);
  448. end;
  449. end;
  450. procedure tx86addnode.second_cmpfloatsse;
  451. var
  452. op : tasmop;
  453. begin
  454. if is_single(left.resulttype.def) then
  455. op:=A_COMISS
  456. else if is_double(left.resulttype.def) then
  457. op:=A_COMISD
  458. else
  459. internalerror(200402222);
  460. pass_left_right;
  461. location_reset(location,LOC_FLAGS,def_cgsize(resulttype.def));
  462. { we can use only right as left operand if the operation is commutative }
  463. if (right.location.loc=LOC_MMREGISTER) then
  464. begin
  465. { force floating point reg. location to be written to memory,
  466. we don't force it to mm register because writing to memory
  467. allows probably shorter code because there is no direct fpu->mm register
  468. copy instruction
  469. }
  470. if left.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  471. location_force_mem(exprasmlist,left.location);
  472. case left.location.loc of
  473. LOC_REFERENCE,LOC_CREFERENCE:
  474. exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,left.location.reference,right.location.register));
  475. LOC_MMREGISTER,LOC_CMMREGISTER:
  476. exprasmlist.concat(taicpu.op_reg_reg(op,S_NO,left.location.register,right.location.register));
  477. else
  478. internalerror(200402221);
  479. end;
  480. if nf_swaped in flags then
  481. exclude(flags,nf_swaped)
  482. else
  483. include(flags,nf_swaped)
  484. end
  485. else
  486. begin
  487. location_force_mmregscalar(exprasmlist,left.location,false);
  488. { force floating point reg. location to be written to memory,
  489. we don't force it to mm register because writing to memory
  490. allows probably shorter code because there is no direct fpu->mm register
  491. copy instruction
  492. }
  493. if right.location.loc in [LOC_FPUREGISTER,LOC_CFPUREGISTER] then
  494. location_force_mem(exprasmlist,right.location);
  495. case right.location.loc of
  496. LOC_REFERENCE,LOC_CREFERENCE:
  497. exprasmlist.concat(taicpu.op_ref_reg(op,S_NO,right.location.reference,left.location.register));
  498. LOC_MMREGISTER,LOC_CMMREGISTER:
  499. exprasmlist.concat(taicpu.op_reg_reg(op,S_NO,right.location.register,left.location.register));
  500. else
  501. internalerror(200402223);
  502. end;
  503. end;
  504. location.resflags:=getresflags(true);
  505. end;
  506. procedure tx86addnode.second_addfloat;
  507. var
  508. op : TAsmOp;
  509. begin
  510. if use_sse(resulttype.def) then
  511. begin
  512. second_addfloatsse;
  513. exit;
  514. end;
  515. pass_left_right;
  516. case nodetype of
  517. addn :
  518. op:=A_FADDP;
  519. muln :
  520. op:=A_FMULP;
  521. subn :
  522. op:=A_FSUBP;
  523. slashn :
  524. op:=A_FDIVP;
  525. else
  526. internalerror(2003042214);
  527. end;
  528. left_and_right_must_be_fpureg;
  529. { if we swaped the tree nodes, then use the reverse operator }
  530. if nf_swaped in flags then
  531. begin
  532. if (nodetype=slashn) then
  533. op:=A_FDIVRP
  534. else if (nodetype=subn) then
  535. op:=A_FSUBRP;
  536. end;
  537. emit_reg_reg(op,S_NO,NR_ST,NR_ST1);
  538. tcgx86(cg).dec_fpu_stack;
  539. location_reset(location,LOC_FPUREGISTER,def_cgsize(resulttype.def));
  540. location.register:=NR_ST;
  541. end;
  542. procedure tx86addnode.second_cmpfloat;
  543. var
  544. resflags : tresflags;
  545. begin
  546. if use_sse(left.resulttype.def) or use_sse(right.resulttype.def) then
  547. begin
  548. second_cmpfloatsse;
  549. exit;
  550. end;
  551. pass_left_right;
  552. left_and_right_must_be_fpureg;
  553. {$ifndef x86_64}
  554. if aktspecificoptprocessor<ClassPentium2 then
  555. begin
  556. emit_none(A_FCOMPP,S_NO);
  557. tcgx86(cg).dec_fpu_stack;
  558. tcgx86(cg).dec_fpu_stack;
  559. { load fpu flags }
  560. cg.getcpuregister(exprasmlist,NR_AX);
  561. emit_reg(A_FNSTSW,S_NO,NR_AX);
  562. emit_none(A_SAHF,S_NO);
  563. cg.ungetcpuregister(exprasmlist,NR_AX);
  564. if nf_swaped in flags then
  565. begin
  566. case nodetype of
  567. equaln : resflags:=F_E;
  568. unequaln : resflags:=F_NE;
  569. ltn : resflags:=F_A;
  570. lten : resflags:=F_AE;
  571. gtn : resflags:=F_B;
  572. gten : resflags:=F_BE;
  573. end;
  574. end
  575. else
  576. begin
  577. case nodetype of
  578. equaln : resflags:=F_E;
  579. unequaln : resflags:=F_NE;
  580. ltn : resflags:=F_B;
  581. lten : resflags:=F_BE;
  582. gtn : resflags:=F_A;
  583. gten : resflags:=F_AE;
  584. end;
  585. end;
  586. end
  587. else
  588. {$endif x86_64}
  589. begin
  590. exprasmlist.concat(taicpu.op_reg_reg(A_FCOMIP,S_NO,NR_ST1,NR_ST0));
  591. { fcomip pops only one fpu register }
  592. exprasmlist.concat(taicpu.op_reg(A_FSTP,S_NO,NR_ST0));
  593. tcgx86(cg).dec_fpu_stack;
  594. tcgx86(cg).dec_fpu_stack;
  595. { load fpu flags }
  596. if nf_swaped in flags then
  597. begin
  598. case nodetype of
  599. equaln : resflags:=F_E;
  600. unequaln : resflags:=F_NE;
  601. ltn : resflags:=F_A;
  602. lten : resflags:=F_AE;
  603. gtn : resflags:=F_B;
  604. gten : resflags:=F_BE;
  605. end;
  606. end
  607. else
  608. begin
  609. case nodetype of
  610. equaln : resflags:=F_E;
  611. unequaln : resflags:=F_NE;
  612. ltn : resflags:=F_B;
  613. lten : resflags:=F_BE;
  614. gtn : resflags:=F_A;
  615. gten : resflags:=F_AE;
  616. end;
  617. end;
  618. end;
  619. location_reset(location,LOC_FLAGS,OS_NO);
  620. location.resflags:=resflags;
  621. end;
  622. {*****************************************************************************
  623. Add64bit
  624. *****************************************************************************}
  625. procedure tx86addnode.second_add64bit;
  626. begin
  627. {$ifdef cpu64bit}
  628. second_addordinal;
  629. {$else cpu64bit}
  630. { must be implemented separate }
  631. internalerror(200402042);
  632. {$endif cpu64bit}
  633. end;
  634. procedure tx86addnode.second_cmp64bit;
  635. begin
  636. {$ifdef cpu64bit}
  637. second_cmpordinal;
  638. {$else cpu64bit}
  639. { must be implemented separate }
  640. internalerror(200402043);
  641. {$endif cpu64bit}
  642. end;
  643. {*****************************************************************************
  644. AddOrdinal
  645. *****************************************************************************}
  646. procedure tx86addnode.second_addordinal;
  647. var
  648. mboverflow : boolean;
  649. op : tasmop;
  650. opsize : tcgsize;
  651. { true, if unsigned types are compared }
  652. unsigned : boolean;
  653. { true, if for sets subtractions the extra not should generated }
  654. extra_not : boolean;
  655. begin
  656. { defaults }
  657. extra_not:=false;
  658. mboverflow:=false;
  659. unsigned:=not(is_signed(left.resulttype.def)) or
  660. not(is_signed(right.resulttype.def));
  661. opsize:=def_cgsize(left.resulttype.def);
  662. pass_left_right;
  663. case nodetype of
  664. addn :
  665. begin
  666. op:=A_ADD;
  667. mboverflow:=true;
  668. end;
  669. muln :
  670. begin
  671. if unsigned then
  672. op:=A_MUL
  673. else
  674. op:=A_IMUL;
  675. mboverflow:=true;
  676. end;
  677. subn :
  678. begin
  679. op:=A_SUB;
  680. mboverflow:=true;
  681. end;
  682. xorn :
  683. op:=A_XOR;
  684. orn :
  685. op:=A_OR;
  686. andn :
  687. op:=A_AND;
  688. else
  689. internalerror(200304229);
  690. end;
  691. { filter MUL, which requires special handling }
  692. if op=A_MUL then
  693. begin
  694. second_mul;
  695. exit;
  696. end;
  697. left_must_be_reg(opsize,false);
  698. emit_generic_code(op,opsize,unsigned,extra_not,mboverflow);
  699. location_freetemp(exprasmlist,right.location);
  700. set_result_location_reg;
  701. end;
  702. procedure tx86addnode.second_cmpordinal;
  703. var
  704. opsize : tcgsize;
  705. unsigned : boolean;
  706. begin
  707. unsigned:=not(is_signed(left.resulttype.def)) or
  708. not(is_signed(right.resulttype.def));
  709. opsize:=def_cgsize(left.resulttype.def);
  710. pass_left_right;
  711. left_must_be_reg(opsize,false);
  712. emit_generic_code(A_CMP,opsize,unsigned,false,false);
  713. location_freetemp(exprasmlist,right.location);
  714. location_freetemp(exprasmlist,left.location);
  715. location_reset(location,LOC_FLAGS,OS_NO);
  716. location.resflags:=getresflags(unsigned);
  717. end;
  718. begin
  719. caddnode:=tx86addnode;
  720. end.
  721. {
  722. $Log$
  723. Revision 1.15 2004-11-01 12:43:29 peter
  724. * shortstr compare with empty string fixed
  725. * removed special i386 code
  726. Revision 1.14 2004/10/31 21:45:04 peter
  727. * generic tlocation
  728. * move tlocation to cgutils
  729. Revision 1.13 2004/09/25 14:23:55 peter
  730. * ungetregister is now only used for cpuregisters, renamed to
  731. ungetcpuregister
  732. * renamed (get|unget)explicitregister(s) to ..cpuregister
  733. * removed location-release/reference_release
  734. Revision 1.12 2004/09/21 17:25:13 peter
  735. * paraloc branch merged
  736. Revision 1.11.4.1 2004/08/31 20:43:06 peter
  737. * paraloc patch
  738. Revision 1.11 2004/06/20 08:55:32 florian
  739. * logs truncated
  740. Revision 1.10 2004/06/16 20:07:11 florian
  741. * dwarf branch merged
  742. Revision 1.9.2.4 2004/05/02 16:46:28 peter
  743. * disable i386 optimized shortstr_compare for x86_64
  744. Revision 1.9.2.3 2004/04/28 18:35:42 peter
  745. * cardinal fixes for x86-64
  746. Revision 1.9.2.2 2004/04/27 18:18:26 peter
  747. * aword -> aint
  748. Revision 1.9.2.1 2004/04/26 15:54:33 peter
  749. * small x86-64 fixes
  750. }