Commit 927f621e7960d3fcf51eecf65ee19b1aafc102ae
1 parent
367e86e8
added float support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@15 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
934 additions
and
160 deletions
Makefile
| @@ -8,6 +8,7 @@ LDFLAGS=-g | @@ -8,6 +8,7 @@ LDFLAGS=-g | ||
| 8 | LIBS= | 8 | LIBS= |
| 9 | CC=gcc | 9 | CC=gcc |
| 10 | DEFINES=-DHAVE_BYTESWAP_H | 10 | DEFINES=-DHAVE_BYTESWAP_H |
| 11 | +OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2 | ||
| 11 | endif | 12 | endif |
| 12 | 13 | ||
| 13 | ifeq ($(ARCH),ppc) | 14 | ifeq ($(ARCH),ppc) |
| @@ -24,6 +25,7 @@ CRTEND=$(GCC_LIBS_DIR)/crtend.o | @@ -24,6 +25,7 @@ CRTEND=$(GCC_LIBS_DIR)/crtend.o | ||
| 24 | LDFLAGS=-static -g -nostdlib $(CRT1) $(CRTI) $(CRTBEGIN) | 25 | LDFLAGS=-static -g -nostdlib $(CRT1) $(CRTI) $(CRTBEGIN) |
| 25 | LIBS=-L$(LIBS_DIR) -ltinyc -lgcc $(CRTEND) $(CRTN) | 26 | LIBS=-L$(LIBS_DIR) -ltinyc -lgcc $(CRTEND) $(CRTN) |
| 26 | DEFINES=-Dsocklen_t=int | 27 | DEFINES=-Dsocklen_t=int |
| 28 | +OP_CFLAGS=$(CFLAGS) | ||
| 27 | endif | 29 | endif |
| 28 | 30 | ||
| 29 | ######################################################### | 31 | ######################################################### |
| @@ -31,7 +33,7 @@ endif | @@ -31,7 +33,7 @@ endif | ||
| 31 | DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS | 33 | DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS |
| 32 | DEFINES+=-DCONFIG_PREFIX=\"/usr/local\" | 34 | DEFINES+=-DCONFIG_PREFIX=\"/usr/local\" |
| 33 | LDSCRIPT=$(ARCH).ld | 35 | LDSCRIPT=$(ARCH).ld |
| 34 | -LIBS+=-ldl | 36 | +LIBS+=-ldl -lm |
| 35 | 37 | ||
| 36 | OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \ | 38 | OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \ |
| 37 | i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \ | 39 | i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \ |
| @@ -67,7 +69,7 @@ op-i386.h: op-i386.o dyngen | @@ -67,7 +69,7 @@ op-i386.h: op-i386.o dyngen | ||
| 67 | ./dyngen -o $@ $< | 69 | ./dyngen -o $@ $< |
| 68 | 70 | ||
| 69 | op-i386.o: op-i386.c opreg_template.h ops_template.h | 71 | op-i386.o: op-i386.c opreg_template.h ops_template.h |
| 70 | - $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< | 72 | + $(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $< |
| 71 | 73 | ||
| 72 | %.o: %.c | 74 | %.o: %.c |
| 73 | $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< | 75 | $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< |
TODO
| @@ -3,3 +3,4 @@ | @@ -3,3 +3,4 @@ | ||
| 3 | - threads | 3 | - threads |
| 4 | - fix printf for doubles (fp87.c bug ?) | 4 | - fix printf for doubles (fp87.c bug ?) |
| 5 | - make it self runnable (use same trick as ld.so : include its own relocator and libc) | 5 | - make it self runnable (use same trick as ld.so : include its own relocator and libc) |
| 6 | +- better FPU comparisons (ucom/com) |
cpu-i386.h
| @@ -75,6 +75,16 @@ enum { | @@ -75,6 +75,16 @@ enum { | ||
| 75 | CC_OP_NB, | 75 | CC_OP_NB, |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | +#ifdef __i386__ | ||
| 79 | +#define USE_X86LDOUBLE | ||
| 80 | +#endif | ||
| 81 | + | ||
| 82 | +#ifdef USE_X86LDOUBLE | ||
| 83 | +typedef long double CPU86_LDouble; | ||
| 84 | +#else | ||
| 85 | +typedef double CPU86_LDouble; | ||
| 86 | +#endif | ||
| 87 | + | ||
| 78 | typedef struct CPU86State { | 88 | typedef struct CPU86State { |
| 79 | /* standard registers */ | 89 | /* standard registers */ |
| 80 | uint32_t regs[8]; | 90 | uint32_t regs[8]; |
| @@ -91,10 +101,18 @@ typedef struct CPU86State { | @@ -91,10 +101,18 @@ typedef struct CPU86State { | ||
| 91 | uint8_t *segs_base[6]; | 101 | uint8_t *segs_base[6]; |
| 92 | uint32_t segs[6]; | 102 | uint32_t segs[6]; |
| 93 | 103 | ||
| 104 | + /* FPU state */ | ||
| 105 | + CPU86_LDouble fpregs[8]; | ||
| 106 | + uint8_t fptags[8]; /* 0 = valid, 1 = empty */ | ||
| 107 | + unsigned int fpstt; /* top of stack index */ | ||
| 108 | + unsigned int fpus; | ||
| 109 | + unsigned int fpuc; | ||
| 110 | + | ||
| 94 | /* emulator internal variables */ | 111 | /* emulator internal variables */ |
| 95 | uint32_t t0; /* temporary t0 storage */ | 112 | uint32_t t0; /* temporary t0 storage */ |
| 96 | uint32_t t1; /* temporary t1 storage */ | 113 | uint32_t t1; /* temporary t1 storage */ |
| 97 | uint32_t a0; /* temporary a0 storage (address) */ | 114 | uint32_t a0; /* temporary a0 storage (address) */ |
| 115 | + CPU86_LDouble ft0; | ||
| 98 | } CPU86State; | 116 | } CPU86State; |
| 99 | 117 | ||
| 100 | static inline int ldub(void *ptr) | 118 | static inline int ldub(void *ptr) |
| @@ -122,6 +140,10 @@ static inline int ldl(void *ptr) | @@ -122,6 +140,10 @@ static inline int ldl(void *ptr) | ||
| 122 | return *(uint32_t *)ptr; | 140 | return *(uint32_t *)ptr; |
| 123 | } | 141 | } |
| 124 | 142 | ||
| 143 | +static inline uint64_t ldq(void *ptr) | ||
| 144 | +{ | ||
| 145 | + return *(uint64_t *)ptr; | ||
| 146 | +} | ||
| 125 | 147 | ||
| 126 | static inline void stb(void *ptr, int v) | 148 | static inline void stb(void *ptr, int v) |
| 127 | { | 149 | { |
| @@ -138,11 +160,40 @@ static inline void stl(void *ptr, int v) | @@ -138,11 +160,40 @@ static inline void stl(void *ptr, int v) | ||
| 138 | *(uint32_t *)ptr = v; | 160 | *(uint32_t *)ptr = v; |
| 139 | } | 161 | } |
| 140 | 162 | ||
| 163 | +static inline void stq(void *ptr, int v) | ||
| 164 | +{ | ||
| 165 | + *(uint64_t *)ptr = v; | ||
| 166 | +} | ||
| 167 | + | ||
| 168 | +/* float access */ | ||
| 169 | + | ||
| 170 | +static inline float ldfl(void *ptr) | ||
| 171 | +{ | ||
| 172 | + return *(float *)ptr; | ||
| 173 | +} | ||
| 174 | + | ||
| 175 | +static inline double ldfq(void *ptr) | ||
| 176 | +{ | ||
| 177 | + return *(double *)ptr; | ||
| 178 | +} | ||
| 179 | + | ||
| 180 | +static inline void stfl(void *ptr, float v) | ||
| 181 | +{ | ||
| 182 | + *(float *)ptr = v; | ||
| 183 | +} | ||
| 184 | + | ||
| 185 | +static inline void stfq(void *ptr, double v) | ||
| 186 | +{ | ||
| 187 | + *(double *)ptr = v; | ||
| 188 | +} | ||
| 189 | + | ||
| 190 | +#ifndef IN_OP_I386 | ||
| 141 | void port_outb(int addr, int val); | 191 | void port_outb(int addr, int val); |
| 142 | void port_outw(int addr, int val); | 192 | void port_outw(int addr, int val); |
| 143 | void port_outl(int addr, int val); | 193 | void port_outl(int addr, int val); |
| 144 | int port_inb(int addr); | 194 | int port_inb(int addr); |
| 145 | int port_inw(int addr); | 195 | int port_inw(int addr); |
| 146 | int port_inl(int addr); | 196 | int port_inl(int addr); |
| 197 | +#endif | ||
| 147 | 198 | ||
| 148 | #endif /* CPU_I386_H */ | 199 | #endif /* CPU_I386_H */ |
dyngen.c
| @@ -243,6 +243,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -243,6 +243,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 243 | if (n >= MAX_ARGS) | 243 | if (n >= MAX_ARGS) |
| 244 | error("too many arguments in %s", name); | 244 | error("too many arguments in %s", name); |
| 245 | args_present[n - 1] = 1; | 245 | args_present[n - 1] = 1; |
| 246 | + } else { | ||
| 247 | + fprintf(outfile, "extern char %s;\n", sym_name); | ||
| 246 | } | 248 | } |
| 247 | } | 249 | } |
| 248 | } | 250 | } |
| @@ -257,6 +259,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | @@ -257,6 +259,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size, | ||
| 257 | if (n >= MAX_ARGS) | 259 | if (n >= MAX_ARGS) |
| 258 | error("too many arguments in %s", name); | 260 | error("too many arguments in %s", name); |
| 259 | args_present[n - 1] = 1; | 261 | args_present[n - 1] = 1; |
| 262 | + } else { | ||
| 263 | + fprintf(outfile, "extern char %s;\n", sym_name); | ||
| 260 | } | 264 | } |
| 261 | } | 265 | } |
| 262 | } | 266 | } |
op-i386.c
| @@ -66,7 +66,13 @@ register struct CPU86State *env asm("l3"); | @@ -66,7 +66,13 @@ register struct CPU86State *env asm("l3"); | ||
| 66 | 66 | ||
| 67 | #define CC_SRC (env->cc_src) | 67 | #define CC_SRC (env->cc_src) |
| 68 | #define CC_DST (env->cc_dst) | 68 | #define CC_DST (env->cc_dst) |
| 69 | -#define CC_OP (env->cc_op) | 69 | +#define CC_OP (env->cc_op) |
| 70 | + | ||
| 71 | +/* float macros */ | ||
| 72 | +#define FT0 (env->ft0) | ||
| 73 | +#define ST0 (env->fpregs[env->fpstt]) | ||
| 74 | +#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7]) | ||
| 75 | +#define ST1 ST(1) | ||
| 70 | 76 | ||
| 71 | extern int __op_param1, __op_param2, __op_param3; | 77 | extern int __op_param1, __op_param2, __op_param3; |
| 72 | #define PARAM1 ((long)(&__op_param1)) | 78 | #define PARAM1 ((long)(&__op_param1)) |
| @@ -133,6 +139,44 @@ const uint8_t rclb_table[32] = { | @@ -133,6 +139,44 @@ const uint8_t rclb_table[32] = { | ||
| 133 | 6, 7, 8, 0, 1, 2, 3, 4, | 139 | 6, 7, 8, 0, 1, 2, 3, 4, |
| 134 | }; | 140 | }; |
| 135 | 141 | ||
| 142 | +#ifdef USE_X86LDOUBLE | ||
| 143 | +/* an array of Intel 80-bit FP constants, to be loaded via integer ops */ | ||
| 144 | +typedef unsigned short f15ld[5]; | ||
| 145 | +const f15ld f15rk[] = | ||
| 146 | +{ | ||
| 147 | +/*0*/ {0x0000,0x0000,0x0000,0x0000,0x0000}, | ||
| 148 | +/*1*/ {0x0000,0x0000,0x0000,0x8000,0x3fff}, | ||
| 149 | +/*pi*/ {0xc235,0x2168,0xdaa2,0xc90f,0x4000}, | ||
| 150 | +/*lg2*/ {0xf799,0xfbcf,0x9a84,0x9a20,0x3ffd}, | ||
| 151 | +/*ln2*/ {0x79ac,0xd1cf,0x17f7,0xb172,0x3ffe}, | ||
| 152 | +/*l2e*/ {0xf0bc,0x5c17,0x3b29,0xb8aa,0x3fff}, | ||
| 153 | +/*l2t*/ {0x8afe,0xcd1b,0x784b,0xd49a,0x4000} | ||
| 154 | +}; | ||
| 155 | +#else | ||
| 156 | +/* the same, 64-bit version */ | ||
| 157 | +typedef unsigned short f15ld[4]; | ||
| 158 | +const f15ld f15rk[] = | ||
| 159 | +{ | ||
| 160 | +#ifndef WORDS_BIGENDIAN | ||
| 161 | +/*0*/ {0x0000,0x0000,0x0000,0x0000}, | ||
| 162 | +/*1*/ {0x0000,0x0000,0x0000,0x3ff0}, | ||
| 163 | +/*pi*/ {0x2d18,0x5444,0x21fb,0x4009}, | ||
| 164 | +/*lg2*/ {0x79ff,0x509f,0x4413,0x3fd3}, | ||
| 165 | +/*ln2*/ {0x39ef,0xfefa,0x2e42,0x3fe6}, | ||
| 166 | +/*l2e*/ {0x82fe,0x652b,0x1547,0x3ff7}, | ||
| 167 | +/*l2t*/ {0xa371,0x0979,0x934f,0x400a} | ||
| 168 | +#else | ||
| 169 | +/*0*/ {0x0000,0x0000,0x0000,0x0000}, | ||
| 170 | +/*1*/ {0x3ff0,0x0000,0x0000,0x0000}, | ||
| 171 | +/*pi*/ {0x4009,0x21fb,0x5444,0x2d18}, | ||
| 172 | +/*lg2*/ {0x3fd3,0x4413,0x509f,0x79ff}, | ||
| 173 | +/*ln2*/ {0x3fe6,0x2e42,0xfefa,0x39ef}, | ||
| 174 | +/*l2e*/ {0x3ff7,0x1547,0x652b,0x82fe}, | ||
| 175 | +/*l2t*/ {0x400a,0x934f,0x0979,0xa371} | ||
| 176 | +#endif | ||
| 177 | +}; | ||
| 178 | +#endif | ||
| 179 | + | ||
| 136 | /* n must be a constant to be efficient */ | 180 | /* n must be a constant to be efficient */ |
| 137 | static inline int lshift(int x, int n) | 181 | static inline int lshift(int x, int n) |
| 138 | { | 182 | { |
| @@ -866,3 +910,685 @@ CCTable cc_table[CC_OP_NB] = { | @@ -866,3 +910,685 @@ CCTable cc_table[CC_OP_NB] = { | ||
| 866 | [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw }, | 910 | [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw }, |
| 867 | [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, | 911 | [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, |
| 868 | }; | 912 | }; |
| 913 | + | ||
| 914 | +/* floating point support */ | ||
| 915 | + | ||
| 916 | +#ifdef USE_X86LDOUBLE | ||
| 917 | +/* use long double functions */ | ||
| 918 | +#define lrint lrintl | ||
| 919 | +#define llrint llrintl | ||
| 920 | +#define fabs fabsl | ||
| 921 | +#define sin sinl | ||
| 922 | +#define cos cosl | ||
| 923 | +#define sqrt sqrtl | ||
| 924 | +#define pow powl | ||
| 925 | +#define log logl | ||
| 926 | +#define tan tanl | ||
| 927 | +#define atan2 atan2l | ||
| 928 | +#define floor floorl | ||
| 929 | +#define ceil ceill | ||
| 930 | +#define rint rintl | ||
| 931 | +#endif | ||
| 932 | + | ||
| 933 | +extern int lrint(CPU86_LDouble x); | ||
| 934 | +extern int64_t llrint(CPU86_LDouble x); | ||
| 935 | +extern CPU86_LDouble fabs(CPU86_LDouble x); | ||
| 936 | +extern CPU86_LDouble sin(CPU86_LDouble x); | ||
| 937 | +extern CPU86_LDouble cos(CPU86_LDouble x); | ||
| 938 | +extern CPU86_LDouble sqrt(CPU86_LDouble x); | ||
| 939 | +extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble); | ||
| 940 | +extern CPU86_LDouble log(CPU86_LDouble x); | ||
| 941 | +extern CPU86_LDouble tan(CPU86_LDouble x); | ||
| 942 | +extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble); | ||
| 943 | +extern CPU86_LDouble floor(CPU86_LDouble x); | ||
| 944 | +extern CPU86_LDouble ceil(CPU86_LDouble x); | ||
| 945 | +extern CPU86_LDouble rint(CPU86_LDouble x); | ||
| 946 | + | ||
| 947 | +#define RC_MASK 0xc00 | ||
| 948 | +#define RC_NEAR 0x000 | ||
| 949 | +#define RC_DOWN 0x400 | ||
| 950 | +#define RC_UP 0x800 | ||
| 951 | +#define RC_CHOP 0xc00 | ||
| 952 | + | ||
| 953 | +#define MAXTAN 9223372036854775808.0 | ||
| 954 | + | ||
| 955 | +#ifdef USE_X86LDOUBLE | ||
| 956 | + | ||
| 957 | +/* only for x86 */ | ||
| 958 | +typedef union { | ||
| 959 | + long double d; | ||
| 960 | + struct { | ||
| 961 | + unsigned long long lower; | ||
| 962 | + unsigned short upper; | ||
| 963 | + } l; | ||
| 964 | +} CPU86_LDoubleU; | ||
| 965 | + | ||
| 966 | +/* the following deal with x86 long double-precision numbers */ | ||
| 967 | +#define MAXEXPD 0x7fff | ||
| 968 | +#define EXPBIAS 16383 | ||
| 969 | +#define EXPD(fp) (fp.l.upper & 0x7fff) | ||
| 970 | +#define SIGND(fp) ((fp.l.upper) & 0x8000) | ||
| 971 | +#define MANTD(fp) (fp.l.lower) | ||
| 972 | +#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS | ||
| 973 | + | ||
| 974 | +#else | ||
| 975 | + | ||
| 976 | +typedef { | ||
| 977 | + double d; | ||
| 978 | +#ifndef WORDS_BIGENDIAN | ||
| 979 | + struct { | ||
| 980 | + unsigned long lower; | ||
| 981 | + long upper; | ||
| 982 | + } l; | ||
| 983 | +#else | ||
| 984 | + struct { | ||
| 985 | + long upper; | ||
| 986 | + unsigned long lower; | ||
| 987 | + } l; | ||
| 988 | +#endif | ||
| 989 | + long long ll; | ||
| 990 | +} CPU86_LDoubleU; | ||
| 991 | + | ||
| 992 | +/* the following deal with IEEE double-precision numbers */ | ||
| 993 | +#define MAXEXPD 0x7ff | ||
| 994 | +#define EXPBIAS 1023 | ||
| 995 | +#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) | ||
| 996 | +#define SIGND(fp) ((fp.l.upper) & 0x80000000) | ||
| 997 | +#define MANTD(fp) (fp.ll & ((1LL << 52) - 1)) | ||
| 998 | +#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20) | ||
| 999 | +#endif | ||
| 1000 | + | ||
| 1001 | +/* fp load FT0 */ | ||
| 1002 | + | ||
| 1003 | +void OPPROTO op_flds_FT0_A0(void) | ||
| 1004 | +{ | ||
| 1005 | + FT0 = ldfl((void *)A0); | ||
| 1006 | +} | ||
| 1007 | + | ||
| 1008 | +void OPPROTO op_fldl_FT0_A0(void) | ||
| 1009 | +{ | ||
| 1010 | + FT0 = ldfq((void *)A0); | ||
| 1011 | +} | ||
| 1012 | + | ||
| 1013 | +void OPPROTO op_fild_FT0_A0(void) | ||
| 1014 | +{ | ||
| 1015 | + FT0 = (CPU86_LDouble)ldsw((void *)A0); | ||
| 1016 | +} | ||
| 1017 | + | ||
| 1018 | +void OPPROTO op_fildl_FT0_A0(void) | ||
| 1019 | +{ | ||
| 1020 | + FT0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | ||
| 1021 | +} | ||
| 1022 | + | ||
| 1023 | +void OPPROTO op_fildll_FT0_A0(void) | ||
| 1024 | +{ | ||
| 1025 | + FT0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | ||
| 1026 | +} | ||
| 1027 | + | ||
| 1028 | +/* fp load ST0 */ | ||
| 1029 | + | ||
| 1030 | +void OPPROTO op_flds_ST0_A0(void) | ||
| 1031 | +{ | ||
| 1032 | + ST0 = ldfl((void *)A0); | ||
| 1033 | +} | ||
| 1034 | + | ||
| 1035 | +void OPPROTO op_fldl_ST0_A0(void) | ||
| 1036 | +{ | ||
| 1037 | + ST0 = ldfq((void *)A0); | ||
| 1038 | +} | ||
| 1039 | + | ||
| 1040 | +void OPPROTO op_fild_ST0_A0(void) | ||
| 1041 | +{ | ||
| 1042 | + ST0 = (CPU86_LDouble)ldsw((void *)A0); | ||
| 1043 | +} | ||
| 1044 | + | ||
| 1045 | +void OPPROTO op_fildl_ST0_A0(void) | ||
| 1046 | +{ | ||
| 1047 | + ST0 = (CPU86_LDouble)((int32_t)ldl((void *)A0)); | ||
| 1048 | +} | ||
| 1049 | + | ||
| 1050 | +void OPPROTO op_fildll_ST0_A0(void) | ||
| 1051 | +{ | ||
| 1052 | + ST0 = (CPU86_LDouble)((int64_t)ldq((void *)A0)); | ||
| 1053 | +} | ||
| 1054 | + | ||
| 1055 | +/* fp store */ | ||
| 1056 | + | ||
| 1057 | +void OPPROTO op_fsts_ST0_A0(void) | ||
| 1058 | +{ | ||
| 1059 | + stfl((void *)A0, (float)ST0); | ||
| 1060 | +} | ||
| 1061 | + | ||
| 1062 | +void OPPROTO op_fstl_ST0_A0(void) | ||
| 1063 | +{ | ||
| 1064 | + ST0 = ldfq((void *)A0); | ||
| 1065 | +} | ||
| 1066 | + | ||
| 1067 | +void OPPROTO op_fist_ST0_A0(void) | ||
| 1068 | +{ | ||
| 1069 | + int val; | ||
| 1070 | + val = lrint(ST0); | ||
| 1071 | + stw((void *)A0, val); | ||
| 1072 | +} | ||
| 1073 | + | ||
| 1074 | +void OPPROTO op_fistl_ST0_A0(void) | ||
| 1075 | +{ | ||
| 1076 | + int val; | ||
| 1077 | + val = lrint(ST0); | ||
| 1078 | + stl((void *)A0, val); | ||
| 1079 | +} | ||
| 1080 | + | ||
| 1081 | +void OPPROTO op_fistll_ST0_A0(void) | ||
| 1082 | +{ | ||
| 1083 | + int64_t val; | ||
| 1084 | + val = llrint(ST0); | ||
| 1085 | + stq((void *)A0, val); | ||
| 1086 | +} | ||
| 1087 | + | ||
| 1088 | +/* FPU move */ | ||
| 1089 | + | ||
| 1090 | +static inline void fpush(void) | ||
| 1091 | +{ | ||
| 1092 | + env->fpstt = (env->fpstt - 1) & 7; | ||
| 1093 | + env->fptags[env->fpstt] = 0; /* validate stack entry */ | ||
| 1094 | +} | ||
| 1095 | + | ||
| 1096 | +static inline void fpop(void) | ||
| 1097 | +{ | ||
| 1098 | + env->fptags[env->fpstt] = 1; /* invvalidate stack entry */ | ||
| 1099 | + env->fpstt = (env->fpstt + 1) & 7; | ||
| 1100 | +} | ||
| 1101 | + | ||
| 1102 | +void OPPROTO op_fpush(void) | ||
| 1103 | +{ | ||
| 1104 | + fpush(); | ||
| 1105 | +} | ||
| 1106 | + | ||
| 1107 | +void OPPROTO op_fpop(void) | ||
| 1108 | +{ | ||
| 1109 | + fpop(); | ||
| 1110 | +} | ||
| 1111 | + | ||
| 1112 | +void OPPROTO op_fdecstp(void) | ||
| 1113 | +{ | ||
| 1114 | + env->fpstt = (env->fpstt - 1) & 7; | ||
| 1115 | + env->fpus &= (~0x4700); | ||
| 1116 | +} | ||
| 1117 | + | ||
| 1118 | +void OPPROTO op_fincstp(void) | ||
| 1119 | +{ | ||
| 1120 | + env->fpstt = (env->fpstt + 1) & 7; | ||
| 1121 | + env->fpus &= (~0x4700); | ||
| 1122 | +} | ||
| 1123 | + | ||
| 1124 | +void OPPROTO op_fmov_ST0_FT0(void) | ||
| 1125 | +{ | ||
| 1126 | + ST0 = FT0; | ||
| 1127 | +} | ||
| 1128 | + | ||
| 1129 | +void OPPROTO op_fmov_FT0_STN(void) | ||
| 1130 | +{ | ||
| 1131 | + FT0 = ST(PARAM1); | ||
| 1132 | +} | ||
| 1133 | + | ||
| 1134 | +void OPPROTO op_fmov_ST0_STN(void) | ||
| 1135 | +{ | ||
| 1136 | + ST0 = ST(PARAM1); | ||
| 1137 | +} | ||
| 1138 | + | ||
| 1139 | +void OPPROTO op_fmov_STN_ST0(void) | ||
| 1140 | +{ | ||
| 1141 | + ST(PARAM1) = ST0; | ||
| 1142 | +} | ||
| 1143 | + | ||
| 1144 | +void OPPROTO op_fxchg_ST0_STN(void) | ||
| 1145 | +{ | ||
| 1146 | + CPU86_LDouble tmp; | ||
| 1147 | + tmp = ST(PARAM1); | ||
| 1148 | + ST(PARAM1) = ST0; | ||
| 1149 | + ST0 = tmp; | ||
| 1150 | +} | ||
| 1151 | + | ||
| 1152 | +/* FPU operations */ | ||
| 1153 | + | ||
| 1154 | +/* XXX: handle nans */ | ||
| 1155 | +void OPPROTO op_fcom_ST0_FT0(void) | ||
| 1156 | +{ | ||
| 1157 | + env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ | ||
| 1158 | + if (ST0 < FT0) | ||
| 1159 | + env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ | ||
| 1160 | + else if (ST0 == FT0) | ||
| 1161 | + env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ | ||
| 1162 | + FORCE_RET(); | ||
| 1163 | +} | ||
| 1164 | + | ||
| 1165 | +void OPPROTO op_fadd_ST0_FT0(void) | ||
| 1166 | +{ | ||
| 1167 | + ST0 += FT0; | ||
| 1168 | +} | ||
| 1169 | + | ||
| 1170 | +void OPPROTO op_fmul_ST0_FT0(void) | ||
| 1171 | +{ | ||
| 1172 | + ST0 *= FT0; | ||
| 1173 | +} | ||
| 1174 | + | ||
| 1175 | +void OPPROTO op_fsub_ST0_FT0(void) | ||
| 1176 | +{ | ||
| 1177 | + ST0 -= FT0; | ||
| 1178 | +} | ||
| 1179 | + | ||
| 1180 | +void OPPROTO op_fsubr_ST0_FT0(void) | ||
| 1181 | +{ | ||
| 1182 | + ST0 = FT0 - ST0; | ||
| 1183 | +} | ||
| 1184 | + | ||
| 1185 | +void OPPROTO op_fdiv_ST0_FT0(void) | ||
| 1186 | +{ | ||
| 1187 | + ST0 /= FT0; | ||
| 1188 | +} | ||
| 1189 | + | ||
| 1190 | +void OPPROTO op_fdivr_ST0_FT0(void) | ||
| 1191 | +{ | ||
| 1192 | + ST0 = FT0 / ST0; | ||
| 1193 | +} | ||
| 1194 | + | ||
| 1195 | +/* fp operations between STN and ST0 */ | ||
| 1196 | + | ||
| 1197 | +void OPPROTO op_fadd_STN_ST0(void) | ||
| 1198 | +{ | ||
| 1199 | + ST(PARAM1) += ST0; | ||
| 1200 | +} | ||
| 1201 | + | ||
| 1202 | +void OPPROTO op_fmul_STN_ST0(void) | ||
| 1203 | +{ | ||
| 1204 | + ST(PARAM1) *= ST0; | ||
| 1205 | +} | ||
| 1206 | + | ||
| 1207 | +void OPPROTO op_fsub_STN_ST0(void) | ||
| 1208 | +{ | ||
| 1209 | + ST(PARAM1) -= ST0; | ||
| 1210 | +} | ||
| 1211 | + | ||
| 1212 | +void OPPROTO op_fsubr_STN_ST0(void) | ||
| 1213 | +{ | ||
| 1214 | + CPU86_LDouble *p; | ||
| 1215 | + p = &ST(PARAM1); | ||
| 1216 | + *p = ST0 - *p; | ||
| 1217 | +} | ||
| 1218 | + | ||
| 1219 | +void OPPROTO op_fdiv_STN_ST0(void) | ||
| 1220 | +{ | ||
| 1221 | + ST(PARAM1) /= ST0; | ||
| 1222 | +} | ||
| 1223 | + | ||
| 1224 | +void OPPROTO op_fdivr_STN_ST0(void) | ||
| 1225 | +{ | ||
| 1226 | + CPU86_LDouble *p; | ||
| 1227 | + p = &ST(PARAM1); | ||
| 1228 | + *p = ST0 / *p; | ||
| 1229 | +} | ||
| 1230 | + | ||
| 1231 | +/* misc FPU operations */ | ||
| 1232 | +void OPPROTO op_fchs_ST0(void) | ||
| 1233 | +{ | ||
| 1234 | + ST0 = -ST0; | ||
| 1235 | +} | ||
| 1236 | + | ||
| 1237 | +void OPPROTO op_fabs_ST0(void) | ||
| 1238 | +{ | ||
| 1239 | + ST0 = fabs(ST0); | ||
| 1240 | +} | ||
| 1241 | + | ||
| 1242 | +void OPPROTO op_fxam_ST0(void) | ||
| 1243 | +{ | ||
| 1244 | + CPU86_LDoubleU temp; | ||
| 1245 | + int expdif; | ||
| 1246 | + | ||
| 1247 | + temp.d = ST0; | ||
| 1248 | + | ||
| 1249 | + env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
| 1250 | + if (SIGND(temp)) | ||
| 1251 | + env->fpus |= 0x200; /* C1 <-- 1 */ | ||
| 1252 | + | ||
| 1253 | + expdif = EXPD(temp); | ||
| 1254 | + if (expdif == MAXEXPD) { | ||
| 1255 | + if (MANTD(temp) == 0) | ||
| 1256 | + env->fpus |= 0x500 /*Infinity*/; | ||
| 1257 | + else | ||
| 1258 | + env->fpus |= 0x100 /*NaN*/; | ||
| 1259 | + } else if (expdif == 0) { | ||
| 1260 | + if (MANTD(temp) == 0) | ||
| 1261 | + env->fpus |= 0x4000 /*Zero*/; | ||
| 1262 | + else | ||
| 1263 | + env->fpus |= 0x4400 /*Denormal*/; | ||
| 1264 | + } else { | ||
| 1265 | + env->fpus |= 0x400; | ||
| 1266 | + } | ||
| 1267 | + FORCE_RET(); | ||
| 1268 | +} | ||
| 1269 | + | ||
| 1270 | +void OPPROTO op_fld1_ST0(void) | ||
| 1271 | +{ | ||
| 1272 | + ST0 = *(CPU86_LDouble *)&f15rk[1]; | ||
| 1273 | +} | ||
| 1274 | + | ||
| 1275 | +void OPPROTO op_fld2t_ST0(void) | ||
| 1276 | +{ | ||
| 1277 | + ST0 = *(CPU86_LDouble *)&f15rk[6]; | ||
| 1278 | +} | ||
| 1279 | + | ||
| 1280 | +void OPPROTO op_fld2e_ST0(void) | ||
| 1281 | +{ | ||
| 1282 | + ST0 = *(CPU86_LDouble *)&f15rk[5]; | ||
| 1283 | +} | ||
| 1284 | + | ||
| 1285 | +void OPPROTO op_fldpi_ST0(void) | ||
| 1286 | +{ | ||
| 1287 | + ST0 = *(CPU86_LDouble *)&f15rk[2]; | ||
| 1288 | +} | ||
| 1289 | + | ||
| 1290 | +void OPPROTO op_fldlg2_ST0(void) | ||
| 1291 | +{ | ||
| 1292 | + ST0 = *(CPU86_LDouble *)&f15rk[3]; | ||
| 1293 | +} | ||
| 1294 | + | ||
| 1295 | +void OPPROTO op_fldln2_ST0(void) | ||
| 1296 | +{ | ||
| 1297 | + ST0 = *(CPU86_LDouble *)&f15rk[4]; | ||
| 1298 | +} | ||
| 1299 | + | ||
| 1300 | +void OPPROTO op_fldz_ST0(void) | ||
| 1301 | +{ | ||
| 1302 | + ST0 = *(CPU86_LDouble *)&f15rk[0]; | ||
| 1303 | +} | ||
| 1304 | + | ||
| 1305 | +void OPPROTO op_fldz_FT0(void) | ||
| 1306 | +{ | ||
| 1307 | + ST0 = *(CPU86_LDouble *)&f15rk[0]; | ||
| 1308 | +} | ||
| 1309 | + | ||
| 1310 | +void helper_f2xm1(void) | ||
| 1311 | +{ | ||
| 1312 | + ST0 = pow(2.0,ST0) - 1.0; | ||
| 1313 | +} | ||
| 1314 | + | ||
| 1315 | +void helper_fyl2x(void) | ||
| 1316 | +{ | ||
| 1317 | + CPU86_LDouble fptemp; | ||
| 1318 | + | ||
| 1319 | + fptemp = ST0; | ||
| 1320 | + if (fptemp>0.0){ | ||
| 1321 | + fptemp = log(fptemp)/log(2.0); /* log2(ST) */ | ||
| 1322 | + ST1 *= fptemp; | ||
| 1323 | + fpop(); | ||
| 1324 | + } else { | ||
| 1325 | + env->fpus &= (~0x4700); | ||
| 1326 | + env->fpus |= 0x400; | ||
| 1327 | + } | ||
| 1328 | +} | ||
| 1329 | + | ||
| 1330 | +void helper_fptan(void) | ||
| 1331 | +{ | ||
| 1332 | + CPU86_LDouble fptemp; | ||
| 1333 | + | ||
| 1334 | + fptemp = ST0; | ||
| 1335 | + if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
| 1336 | + env->fpus |= 0x400; | ||
| 1337 | + } else { | ||
| 1338 | + ST0 = tan(fptemp); | ||
| 1339 | + fpush(); | ||
| 1340 | + ST0 = 1.0; | ||
| 1341 | + env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
| 1342 | + /* the above code is for |arg| < 2**52 only */ | ||
| 1343 | + } | ||
| 1344 | +} | ||
| 1345 | + | ||
| 1346 | +void helper_fpatan(void) | ||
| 1347 | +{ | ||
| 1348 | + CPU86_LDouble fptemp, fpsrcop; | ||
| 1349 | + | ||
| 1350 | + fpsrcop = ST1; | ||
| 1351 | + fptemp = ST0; | ||
| 1352 | + ST1 = atan2(fpsrcop,fptemp); | ||
| 1353 | + fpop(); | ||
| 1354 | +} | ||
| 1355 | + | ||
| 1356 | +void helper_fxtract(void) | ||
| 1357 | +{ | ||
| 1358 | + CPU86_LDoubleU temp; | ||
| 1359 | + unsigned int expdif; | ||
| 1360 | + | ||
| 1361 | + temp.d = ST0; | ||
| 1362 | + expdif = EXPD(temp) - EXPBIAS; | ||
| 1363 | + /*DP exponent bias*/ | ||
| 1364 | + ST0 = expdif; | ||
| 1365 | + fpush(); | ||
| 1366 | + BIASEXPONENT(temp); | ||
| 1367 | + ST0 = temp.d; | ||
| 1368 | +} | ||
| 1369 | + | ||
| 1370 | +void helper_fprem1(void) | ||
| 1371 | +{ | ||
| 1372 | + CPU86_LDouble dblq, fpsrcop, fptemp; | ||
| 1373 | + CPU86_LDoubleU fpsrcop1, fptemp1; | ||
| 1374 | + int expdif; | ||
| 1375 | + int q; | ||
| 1376 | + | ||
| 1377 | + fpsrcop = ST0; | ||
| 1378 | + fptemp = ST1; | ||
| 1379 | + fpsrcop1.d = fpsrcop; | ||
| 1380 | + fptemp1.d = fptemp; | ||
| 1381 | + expdif = EXPD(fpsrcop1) - EXPD(fptemp1); | ||
| 1382 | + if (expdif < 53) { | ||
| 1383 | + dblq = fpsrcop / fptemp; | ||
| 1384 | + dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); | ||
| 1385 | + ST0 = fpsrcop - fptemp*dblq; | ||
| 1386 | + q = (int)dblq; /* cutting off top bits is assumed here */ | ||
| 1387 | + env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
| 1388 | + /* (C0,C1,C3) <-- (q2,q1,q0) */ | ||
| 1389 | + env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ | ||
| 1390 | + env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ | ||
| 1391 | + env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ | ||
| 1392 | + } else { | ||
| 1393 | + env->fpus |= 0x400; /* C2 <-- 1 */ | ||
| 1394 | + fptemp = pow(2.0, expdif-50); | ||
| 1395 | + fpsrcop = (ST0 / ST1) / fptemp; | ||
| 1396 | + /* fpsrcop = integer obtained by rounding to the nearest */ | ||
| 1397 | + fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)? | ||
| 1398 | + floor(fpsrcop): ceil(fpsrcop); | ||
| 1399 | + ST0 -= (ST1 * fpsrcop * fptemp); | ||
| 1400 | + } | ||
| 1401 | +} | ||
| 1402 | + | ||
| 1403 | +void helper_fprem(void) | ||
| 1404 | +{ | ||
| 1405 | + CPU86_LDouble dblq, fpsrcop, fptemp; | ||
| 1406 | + CPU86_LDoubleU fpsrcop1, fptemp1; | ||
| 1407 | + int expdif; | ||
| 1408 | + int q; | ||
| 1409 | + | ||
| 1410 | + fpsrcop = ST0; | ||
| 1411 | + fptemp = ST1; | ||
| 1412 | + fpsrcop1.d = fpsrcop; | ||
| 1413 | + fptemp1.d = fptemp; | ||
| 1414 | + expdif = EXPD(fpsrcop1) - EXPD(fptemp1); | ||
| 1415 | + if ( expdif < 53 ) { | ||
| 1416 | + dblq = fpsrcop / fptemp; | ||
| 1417 | + dblq = (dblq < 0.0)? ceil(dblq): floor(dblq); | ||
| 1418 | + ST0 = fpsrcop - fptemp*dblq; | ||
| 1419 | + q = (int)dblq; /* cutting off top bits is assumed here */ | ||
| 1420 | + env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
| 1421 | + /* (C0,C1,C3) <-- (q2,q1,q0) */ | ||
| 1422 | + env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */ | ||
| 1423 | + env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */ | ||
| 1424 | + env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */ | ||
| 1425 | + } else { | ||
| 1426 | + env->fpus |= 0x400; /* C2 <-- 1 */ | ||
| 1427 | + fptemp = pow(2.0, expdif-50); | ||
| 1428 | + fpsrcop = (ST0 / ST1) / fptemp; | ||
| 1429 | + /* fpsrcop = integer obtained by chopping */ | ||
| 1430 | + fpsrcop = (fpsrcop < 0.0)? | ||
| 1431 | + -(floor(fabs(fpsrcop))): floor(fpsrcop); | ||
| 1432 | + ST0 -= (ST1 * fpsrcop * fptemp); | ||
| 1433 | + } | ||
| 1434 | +} | ||
| 1435 | + | ||
| 1436 | +void helper_fyl2xp1(void) | ||
| 1437 | +{ | ||
| 1438 | + CPU86_LDouble fptemp; | ||
| 1439 | + | ||
| 1440 | + fptemp = ST0; | ||
| 1441 | + if ((fptemp+1.0)>0.0) { | ||
| 1442 | + fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */ | ||
| 1443 | + ST1 *= fptemp; | ||
| 1444 | + fpop(); | ||
| 1445 | + } else { | ||
| 1446 | + env->fpus &= (~0x4700); | ||
| 1447 | + env->fpus |= 0x400; | ||
| 1448 | + } | ||
| 1449 | +} | ||
| 1450 | + | ||
| 1451 | +void helper_fsqrt(void) | ||
| 1452 | +{ | ||
| 1453 | + CPU86_LDouble fptemp; | ||
| 1454 | + | ||
| 1455 | + fptemp = ST0; | ||
| 1456 | + if (fptemp<0.0) { | ||
| 1457 | + env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */ | ||
| 1458 | + env->fpus |= 0x400; | ||
| 1459 | + } | ||
| 1460 | + ST0 = sqrt(fptemp); | ||
| 1461 | +} | ||
| 1462 | + | ||
| 1463 | +void helper_fsincos(void) | ||
| 1464 | +{ | ||
| 1465 | + CPU86_LDouble fptemp; | ||
| 1466 | + | ||
| 1467 | + fptemp = ST0; | ||
| 1468 | + if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
| 1469 | + env->fpus |= 0x400; | ||
| 1470 | + } else { | ||
| 1471 | + ST0 = sin(fptemp); | ||
| 1472 | + fpush(); | ||
| 1473 | + ST0 = cos(fptemp); | ||
| 1474 | + env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
| 1475 | + /* the above code is for |arg| < 2**63 only */ | ||
| 1476 | + } | ||
| 1477 | +} | ||
| 1478 | + | ||
| 1479 | +void helper_frndint(void) | ||
| 1480 | +{ | ||
| 1481 | + ST0 = rint(ST0); | ||
| 1482 | +} | ||
| 1483 | + | ||
| 1484 | +void helper_fscale(void) | ||
| 1485 | +{ | ||
| 1486 | + CPU86_LDouble fpsrcop, fptemp; | ||
| 1487 | + | ||
| 1488 | + fpsrcop = 2.0; | ||
| 1489 | + fptemp = pow(fpsrcop,ST1); | ||
| 1490 | + ST0 *= fptemp; | ||
| 1491 | +} | ||
| 1492 | + | ||
| 1493 | +void helper_fsin(void) | ||
| 1494 | +{ | ||
| 1495 | + CPU86_LDouble fptemp; | ||
| 1496 | + | ||
| 1497 | + fptemp = ST0; | ||
| 1498 | + if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
| 1499 | + env->fpus |= 0x400; | ||
| 1500 | + } else { | ||
| 1501 | + ST0 = sin(fptemp); | ||
| 1502 | + env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
| 1503 | + /* the above code is for |arg| < 2**53 only */ | ||
| 1504 | + } | ||
| 1505 | +} | ||
| 1506 | + | ||
| 1507 | +void helper_fcos(void) | ||
| 1508 | +{ | ||
| 1509 | + CPU86_LDouble fptemp; | ||
| 1510 | + | ||
| 1511 | + fptemp = ST0; | ||
| 1512 | + if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) { | ||
| 1513 | + env->fpus |= 0x400; | ||
| 1514 | + } else { | ||
| 1515 | + ST0 = cos(fptemp); | ||
| 1516 | + env->fpus &= (~0x400); /* C2 <-- 0 */ | ||
| 1517 | + /* the above code is for |arg5 < 2**63 only */ | ||
| 1518 | + } | ||
| 1519 | +} | ||
| 1520 | + | ||
| 1521 | +/* associated heplers to reduce generated code length and to simplify | ||
| 1522 | + relocation (FP constants are usually stored in .rodata section) */ | ||
| 1523 | + | ||
| 1524 | +void OPPROTO op_f2xm1(void) | ||
| 1525 | +{ | ||
| 1526 | + helper_f2xm1(); | ||
| 1527 | +} | ||
| 1528 | + | ||
| 1529 | +void OPPROTO op_fyl2x(void) | ||
| 1530 | +{ | ||
| 1531 | + helper_fyl2x(); | ||
| 1532 | +} | ||
| 1533 | + | ||
| 1534 | +void OPPROTO op_fptan(void) | ||
| 1535 | +{ | ||
| 1536 | + helper_fptan(); | ||
| 1537 | +} | ||
| 1538 | + | ||
| 1539 | +void OPPROTO op_fpatan(void) | ||
| 1540 | +{ | ||
| 1541 | + helper_fpatan(); | ||
| 1542 | +} | ||
| 1543 | + | ||
| 1544 | +void OPPROTO op_fxtract(void) | ||
| 1545 | +{ | ||
| 1546 | + helper_fxtract(); | ||
| 1547 | +} | ||
| 1548 | + | ||
| 1549 | +void OPPROTO op_fprem1(void) | ||
| 1550 | +{ | ||
| 1551 | + helper_fprem1(); | ||
| 1552 | +} | ||
| 1553 | + | ||
| 1554 | + | ||
| 1555 | +void OPPROTO op_fprem(void) | ||
| 1556 | +{ | ||
| 1557 | + helper_fprem(); | ||
| 1558 | +} | ||
| 1559 | + | ||
| 1560 | +void OPPROTO op_fyl2xp1(void) | ||
| 1561 | +{ | ||
| 1562 | + helper_fyl2xp1(); | ||
| 1563 | +} | ||
| 1564 | + | ||
| 1565 | +void OPPROTO op_fsqrt(void) | ||
| 1566 | +{ | ||
| 1567 | + helper_fsqrt(); | ||
| 1568 | +} | ||
| 1569 | + | ||
| 1570 | +void OPPROTO op_fsincos(void) | ||
| 1571 | +{ | ||
| 1572 | + helper_fsincos(); | ||
| 1573 | +} | ||
| 1574 | + | ||
| 1575 | +void OPPROTO op_frndint(void) | ||
| 1576 | +{ | ||
| 1577 | + helper_frndint(); | ||
| 1578 | +} | ||
| 1579 | + | ||
| 1580 | +void OPPROTO op_fscale(void) | ||
| 1581 | +{ | ||
| 1582 | + helper_fscale(); | ||
| 1583 | +} | ||
| 1584 | + | ||
| 1585 | +void OPPROTO op_fsin(void) | ||
| 1586 | +{ | ||
| 1587 | + helper_fsin(); | ||
| 1588 | +} | ||
| 1589 | + | ||
| 1590 | +void OPPROTO op_fcos(void) | ||
| 1591 | +{ | ||
| 1592 | + helper_fcos(); | ||
| 1593 | +} | ||
| 1594 | + |
translate-i386.c
| @@ -5,6 +5,7 @@ | @@ -5,6 +5,7 @@ | ||
| 5 | #include <inttypes.h> | 5 | #include <inttypes.h> |
| 6 | #include <assert.h> | 6 | #include <assert.h> |
| 7 | 7 | ||
| 8 | +#define IN_OP_I386 | ||
| 8 | #include "cpu-i386.h" | 9 | #include "cpu-i386.h" |
| 9 | 10 | ||
| 10 | static uint8_t *gen_code_ptr; | 11 | static uint8_t *gen_code_ptr; |
| @@ -39,7 +40,6 @@ typedef struct DisasContext { | @@ -39,7 +40,6 @@ typedef struct DisasContext { | ||
| 39 | int prefix; | 40 | int prefix; |
| 40 | int aflag, dflag; | 41 | int aflag, dflag; |
| 41 | uint8_t *pc; /* current pc */ | 42 | uint8_t *pc; /* current pc */ |
| 42 | - uint8_t *runtime_pc; /* current pc in the runtime generated code */ | ||
| 43 | int cc_op; /* current CC operation */ | 43 | int cc_op; /* current CC operation */ |
| 44 | int f_st; | 44 | int f_st; |
| 45 | } DisasContext; | 45 | } DisasContext; |
| @@ -68,18 +68,6 @@ enum { | @@ -68,18 +68,6 @@ enum { | ||
| 68 | OP_SAR = 7, | 68 | OP_SAR = 7, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | - | ||
| 72 | -static const int fp_ops[8] = { | ||
| 73 | -#if 0 | ||
| 74 | - OP_FADDQ, OP_FMULQ, OP_CMP, OP_CMP, | ||
| 75 | - OP_FSUBQ, OP_FSUBQ, OP_FDIVQ, OP_FDIVQ | ||
| 76 | -#endif | ||
| 77 | -}; | ||
| 78 | - | ||
| 79 | -extern char cc_table, rclw_table, rclb_table; | ||
| 80 | -extern char helper_rcll_T0_T1_cc; | ||
| 81 | -extern char __udivdi3, __umoddi3; | ||
| 82 | - | ||
| 83 | #include "op-i386.h" | 71 | #include "op-i386.h" |
| 84 | 72 | ||
| 85 | /* operand size */ | 73 | /* operand size */ |
| @@ -606,6 +594,28 @@ static GenOpFunc *gen_setcc_sub[3][8] = { | @@ -606,6 +594,28 @@ static GenOpFunc *gen_setcc_sub[3][8] = { | ||
| 606 | }, | 594 | }, |
| 607 | }; | 595 | }; |
| 608 | 596 | ||
| 597 | +static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = { | ||
| 598 | + gen_op_fadd_ST0_FT0, | ||
| 599 | + gen_op_fmul_ST0_FT0, | ||
| 600 | + gen_op_fcom_ST0_FT0, | ||
| 601 | + gen_op_fcom_ST0_FT0, | ||
| 602 | + gen_op_fsub_ST0_FT0, | ||
| 603 | + gen_op_fsubr_ST0_FT0, | ||
| 604 | + gen_op_fdiv_ST0_FT0, | ||
| 605 | + gen_op_fdivr_ST0_FT0, | ||
| 606 | +}; | ||
| 607 | + | ||
| 608 | +static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = { | ||
| 609 | + gen_op_fadd_STN_ST0, | ||
| 610 | + gen_op_fmul_STN_ST0, | ||
| 611 | + NULL, | ||
| 612 | + NULL, | ||
| 613 | + gen_op_fsub_STN_ST0, | ||
| 614 | + gen_op_fsubr_STN_ST0, | ||
| 615 | + gen_op_fdiv_STN_ST0, | ||
| 616 | + gen_op_fdivr_STN_ST0, | ||
| 617 | +}; | ||
| 618 | + | ||
| 609 | static void gen_op(DisasContext *s1, int op, int ot, int d, int s) | 619 | static void gen_op(DisasContext *s1, int op, int ot, int d, int s) |
| 610 | { | 620 | { |
| 611 | if (d != OR_TMP0) | 621 | if (d != OR_TMP0) |
| @@ -1345,12 +1355,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1345,12 +1355,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1345 | /**************************/ | 1355 | /**************************/ |
| 1346 | /* push/pop */ | 1356 | /* push/pop */ |
| 1347 | case 0x50 ... 0x57: /* push */ | 1357 | case 0x50 ... 0x57: /* push */ |
| 1348 | - gen_op_mov_TN_reg[OT_LONG][0][(b & 7)](); | 1358 | + gen_op_mov_TN_reg[OT_LONG][0][b & 7](); |
| 1349 | gen_op_pushl_T0(); | 1359 | gen_op_pushl_T0(); |
| 1350 | break; | 1360 | break; |
| 1351 | case 0x58 ... 0x5f: /* pop */ | 1361 | case 0x58 ... 0x5f: /* pop */ |
| 1352 | gen_op_popl_T0(); | 1362 | gen_op_popl_T0(); |
| 1353 | - gen_op_mov_reg_T0[OT_LONG][reg](); | 1363 | + gen_op_mov_reg_T0[OT_LONG][b & 7](); |
| 1354 | break; | 1364 | break; |
| 1355 | case 0x68: /* push Iv */ | 1365 | case 0x68: /* push Iv */ |
| 1356 | case 0x6a: | 1366 | case 0x6a: |
| @@ -1581,7 +1591,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1581,7 +1591,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1581 | 1591 | ||
| 1582 | /************************/ | 1592 | /************************/ |
| 1583 | /* floats */ | 1593 | /* floats */ |
| 1584 | -#if 0 | ||
| 1585 | case 0xd8 ... 0xdf: | 1594 | case 0xd8 ... 0xdf: |
| 1586 | modrm = ldub(s->pc++); | 1595 | modrm = ldub(s->pc++); |
| 1587 | mod = (modrm >> 6) & 3; | 1596 | mod = (modrm >> 6) & 3; |
| @@ -1597,52 +1606,29 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1597,52 +1606,29 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1597 | case 0x20 ... 0x27: /* fxxxl */ | 1606 | case 0x20 ... 0x27: /* fxxxl */ |
| 1598 | case 0x30 ... 0x37: /* fixxx */ | 1607 | case 0x30 ... 0x37: /* fixxx */ |
| 1599 | { | 1608 | { |
| 1600 | - int op1, swap; | ||
| 1601 | - op1 = fp_ops[op & 7]; | ||
| 1602 | - | ||
| 1603 | - swap = 0; | ||
| 1604 | - if ((op & 7) == 5 || (op & 7) == 7) | ||
| 1605 | - swap = 1; | 1609 | + int op1; |
| 1610 | + op1 = op & 7; | ||
| 1606 | 1611 | ||
| 1607 | switch(op >> 4) { | 1612 | switch(op >> 4) { |
| 1608 | case 0: | 1613 | case 0: |
| 1609 | - ot = OT_LONG; | ||
| 1610 | - is_int = 0; | 1614 | + gen_op_flds_FT0_A0(); |
| 1611 | break; | 1615 | break; |
| 1612 | case 1: | 1616 | case 1: |
| 1613 | - ot = OT_LONG; | ||
| 1614 | - is_int = 1; | 1617 | + gen_op_fildl_FT0_A0(); |
| 1615 | break; | 1618 | break; |
| 1616 | case 2: | 1619 | case 2: |
| 1617 | - ot = OT_QUAD; | ||
| 1618 | - is_int = 0; | 1620 | + gen_op_fldl_FT0_A0(); |
| 1619 | break; | 1621 | break; |
| 1620 | case 3: | 1622 | case 3: |
| 1621 | default: | 1623 | default: |
| 1622 | - ot = OT_WORD; | ||
| 1623 | - is_int = 1; | 1624 | + gen_op_fild_FT0_A0(); |
| 1624 | break; | 1625 | break; |
| 1625 | } | 1626 | } |
| 1626 | 1627 | ||
| 1627 | - /* if integer, needs to convert to float */ | ||
| 1628 | - if (is_int) { | ||
| 1629 | - /* XXX: potential loss of precision if large integer */ | ||
| 1630 | - gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr); | ||
| 1631 | - gen_insn2(OP_I2FL, OR_FTMP0, OR_TMP0); | ||
| 1632 | - } else { | ||
| 1633 | - gen_ld(OP_LDUB + ot, OR_FTMP0, reg_addr, offset_addr); | ||
| 1634 | - } | ||
| 1635 | - if (ot != OT_QUAD) | ||
| 1636 | - op1 += OP_FADDL - OP_FADDQ; | ||
| 1637 | - | ||
| 1638 | - if (!swap) | ||
| 1639 | - gen_insn3(op1, OR_ST0, OR_ST0, OR_FTMP0); | ||
| 1640 | - else | ||
| 1641 | - gen_insn3(op1, OR_ST0, OR_FTMP0, OR_ST0); | ||
| 1642 | - | ||
| 1643 | - if ((op & 7) == 3) { | 1628 | + gen_op_fp_arith_ST0_FT0[op1](); |
| 1629 | + if (op1 == 3) { | ||
| 1644 | /* fcomp needs pop */ | 1630 | /* fcomp needs pop */ |
| 1645 | - gen_insn0(OP_FPOP); | 1631 | + gen_op_fpop(); |
| 1646 | } | 1632 | } |
| 1647 | } | 1633 | } |
| 1648 | break; | 1634 | break; |
| @@ -1659,49 +1645,47 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1659,49 +1645,47 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1659 | case 0x3a: /* fists */ | 1645 | case 0x3a: /* fists */ |
| 1660 | case 0x3b: /* fistps */ | 1646 | case 0x3b: /* fistps */ |
| 1661 | 1647 | ||
| 1662 | - switch(op >> 4) { | ||
| 1663 | - case 0: | ||
| 1664 | - ot = OT_LONG; | ||
| 1665 | - is_int = 0; | ||
| 1666 | - break; | ||
| 1667 | - case 1: | ||
| 1668 | - ot = OT_LONG; | ||
| 1669 | - is_int = 1; | ||
| 1670 | - break; | ||
| 1671 | - case 2: | ||
| 1672 | - ot = OT_QUAD; | ||
| 1673 | - is_int = 0; | ||
| 1674 | - break; | ||
| 1675 | - case 3: | ||
| 1676 | - default: | ||
| 1677 | - ot = OT_WORD; | ||
| 1678 | - is_int = 1; | ||
| 1679 | - break; | ||
| 1680 | - } | ||
| 1681 | - | ||
| 1682 | switch(op & 7) { | 1648 | switch(op & 7) { |
| 1683 | case 0: | 1649 | case 0: |
| 1684 | - gen_insn0(OP_FPUSH); | ||
| 1685 | - if (is_int) { | ||
| 1686 | - /* XXX: potential loss of precision */ | ||
| 1687 | - gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr); | ||
| 1688 | - gen_insn2(OP_I2FL, OR_ST0, OR_TMP0); | ||
| 1689 | - } else { | ||
| 1690 | - gen_ld(OP_LDUB + ot, OR_ST0, reg_addr, offset_addr); | 1650 | + gen_op_fpush(); |
| 1651 | + switch(op >> 4) { | ||
| 1652 | + case 0: | ||
| 1653 | + gen_op_flds_ST0_A0(); | ||
| 1654 | + break; | ||
| 1655 | + case 1: | ||
| 1656 | + gen_op_fildl_ST0_A0(); | ||
| 1657 | + break; | ||
| 1658 | + case 2: | ||
| 1659 | + gen_op_fldl_ST0_A0(); | ||
| 1660 | + break; | ||
| 1661 | + case 3: | ||
| 1662 | + default: | ||
| 1663 | + gen_op_fild_ST0_A0(); | ||
| 1664 | + break; | ||
| 1691 | } | 1665 | } |
| 1692 | break; | 1666 | break; |
| 1693 | default: | 1667 | default: |
| 1694 | - if (is_int) { | ||
| 1695 | - gen_insn2(OP_F2IL, OR_TMP0, OR_ST0); | ||
| 1696 | - gen_st(OP_STB + ot, OR_TMP0, reg_addr, offset_addr); | ||
| 1697 | - } else { | ||
| 1698 | - gen_st(OP_STB + ot, OR_ST0, reg_addr, offset_addr); | 1668 | + switch(op >> 4) { |
| 1669 | + case 0: | ||
| 1670 | + gen_op_fsts_ST0_A0(); | ||
| 1671 | + break; | ||
| 1672 | + case 1: | ||
| 1673 | + gen_op_fistl_ST0_A0(); | ||
| 1674 | + break; | ||
| 1675 | + case 2: | ||
| 1676 | + gen_op_fstl_ST0_A0(); | ||
| 1677 | + break; | ||
| 1678 | + case 3: | ||
| 1679 | + default: | ||
| 1680 | + gen_op_fist_ST0_A0(); | ||
| 1681 | + break; | ||
| 1699 | } | 1682 | } |
| 1700 | if ((op & 7) == 3) | 1683 | if ((op & 7) == 3) |
| 1701 | - gen_insn0(OP_FPOP); | 1684 | + gen_op_fpop(); |
| 1702 | break; | 1685 | break; |
| 1703 | } | 1686 | } |
| 1704 | break; | 1687 | break; |
| 1688 | +#if 0 | ||
| 1705 | case 0x2f: /* fnstsw mem */ | 1689 | case 0x2f: /* fnstsw mem */ |
| 1706 | gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO); | 1690 | gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO); |
| 1707 | gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr); | 1691 | gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr); |
| @@ -1711,15 +1695,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1711,15 +1695,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1711 | case 0x3e: /* fbstp */ | 1695 | case 0x3e: /* fbstp */ |
| 1712 | error("float BCD not hanlded"); | 1696 | error("float BCD not hanlded"); |
| 1713 | return -1; | 1697 | return -1; |
| 1698 | +#endif | ||
| 1714 | case 0x3d: /* fildll */ | 1699 | case 0x3d: /* fildll */ |
| 1715 | - gen_insn0(OP_FPUSH); | ||
| 1716 | - gen_ld(OP_LDQ, OR_TMP0, reg_addr, offset_addr); | ||
| 1717 | - gen_insn2(OP_I2FQ, OR_ST0, OR_TMP0); | 1700 | + gen_op_fpush(); |
| 1701 | + gen_op_fildll_ST0_A0(); | ||
| 1718 | break; | 1702 | break; |
| 1719 | case 0x3f: /* fistpll */ | 1703 | case 0x3f: /* fistpll */ |
| 1720 | - gen_insn2(OP_F2IQ, OR_TMP0, OR_ST0); | ||
| 1721 | - gen_st(OP_STQ, OR_TMP0, reg_addr, offset_addr); | ||
| 1722 | - gen_insn0(OP_FPOP); | 1704 | + gen_op_fistll_ST0_A0(); |
| 1705 | + gen_op_fpop(); | ||
| 1723 | break; | 1706 | break; |
| 1724 | default: | 1707 | default: |
| 1725 | error("unhandled memory FP\n"); | 1708 | error("unhandled memory FP\n"); |
| @@ -1727,22 +1710,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1727,22 +1710,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1727 | } | 1710 | } |
| 1728 | } else { | 1711 | } else { |
| 1729 | /* register float ops */ | 1712 | /* register float ops */ |
| 1730 | - opreg = rm + OR_ST0; | 1713 | + opreg = rm; |
| 1731 | 1714 | ||
| 1732 | switch(op) { | 1715 | switch(op) { |
| 1733 | case 0x08: /* fld sti */ | 1716 | case 0x08: /* fld sti */ |
| 1734 | - gen_insn0(OP_FPUSH); | ||
| 1735 | - gen_mov(OR_ST0, OR_ST0 + ((rm + 1) & 7)); | 1717 | + gen_op_fpush(); |
| 1718 | + gen_op_fmov_ST0_STN((opreg + 1) & 7); | ||
| 1736 | break; | 1719 | break; |
| 1737 | case 0x09: /* fxchg sti */ | 1720 | case 0x09: /* fxchg sti */ |
| 1738 | - gen_mov(OR_TMP0, OR_ST0); | ||
| 1739 | - gen_mov(OR_ST0, opreg); | ||
| 1740 | - gen_mov(opreg, OR_TMP0); | 1721 | + gen_op_fxchg_ST0_STN((opreg + 1) & 7); |
| 1741 | break; | 1722 | break; |
| 1742 | case 0x0a: /* grp d9/2 */ | 1723 | case 0x0a: /* grp d9/2 */ |
| 1743 | switch(rm) { | 1724 | switch(rm) { |
| 1744 | case 0: /* fnop */ | 1725 | case 0: /* fnop */ |
| 1745 | - gen_insn0(OP_NOP); | ||
| 1746 | break; | 1726 | break; |
| 1747 | default: | 1727 | default: |
| 1748 | error("unhandled FP GRP d9/2\n"); | 1728 | error("unhandled FP GRP d9/2\n"); |
| @@ -1752,16 +1732,17 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1752,16 +1732,17 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1752 | case 0x0c: /* grp d9/4 */ | 1732 | case 0x0c: /* grp d9/4 */ |
| 1753 | switch(rm) { | 1733 | switch(rm) { |
| 1754 | case 0: /* fchs */ | 1734 | case 0: /* fchs */ |
| 1755 | - gen_insn3(OP_FSUBQ, OR_ST0, OR_ZERO, OR_ST0); | 1735 | + gen_op_fchs_ST0(); |
| 1756 | break; | 1736 | break; |
| 1757 | case 1: /* fabs */ | 1737 | case 1: /* fabs */ |
| 1758 | - gen_insn2(OP_FABSQ, OR_ST0, OR_ST0); | 1738 | + gen_op_fabs_ST0(); |
| 1759 | break; | 1739 | break; |
| 1760 | case 4: /* ftst */ | 1740 | case 4: /* ftst */ |
| 1761 | - gen_insn3(OP_CMP, OR_ZERO, OR_ST0, OR_ZERO); | 1741 | + gen_op_fldz_FT0(); |
| 1742 | + gen_op_fcom_ST0_FT0(); | ||
| 1762 | break; | 1743 | break; |
| 1763 | case 5: /* fxam */ | 1744 | case 5: /* fxam */ |
| 1764 | - gen_insn3(OP_FSPECIAL, OR_ZERO, OR_ST0, OR_ZERO); | 1745 | + gen_op_fxam_ST0(); |
| 1765 | break; | 1746 | break; |
| 1766 | default: | 1747 | default: |
| 1767 | return -1; | 1748 | return -1; |
| @@ -1769,76 +1750,88 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1769,76 +1750,88 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1769 | break; | 1750 | break; |
| 1770 | case 0x0d: /* grp d9/5 */ | 1751 | case 0x0d: /* grp d9/5 */ |
| 1771 | { | 1752 | { |
| 1772 | - if (rm == 7) { | ||
| 1773 | - error("bad GRP d9/5"); | 1753 | + switch(rm) { |
| 1754 | + case 0: | ||
| 1755 | + gen_op_fld1_ST0(); | ||
| 1756 | + break; | ||
| 1757 | + case 1: | ||
| 1758 | + gen_op_fld2t_ST0(); | ||
| 1759 | + break; | ||
| 1760 | + case 2: | ||
| 1761 | + gen_op_fld2e_ST0(); | ||
| 1762 | + break; | ||
| 1763 | + case 3: | ||
| 1764 | + gen_op_fldpi_ST0(); | ||
| 1765 | + break; | ||
| 1766 | + case 4: | ||
| 1767 | + gen_op_fldlg2_ST0(); | ||
| 1768 | + break; | ||
| 1769 | + case 5: | ||
| 1770 | + gen_op_fldln2_ST0(); | ||
| 1771 | + break; | ||
| 1772 | + case 6: | ||
| 1773 | + gen_op_fldz_ST0(); | ||
| 1774 | + break; | ||
| 1775 | + default: | ||
| 1774 | return -1; | 1776 | return -1; |
| 1775 | } | 1777 | } |
| 1776 | - /* XXX: needs constant load or symbol table */ | ||
| 1777 | - gen_insn0(OP_FPUSH); | ||
| 1778 | - gen_ld(OP_LDQ, OR_ST0, OR_ZERO, | ||
| 1779 | - (rm * 8) + FLOAT_CONST_ADDR); | ||
| 1780 | } | 1778 | } |
| 1781 | break; | 1779 | break; |
| 1782 | case 0x0e: /* grp d9/6 */ | 1780 | case 0x0e: /* grp d9/6 */ |
| 1783 | switch(rm) { | 1781 | switch(rm) { |
| 1784 | case 0: /* f2xm1 */ | 1782 | case 0: /* f2xm1 */ |
| 1785 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO); | 1783 | + gen_op_f2xm1(); |
| 1786 | break; | 1784 | break; |
| 1787 | case 1: /* fyl2x */ | 1785 | case 1: /* fyl2x */ |
| 1788 | - gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1); | ||
| 1789 | - gen_insn0(OP_FPOP); | 1786 | + gen_op_fyl2x(); |
| 1790 | break; | 1787 | break; |
| 1791 | case 2: /* fptan */ | 1788 | case 2: /* fptan */ |
| 1792 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO); | ||
| 1793 | - gen_insn0(OP_FPUSH); | ||
| 1794 | - /* load one */ | ||
| 1795 | - gen_ld(OP_LDQ, OR_ST0, OR_ZERO, | ||
| 1796 | - (0 * 8) + FLOAT_CONST_ADDR); | 1789 | + gen_op_fptan(); |
| 1797 | break; | 1790 | break; |
| 1798 | case 3: /* fpatan */ | 1791 | case 3: /* fpatan */ |
| 1799 | - gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1); | ||
| 1800 | - gen_insn0(OP_FPOP); | 1792 | + gen_op_fpatan(); |
| 1801 | break; | 1793 | break; |
| 1802 | case 4: /* fxtract */ | 1794 | case 4: /* fxtract */ |
| 1803 | - gen_insn0(OP_FPUSH); | ||
| 1804 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO); | ||
| 1805 | - gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO); | 1795 | + gen_op_fxtract(); |
| 1806 | break; | 1796 | break; |
| 1807 | case 5: /* fprem1 */ | 1797 | case 5: /* fprem1 */ |
| 1808 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1); | 1798 | + gen_op_fprem1(); |
| 1809 | break; | 1799 | break; |
| 1810 | case 6: /* fdecstp */ | 1800 | case 6: /* fdecstp */ |
| 1811 | - gen_insn0(OP_FPUSH); | 1801 | + gen_op_fdecstp(); |
| 1812 | break; | 1802 | break; |
| 1813 | default: | 1803 | default: |
| 1814 | - case 7: /* fdecstp */ | ||
| 1815 | - gen_insn0(OP_FPOP); | 1804 | + case 7: /* fincstp */ |
| 1805 | + gen_op_fincstp(); | ||
| 1816 | break; | 1806 | break; |
| 1817 | } | 1807 | } |
| 1818 | break; | 1808 | break; |
| 1819 | case 0x0f: /* grp d9/7 */ | 1809 | case 0x0f: /* grp d9/7 */ |
| 1820 | switch(rm) { | 1810 | switch(rm) { |
| 1821 | case 0: /* fprem */ | 1811 | case 0: /* fprem */ |
| 1822 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1); | 1812 | + gen_op_fprem(); |
| 1823 | break; | 1813 | break; |
| 1824 | case 1: /* fyl2xp1 */ | 1814 | case 1: /* fyl2xp1 */ |
| 1825 | - gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1); | ||
| 1826 | - gen_insn0(OP_FPOP); | 1815 | + gen_op_fyl2xp1(); |
| 1816 | + break; | ||
| 1817 | + case 2: /* fsqrt */ | ||
| 1818 | + gen_op_fsqrt(); | ||
| 1827 | break; | 1819 | break; |
| 1828 | case 3: /* fsincos */ | 1820 | case 3: /* fsincos */ |
| 1829 | - gen_insn0(OP_FPUSH); | ||
| 1830 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO); | ||
| 1831 | - gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO); | 1821 | + gen_op_fsincos(); |
| 1832 | break; | 1822 | break; |
| 1833 | case 5: /* fscale */ | 1823 | case 5: /* fscale */ |
| 1834 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1); | 1824 | + gen_op_fscale(); |
| 1835 | break; | 1825 | break; |
| 1836 | - case 2: /* fsqrt */ | ||
| 1837 | case 4: /* frndint */ | 1826 | case 4: /* frndint */ |
| 1827 | + gen_op_frndint(); | ||
| 1828 | + break; | ||
| 1838 | case 6: /* fsin */ | 1829 | case 6: /* fsin */ |
| 1830 | + gen_op_fsin(); | ||
| 1831 | + break; | ||
| 1839 | default: | 1832 | default: |
| 1840 | case 7: /* fcos */ | 1833 | case 7: /* fcos */ |
| 1841 | - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO); | 1834 | + gen_op_fcos(); |
| 1842 | break; | 1835 | break; |
| 1843 | } | 1836 | } |
| 1844 | break; | 1837 | break; |
| @@ -1846,58 +1839,54 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1846,58 +1839,54 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1846 | case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ | 1839 | case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */ |
| 1847 | case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ | 1840 | case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */ |
| 1848 | { | 1841 | { |
| 1849 | - int op1, swap; | 1842 | + int op1; |
| 1850 | 1843 | ||
| 1851 | - op1 = fp_ops[op & 7]; | ||
| 1852 | - swap = 0; | ||
| 1853 | - if ((op & 7) == 5 || (op & 7) == 7) | ||
| 1854 | - swap = 1; | 1844 | + op1 = op & 7; |
| 1855 | if (op >= 0x20) { | 1845 | if (op >= 0x20) { |
| 1856 | - if (swap) | ||
| 1857 | - gen_insn3(op1, opreg, OR_ST0, opreg); | ||
| 1858 | - else | ||
| 1859 | - gen_insn3(op1, opreg, opreg, OR_ST0); | 1846 | + gen_op_fp_arith_STN_ST0[op1](opreg); |
| 1860 | } else { | 1847 | } else { |
| 1861 | - if (swap) | ||
| 1862 | - gen_insn3(op1, OR_ST0, opreg, OR_ST0); | ||
| 1863 | - else | ||
| 1864 | - gen_insn3(op1, OR_ST0, OR_ST0, opreg); | 1848 | + gen_op_fmov_FT0_STN(opreg); |
| 1849 | + gen_op_fp_arith_ST0_FT0[op1](); | ||
| 1865 | } | 1850 | } |
| 1866 | if (op >= 0x30) | 1851 | if (op >= 0x30) |
| 1867 | - gen_insn0(OP_FPOP); | 1852 | + gen_op_fpop(); |
| 1868 | } | 1853 | } |
| 1869 | break; | 1854 | break; |
| 1870 | case 0x02: /* fcom */ | 1855 | case 0x02: /* fcom */ |
| 1871 | - gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg); | 1856 | + gen_op_fmov_FT0_STN(opreg); |
| 1857 | + gen_op_fcom_ST0_FT0(); | ||
| 1872 | break; | 1858 | break; |
| 1873 | case 0x03: /* fcomp */ | 1859 | case 0x03: /* fcomp */ |
| 1874 | - gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg); | ||
| 1875 | - gen_insn0(OP_FPOP); | 1860 | + gen_op_fmov_FT0_STN(opreg); |
| 1861 | + gen_op_fcom_ST0_FT0(); | ||
| 1862 | + gen_op_fpop(); | ||
| 1876 | break; | 1863 | break; |
| 1877 | case 0x15: /* da/5 */ | 1864 | case 0x15: /* da/5 */ |
| 1878 | switch(rm) { | 1865 | switch(rm) { |
| 1879 | case 1: /* fucompp */ | 1866 | case 1: /* fucompp */ |
| 1880 | - gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg); | ||
| 1881 | - gen_insn0(OP_FPOP); | ||
| 1882 | - gen_insn0(OP_FPOP); | 1867 | + gen_op_fmov_FT0_STN(1); |
| 1868 | + gen_op_fcom_ST0_FT0(); | ||
| 1869 | + gen_op_fpop(); | ||
| 1870 | + gen_op_fpop(); | ||
| 1883 | break; | 1871 | break; |
| 1884 | default: | 1872 | default: |
| 1885 | return -1; | 1873 | return -1; |
| 1886 | } | 1874 | } |
| 1887 | break; | 1875 | break; |
| 1888 | case 0x2a: /* fst sti */ | 1876 | case 0x2a: /* fst sti */ |
| 1889 | - gen_mov(opreg, OR_ST0); | 1877 | + gen_op_fmov_STN_ST0(opreg); |
| 1890 | break; | 1878 | break; |
| 1891 | case 0x2b: /* fstp sti */ | 1879 | case 0x2b: /* fstp sti */ |
| 1892 | - gen_mov(opreg, OR_ST0); | ||
| 1893 | - gen_insn0(OP_FPOP); | 1880 | + gen_op_fmov_STN_ST0(opreg); |
| 1881 | + gen_op_fpop(); | ||
| 1894 | break; | 1882 | break; |
| 1895 | case 0x33: /* de/3 */ | 1883 | case 0x33: /* de/3 */ |
| 1896 | switch(rm) { | 1884 | switch(rm) { |
| 1897 | case 1: /* fcompp */ | 1885 | case 1: /* fcompp */ |
| 1898 | - gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg); | ||
| 1899 | - gen_insn0(OP_FPOP); | ||
| 1900 | - gen_insn0(OP_FPOP); | 1886 | + gen_op_fmov_FT0_STN(1); |
| 1887 | + gen_op_fcom_ST0_FT0(); | ||
| 1888 | + gen_op_fpop(); | ||
| 1889 | + gen_op_fpop(); | ||
| 1901 | break; | 1890 | break; |
| 1902 | default: | 1891 | default: |
| 1903 | return -1; | 1892 | return -1; |
| @@ -1905,9 +1894,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1905,9 +1894,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1905 | break; | 1894 | break; |
| 1906 | case 0x3c: /* df/4 */ | 1895 | case 0x3c: /* df/4 */ |
| 1907 | switch(rm) { | 1896 | switch(rm) { |
| 1897 | +#if 0 | ||
| 1908 | case 0: | 1898 | case 0: |
| 1909 | gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO); | 1899 | gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO); |
| 1910 | break; | 1900 | break; |
| 1901 | +#endif | ||
| 1911 | default: | 1902 | default: |
| 1912 | return -1; | 1903 | return -1; |
| 1913 | } | 1904 | } |
| @@ -1918,7 +1909,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -1918,7 +1909,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 1918 | } | 1909 | } |
| 1919 | } | 1910 | } |
| 1920 | break; | 1911 | break; |
| 1921 | -#endif | ||
| 1922 | /************************/ | 1912 | /************************/ |
| 1923 | /* string ops */ | 1913 | /* string ops */ |
| 1924 | case 0xa4: /* movsS */ | 1914 | case 0xa4: /* movsS */ |