/js/src/nanojit/Nativei386.h

http://github.com/zpao/v8monkey · C Header · 490 lines · 413 code · 30 blank · 47 comment · 10 complexity · 310baad48d435374c3b5d30c699cf5b8 MD5 · raw file

  1. /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
  2. /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
  3. /* ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is [Open Source Virtual Machine].
  17. *
  18. * The Initial Developer of the Original Code is
  19. * Adobe System Incorporated.
  20. * Portions created by the Initial Developer are Copyright (C) 2004-2007
  21. * the Initial Developer. All Rights Reserved.
  22. *
  23. * Contributor(s):
  24. * Adobe AS3 Team
  25. *
  26. * Alternatively, the contents of this file may be used under the terms of
  27. * either the GNU General Public License Version 2 or later (the "GPL"), or
  28. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29. * in which case the provisions of the GPL or the LGPL are applicable instead
  30. * of those above. If you wish to allow use of your version of this file only
  31. * under the terms of either the GPL or the LGPL, and not to allow others to
  32. * use your version of this file under the terms of the MPL, indicate your
  33. * decision by deleting the provisions above and replace them with the notice
  34. * and other provisions required by the GPL or the LGPL. If you do not delete
  35. * the provisions above, a recipient may use your version of this file under
  36. * the terms of any one of the MPL, the GPL or the LGPL.
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. #ifndef __nanojit_Nativei386__
  40. #define __nanojit_Nativei386__
  41. #include "NativeCommon.h"
  42. #ifdef PERFM
  43. #define DOPROF
  44. #include "../vprof/vprof.h"
  45. #define count_instr() _nvprof("x86",1)
  46. #define count_ret() _nvprof("x86-ret",1); count_instr();
  47. #define count_push() _nvprof("x86-push",1); count_instr();
  48. #define count_pop() _nvprof("x86-pop",1); count_instr();
  49. #define count_st() _nvprof("x86-st",1); count_instr();
  50. #define count_stq() _nvprof("x86-stq",1); count_instr();
  51. #define count_ld() _nvprof("x86-ld",1); count_instr();
  52. #define count_ldq() _nvprof("x86-ldq",1); count_instr();
  53. #define count_call() _nvprof("x86-call",1); count_instr();
  54. #define count_calli() _nvprof("x86-calli",1); count_instr();
  55. #define count_prolog() _nvprof("x86-prolog",1); count_instr();
  56. #define count_alu() _nvprof("x86-alu",1); count_instr();
  57. #define count_mov() _nvprof("x86-mov",1); count_instr();
  58. #define count_fpu() _nvprof("x86-fpu",1); count_instr();
  59. #define count_jmp() _nvprof("x86-jmp",1); count_instr();
  60. #define count_jcc() _nvprof("x86-jcc",1); count_instr();
  61. #define count_fpuld() _nvprof("x86-ldq",1); _nvprof("x86-fpu",1); count_instr()
  62. #define count_aluld() _nvprof("x86-ld",1); _nvprof("x86-alu",1); count_instr()
  63. #define count_alust() _nvprof("x86-ld",1); _nvprof("x86-alu",1); _nvprof("x86-st",1); count_instr()
  64. #define count_pushld() _nvprof("x86-ld",1); _nvprof("x86-push",1); count_instr()
  65. #define count_imt() _nvprof("x86-imt",1) count_instr()
  66. #else
  67. #define count_instr()
  68. #define count_ret()
  69. #define count_push()
  70. #define count_pop()
  71. #define count_st()
  72. #define count_stq()
  73. #define count_ld()
  74. #define count_ldq()
  75. #define count_call()
  76. #define count_calli()
  77. #define count_prolog()
  78. #define count_alu()
  79. #define count_mov()
  80. #define count_fpu()
  81. #define count_jmp()
  82. #define count_jcc()
  83. #define count_fpuld()
  84. #define count_aluld()
  85. #define count_alust()
  86. #define count_pushld()
  87. #define count_imt()
  88. #endif
  89. namespace nanojit
  90. {
  91. const int NJ_MAX_REGISTERS = 24; // gpregs, x87 regs, xmm regs
  92. #define NJ_MAX_STACK_ENTRY 4096
  93. #define NJ_MAX_PARAMETERS 1
  94. #define NJ_USES_IMMD_POOL 1
  95. #define NJ_JTBL_SUPPORTED 1
  96. #define NJ_EXPANDED_LOADSTORE_SUPPORTED 1
  97. #define NJ_F2I_SUPPORTED 1
  98. #define NJ_SOFTFLOAT_SUPPORTED 0
  99. #define NJ_DIVI_SUPPORTED 1
  100. // Preserve a 16-byte stack alignment, to support the use of
  101. // SSE instructions like MOVDQA (if not by Tamarin itself,
  102. // then by the C functions it calls).
  103. const int NJ_ALIGN_STACK = 16;
  104. const int32_t LARGEST_UNDERRUN_PROT = 32; // largest value passed to underrunProtect
  105. typedef uint8_t NIns;
  106. // Bytes of icache to flush after patch
  107. const size_t LARGEST_BRANCH_PATCH = 16 * sizeof(NIns);
  108. static const Register
  109. // General purpose 32 bit registers. The names are rEAX, rEBX, etc,
  110. // because EAX, EBX, et al clash with <sys/regset.h> on Solaris (sigh).
  111. // See bug 570726 for details.
  112. rEAX = { 0 }, // return value, scratch
  113. rECX = { 1 }, // this/arg0, scratch
  114. rEDX = { 2 }, // arg1, return-msw, scratch
  115. rEBX = { 3 },
  116. rESP = { 4 }, // stack pointer
  117. rEBP = { 5 }, // frame pointer
  118. rESI = { 6 },
  119. rEDI = { 7 },
  120. SP = rESP, // alias SP to ESP for convenience
  121. FP = rEBP, // alias FP to EBP for convenience
  122. // SSE regs come before X87 so we prefer them
  123. XMM0 = { 8 },
  124. XMM1 = { 9 },
  125. XMM2 = { 10 },
  126. XMM3 = { 11 },
  127. XMM4 = { 12 },
  128. XMM5 = { 13 },
  129. XMM6 = { 14 },
  130. XMM7 = { 15 },
  131. // X87 regs
  132. FST0 = { 16 },
  133. deprecated_UnknownReg = { 17 }, // XXX: remove eventually, see bug 538924
  134. UnspecifiedReg = { 17 };
  135. static const uint32_t FirstRegNum = 0;
  136. static const uint32_t LastRegNum = 16;
  137. typedef int RegisterMask;
  138. static const int NumSavedRegs = 3;
  139. static const RegisterMask SavedRegs = 1<<REGNUM(rEBX) | 1<<REGNUM(rEDI) | 1<<REGNUM(rESI);
  140. static const RegisterMask GpRegs = SavedRegs | 1<<REGNUM(rEAX) | 1<<REGNUM(rECX) |
  141. 1<<REGNUM(rEDX);
  142. static const RegisterMask XmmRegs = 1<<REGNUM(XMM0) | 1<<REGNUM(XMM1) | 1<<REGNUM(XMM2) |
  143. 1<<REGNUM(XMM3) | 1<<REGNUM(XMM4) | 1<<REGNUM(XMM5) |
  144. 1<<REGNUM(XMM6) | 1<<REGNUM(XMM7);
  145. static const RegisterMask x87Regs = 1<<REGNUM(FST0);
  146. static const RegisterMask FpRegs = x87Regs | XmmRegs;
  147. static const RegisterMask ScratchRegs = 1<<REGNUM(rEAX) | 1<<REGNUM(rECX) | 1<<REGNUM(rEDX) |
  148. FpRegs;
  149. static const RegisterMask AllowableByteRegs = 1<<REGNUM(rEAX) | 1<<REGNUM(rECX) |
  150. 1<<REGNUM(rEDX) | 1<<REGNUM(rEBX);
  151. static inline bool IsGpReg(Register r) {
  152. return ((1<<REGNUM(r)) & GpRegs) != 0;
  153. }
  154. static inline bool IsXmmReg(Register r) {
  155. return ((1<<REGNUM(r)) & XmmRegs) != 0;
  156. }
  157. verbose_only( extern const char* regNames[]; )
  158. #define DECLARE_PLATFORM_STATS()
  159. #define DECLARE_PLATFORM_REGALLOC()
  160. #define JCC32 0x0f
  161. #define JMP8 0xeb
  162. #define JMP32 0xe9
  163. #define DECLARE_PLATFORM_ASSEMBLER() \
  164. const static Register argRegs[2], retRegs[2]; \
  165. int32_t max_stk_args;\
  166. debug_only( int32_t _fpuStkDepth; ) \
  167. debug_only( int32_t _sv_fpuStkDepth; ) \
  168. void nativePageReset();\
  169. void nativePageSetup();\
  170. void underrunProtect(int);\
  171. bool hardenNopInsertion(const Config& c) { return c.harden_nop_insertion; } \
  172. void asm_immi(Register r, int32_t val, bool canClobberCCs);\
  173. void asm_stkarg(LIns* p, int32_t& stkd);\
  174. void asm_farg(LIns*, int32_t& stkd);\
  175. void asm_arg(ArgType ty, LIns* p, Register r, int32_t& stkd);\
  176. void asm_pusharg(LIns*);\
  177. void asm_cmp(LIns *cond); \
  178. void asm_cmpi(LIns *cond); \
  179. void asm_cmpd(LIns *cond);\
  180. Branches asm_branch_helper(bool, LIns* cond, NIns*);\
  181. Branches asm_branchi_helper(bool, LIns* cond, NIns*);\
  182. Branches asm_branchd_helper(bool, LIns* cond, NIns*);\
  183. void asm_div_mod(LIns *cond); \
  184. void asm_load(int d, Register r); \
  185. void asm_immd(Register r, uint64_t q, double d, bool canClobberCCs); \
  186. \
  187. /* These function generate fragments of instructions. */ \
  188. void IMM8(int32_t i) { /* Length: 1 byte. */ \
  189. _nIns -= 1; \
  190. *((int8_t*)_nIns) = int8_t(i); \
  191. }; \
  192. void IMM16(int32_t i) { /* Length: 2 bytes. */ \
  193. _nIns -= 2; \
  194. *((int16_t*)_nIns) = int16_t(i); \
  195. }; \
  196. void IMM32(int32_t i) { /* Length: 4 bytes. */ \
  197. _nIns -= 4; \
  198. *((int32_t*)_nIns) = int32_t(i); \
  199. }; \
  200. void OPCODE(int32_t opc) { /* Length: 1 byte. */ \
  201. NanoAssert(unsigned(opc) <= 0xff); \
  202. *(--_nIns) = uint8_t(opc); \
  203. } \
  204. void OPCODE2(int32_t opc2) { /* Length: 2 bytes. */ \
  205. NanoAssert(unsigned(opc2) <= 0xffff); \
  206. *(--_nIns) = uint8_t(opc2); \
  207. *(--_nIns) = uint8_t(opc2 >> 8); \
  208. } \
  209. void OPCODE3(int32_t opc3) { /* Length: 3 bytes. */ \
  210. NanoAssert(unsigned(opc3) <= 0xffffff); \
  211. *(--_nIns) = uint8_t(opc3); \
  212. *(--_nIns) = uint8_t(opc3 >> 8); \
  213. *(--_nIns) = uint8_t(opc3 >> 16); \
  214. } \
  215. void MODRM(int32_t mod, int32_t ro, int32_t rm) { /* Length: 1 byte. */ \
  216. NanoAssert(unsigned(mod) < 4 && unsigned(ro) < 8 && unsigned(rm) < 8); \
  217. *(--_nIns) = uint8_t(mod << 6 | ro << 3 | rm); \
  218. } \
  219. void SIB(int32_t s, int32_t i, int32_t b) { /* Length: 1 byte. */ \
  220. NanoAssert(unsigned(s) < 4 && unsigned(i) < 8 && unsigned(b) < 8); \
  221. *(--_nIns) = uint8_t(s << 6 | i << 3 | b); \
  222. } \
  223. void MODRMr(int32_t d, int32_t s) { /* Length: 1 byte. */ \
  224. NanoAssert(unsigned(d) < 8 && unsigned(s) < 8); \
  225. MODRM(3, d, s); \
  226. }; \
  227. void MODRMm(int32_t r, int32_t d, Register b); \
  228. void MODRMsib(int32_t r, Register b, Register i, int32_t s, int32_t d); \
  229. void MODRMdm(int32_t r, int32_t addr); \
  230. \
  231. /* These functions generate entire instructions. */ \
  232. void ALU0(int32_t o); \
  233. void ALUm(int32_t c, int32_t r, int32_t d, Register b); \
  234. void ALUdm(int32_t c, Register r, int32_t addr); \
  235. void ALUsib(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \
  236. void ALUsib16(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \
  237. void ALUm16(int32_t c, int32_t r, int32_t d, Register b); \
  238. void ALU2dm(int32_t c, Register r, int32_t addr); \
  239. void ALU2m(int32_t c, Register r, int32_t d, Register b); \
  240. void ALU2sib(int32_t c, Register r, Register base, Register index, int32_t scale, int32_t disp); \
  241. void ALU(int32_t opc, int32_t d, Register s) { \
  242. underrunProtect(2); \
  243. MODRMr(d, REGNUM(s)); \
  244. OPCODE(opc); \
  245. }; \
  246. void ALUi(int32_t c, Register r, int32_t i); \
  247. void ALUmi(int32_t c, int32_t d, Register b, int32_t i); \
  248. void ALU2(int32_t c, Register d, Register s); \
  249. Register AL2AHReg(Register r); \
  250. void OR(Register l, Register r); \
  251. void AND(Register l, Register r); \
  252. void AND8R(Register r); \
  253. void XOR(Register l, Register r); \
  254. void ADD(Register l, Register r); \
  255. void SUB(Register l, Register r); \
  256. void IMUL(Register l, Register r); \
  257. void DIV(Register r); \
  258. void NOT(Register r); \
  259. void NEG(Register r); \
  260. void SHR(Register r, Register s); \
  261. void SAR(Register r, Register s); \
  262. void SHL(Register r, Register s); \
  263. void SHIFTi(int32_t c, Register r, int32_t i); \
  264. void SHLi(Register r, int32_t i); \
  265. void SHRi(Register r, int32_t i); \
  266. void SARi(Register r, int32_t i); \
  267. void MOVZX8(Register d, Register s); \
  268. void SUBi(Register r, int32_t i); \
  269. void ADDi(Register r, int32_t i); \
  270. void ANDi(Register r, int32_t i); \
  271. void ORi(Register r, int32_t i); \
  272. void XORi(Register r, int32_t i); \
  273. void ADDmi(int32_t d, Register b, int32_t i); \
  274. void TEST(Register d, Register s); \
  275. void CMP(Register l, Register r); \
  276. void CMPi(Register r, int32_t i); \
  277. void MR(Register d, Register s) { \
  278. count_mov(); \
  279. ALU(0x8b, REGNUM(d), s); \
  280. asm_output("mov %s,%s", gpn(d), gpn(s)); \
  281. }; \
  282. void LEA(Register r, int32_t d, Register b); \
  283. void LEAmi4(Register r, int32_t d, Register i); \
  284. void CDQ(); \
  285. void INCLi(int32_t p); \
  286. void SETE( Register r); \
  287. void SETNP(Register r); \
  288. void SETNPH(Register r); \
  289. void SETL( Register r); \
  290. void SETLE(Register r); \
  291. void SETG( Register r); \
  292. void SETGE(Register r); \
  293. void SETB( Register r); \
  294. void SETBE(Register r); \
  295. void SETA( Register r); \
  296. void SETAE(Register r); \
  297. void SETO( Register r); \
  298. void MREQ(Register d, Register s); \
  299. void MRNE(Register d, Register s); \
  300. void MRL( Register d, Register s); \
  301. void MRLE(Register d, Register s); \
  302. void MRG( Register d, Register s); \
  303. void MRGE(Register d, Register s); \
  304. void MRB( Register d, Register s); \
  305. void MRBE(Register d, Register s); \
  306. void MRA( Register d, Register s); \
  307. void MRAE(Register d, Register s); \
  308. void MRNO(Register d, Register s); \
  309. void LD(Register reg, int32_t disp, Register base); \
  310. void LDdm(Register reg, int32_t addr); \
  311. void LDsib(Register reg, int32_t disp, Register base, Register index, int32_t scale); \
  312. void LD16S(Register r, int32_t d, Register b); \
  313. void LD16Sdm(Register r, int32_t addr); \
  314. void LD16Ssib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
  315. void LD16Z(Register r, int32_t d, Register b); \
  316. void LD16Zdm(Register r, int32_t addr); \
  317. void LD16Zsib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
  318. void LD8Z(Register r, int32_t d, Register b); \
  319. void LD8Zdm(Register r, int32_t addr); \
  320. void LD8Zsib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
  321. void LD8S(Register r, int32_t d, Register b); \
  322. void LD8Sdm(Register r, int32_t addr); \
  323. void LD8Ssib(Register r, int32_t disp, Register base, Register index, int32_t scale); \
  324. void LDi(Register r, int32_t i); \
  325. void ST8(Register base, int32_t disp, Register reg); \
  326. void ST8sib(int32_t disp, Register base, Register index, int32_t scale, Register reg); \
  327. void ST16(Register base, int32_t disp, Register reg); \
  328. void ST16sib(int32_t disp, Register base, Register index, int32_t scale, Register reg); \
  329. void ST(Register base, int32_t disp, Register reg); \
  330. void STsib(int32_t disp, Register base, Register index, int32_t scale, Register reg); \
  331. void ST8i(Register base, int32_t disp, int32_t imm); \
  332. void ST8isib(int32_t disp, Register base, Register index, int32_t scale, int32_t imm); \
  333. void ST16i(Register base, int32_t disp, int32_t imm); \
  334. void ST16isib(int32_t disp, Register base, Register index, int32_t scale, int32_t imm); \
  335. void STi(Register base, int32_t disp, int32_t imm); \
  336. void STisib(int32_t disp, Register base, Register index, int32_t scale, int32_t imm); \
  337. void RET(); \
  338. void NOP(); \
  339. void INT3(); \
  340. void PUSHi(int32_t i); \
  341. void PUSHr(Register r); \
  342. void PUSHm(int32_t d, Register b); \
  343. void POPr(Register r); \
  344. void JCC(int32_t o, NIns* t, const char* n); \
  345. void JMP_long(NIns* t); \
  346. void JMP(NIns* t) { \
  347. count_jmp(); \
  348. underrunProtect(5); \
  349. intptr_t tt = t ? (intptr_t)t - (intptr_t)_nIns : 0; \
  350. if (t && isS8(tt)) { \
  351. *(--_nIns) = uint8_t(tt & 0xff); \
  352. *(--_nIns) = JMP8; \
  353. } else { \
  354. IMM32(tt); \
  355. *(--_nIns) = JMP32; \
  356. } \
  357. asm_output("jmp %p", t); \
  358. }; \
  359. void JMP_indirect(Register r); \
  360. void JMP_indexed(Register x, int32_t ss, NIns** addr); \
  361. void JE(NIns* t); \
  362. void JNE(NIns* t); \
  363. void JP(NIns* t); \
  364. void JNP(NIns* t); \
  365. void JB(NIns* t); \
  366. void JNB(NIns* t); \
  367. void JBE(NIns* t); \
  368. void JNBE(NIns* t); \
  369. void JA(NIns* t); \
  370. void JNA(NIns* t); \
  371. void JAE(NIns* t); \
  372. void JNAE(NIns* t); \
  373. void JL(NIns* t); \
  374. void JNL(NIns* t); \
  375. void JLE(NIns* t); \
  376. void JNLE(NIns* t); \
  377. void JG(NIns* t); \
  378. void JNG(NIns* t); \
  379. void JGE(NIns* t); \
  380. void JNGE(NIns* t); \
  381. void JO(NIns* t); \
  382. void JNO(NIns* t); \
  383. void SSE(int32_t c, Register d, Register s); \
  384. void SSEm(int32_t c, Register r, int32_t d, Register b); \
  385. void SSEsib(int32_t c, Register rr, int32_t d, Register rb, Register ri, int32_t scale); \
  386. void LDSDm(Register r, const double* addr); \
  387. void SSE_LDQ( Register r, int32_t d, Register b); \
  388. void SSE_LDSS(Register r, int32_t d, Register b); \
  389. void SSE_LDQsib(Register r, int32_t d, Register rb, Register ri, int32_t scale); \
  390. void SSE_LDSSsib(Register r, int32_t d, Register rb, Register ri, int32_t scale); \
  391. void SSE_STSD(int32_t d, Register b, Register r); \
  392. void SSE_STQ( int32_t d, Register b, Register r); \
  393. void SSE_STSS(int32_t d, Register b, Register r); \
  394. void SSE_STQsib(int32_t d, Register rb, Register ri, int32_t scale, Register rv); \
  395. void SSE_CVTSI2SD(Register xr, Register gr); \
  396. void SSE_CVTSD2SI(Register gr, Register xr); \
  397. void SSE_CVTTSD2SI(Register gr, Register xr); \
  398. void SSE_CVTSD2SS(Register xr, Register gr); \
  399. void SSE_CVTSS2SD(Register xr, Register gr); \
  400. void SSE_CVTDQ2PD(Register d, Register r); \
  401. void SSE_MOVD(Register d, Register s); \
  402. void SSE_MOVSD(Register rd, Register rs); \
  403. void SSE_ADDSD(Register rd, Register rs); \
  404. void SSE_ADDSDm(Register r, const double* addr); \
  405. void SSE_SUBSD(Register rd, Register rs); \
  406. void SSE_MULSD(Register rd, Register rs); \
  407. void SSE_DIVSD(Register rd, Register rs); \
  408. void SSE_UCOMISD(Register rl, Register rr); \
  409. void SSE_XORPD(Register r, const uint32_t* maskaddr); \
  410. void SSE_XORPDr(Register rd, Register rs); \
  411. void fpu_push(); \
  412. void fpu_pop(); \
  413. void FPUc(int32_t o); \
  414. void FPU(int32_t o, Register r) { \
  415. underrunProtect(2); \
  416. *(--_nIns) = uint8_t((uint8_t(o) & 0xff) | (REGNUM(r) & 7)); \
  417. *(--_nIns) = uint8_t((o >> 8) & 0xff); \
  418. }; \
  419. void FPUm(int32_t o, int32_t d, Register b); \
  420. void FPUdm(int32_t o, const double* const m); \
  421. void TEST_AH(int32_t i); \
  422. void FNSTSW_AX(); \
  423. void FCHS(); \
  424. void FLD1(); \
  425. void FLDZ(); \
  426. void FST32(bool p, int32_t d, Register b); \
  427. void FSTQ(bool p, int32_t d, Register b); \
  428. void FSTPQ(int32_t d, Register b); \
  429. void FCOM(bool p, int32_t d, Register b); \
  430. void FCOMdm(bool p, const double* dm); \
  431. void FLD32(int32_t d, Register b); \
  432. void FLDQ(int32_t d, Register b); \
  433. void FLDQdm(const double* dm); \
  434. void FILDQ(int32_t d, Register b); \
  435. void FILD(int32_t d, Register b); \
  436. void FIST(bool p, int32_t d, Register b); \
  437. void FADD( int32_t d, Register b); \
  438. void FSUB( int32_t d, Register b); \
  439. void FSUBR(int32_t d, Register b); \
  440. void FMUL( int32_t d, Register b); \
  441. void FDIV( int32_t d, Register b); \
  442. void FDIVR(int32_t d, Register b); \
  443. void FADDdm( const double *dm); \
  444. void FSUBRdm(const double* dm); \
  445. void FMULdm( const double* dm); \
  446. void FDIVRdm(const double* dm); \
  447. void FSTP(Register r) { \
  448. count_fpu(); \
  449. FPU(0xddd8, r); \
  450. asm_output("fstp %s", gpn(r)); \
  451. fpu_pop(); \
  452. }; \
  453. void FCOMP(); \
  454. void FCOMPP(); \
  455. void FLDr(Register r); \
  456. void EMMS(); \
  457. void CALL(const CallInfo* ci); \
  458. void CALLr(const CallInfo* ci, Register r);
  459. }
  460. #endif // __nanojit_Nativei386__