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 */ |