Commit 927f621e7960d3fcf51eecf65ee19b1aafc102ae

Authored by bellard
1 parent 367e86e8

added float support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@15 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
... ... @@ -8,6 +8,7 @@ LDFLAGS=-g
8 8 LIBS=
9 9 CC=gcc
10 10 DEFINES=-DHAVE_BYTESWAP_H
  11 +OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2
11 12 endif
12 13  
13 14 ifeq ($(ARCH),ppc)
... ... @@ -24,6 +25,7 @@ CRTEND=$(GCC_LIBS_DIR)/crtend.o
24 25 LDFLAGS=-static -g -nostdlib $(CRT1) $(CRTI) $(CRTBEGIN)
25 26 LIBS=-L$(LIBS_DIR) -ltinyc -lgcc $(CRTEND) $(CRTN)
26 27 DEFINES=-Dsocklen_t=int
  28 +OP_CFLAGS=$(CFLAGS)
27 29 endif
28 30  
29 31 #########################################################
... ... @@ -31,7 +33,7 @@ endif
31 33 DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS
32 34 DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
33 35 LDSCRIPT=$(ARCH).ld
34   -LIBS+=-ldl
  36 +LIBS+=-ldl -lm
35 37  
36 38 OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
37 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 69 ./dyngen -o $@ $<
68 70  
69 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 74 %.o: %.c
73 75 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
... ...
... ... @@ -3,3 +3,4 @@
3 3 - threads
4 4 - fix printf for doubles (fp87.c bug ?)
5 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 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 88 typedef struct CPU86State {
79 89 /* standard registers */
80 90 uint32_t regs[8];
... ... @@ -91,10 +101,18 @@ typedef struct CPU86State {
91 101 uint8_t *segs_base[6];
92 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 111 /* emulator internal variables */
95 112 uint32_t t0; /* temporary t0 storage */
96 113 uint32_t t1; /* temporary t1 storage */
97 114 uint32_t a0; /* temporary a0 storage (address) */
  115 + CPU86_LDouble ft0;
98 116 } CPU86State;
99 117  
100 118 static inline int ldub(void *ptr)
... ... @@ -122,6 +140,10 @@ static inline int ldl(void *ptr)
122 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 148 static inline void stb(void *ptr, int v)
127 149 {
... ... @@ -138,11 +160,40 @@ static inline void stl(void *ptr, int v)
138 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 191 void port_outb(int addr, int val);
142 192 void port_outw(int addr, int val);
143 193 void port_outl(int addr, int val);
144 194 int port_inb(int addr);
145 195 int port_inw(int addr);
146 196 int port_inl(int addr);
  197 +#endif
147 198  
148 199 #endif /* CPU_I386_H */
... ...
dyngen.c
... ... @@ -243,6 +243,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
243 243 if (n >= MAX_ARGS)
244 244 error("too many arguments in %s", name);
245 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 259 if (n >= MAX_ARGS)
258 260 error("too many arguments in %s", name);
259 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(&quot;l3&quot;);
66 66  
67 67 #define CC_SRC (env->cc_src)
68 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 77 extern int __op_param1, __op_param2, __op_param3;
72 78 #define PARAM1 ((long)(&__op_param1))
... ... @@ -133,6 +139,44 @@ const uint8_t rclb_table[32] = {
133 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 180 /* n must be a constant to be efficient */
137 181 static inline int lshift(int x, int n)
138 182 {
... ... @@ -866,3 +910,685 @@ CCTable cc_table[CC_OP_NB] = {
866 910 [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw },
867 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 5 #include <inttypes.h>
6 6 #include <assert.h>
7 7  
  8 +#define IN_OP_I386
8 9 #include "cpu-i386.h"
9 10  
10 11 static uint8_t *gen_code_ptr;
... ... @@ -39,7 +40,6 @@ typedef struct DisasContext {
39 40 int prefix;
40 41 int aflag, dflag;
41 42 uint8_t *pc; /* current pc */
42   - uint8_t *runtime_pc; /* current pc in the runtime generated code */
43 43 int cc_op; /* current CC operation */
44 44 int f_st;
45 45 } DisasContext;
... ... @@ -68,18 +68,6 @@ enum {
68 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 71 #include "op-i386.h"
84 72  
85 73 /* operand size */
... ... @@ -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 619 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
610 620 {
611 621 if (d != OR_TMP0)
... ... @@ -1345,12 +1355,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1345 1355 /**************************/
1346 1356 /* push/pop */
1347 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 1359 gen_op_pushl_T0();
1350 1360 break;
1351 1361 case 0x58 ... 0x5f: /* pop */
1352 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 1364 break;
1355 1365 case 0x68: /* push Iv */
1356 1366 case 0x6a:
... ... @@ -1581,7 +1591,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1581 1591  
1582 1592 /************************/
1583 1593 /* floats */
1584   -#if 0
1585 1594 case 0xd8 ... 0xdf:
1586 1595 modrm = ldub(s->pc++);
1587 1596 mod = (modrm >> 6) & 3;
... ... @@ -1597,52 +1606,29 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1597 1606 case 0x20 ... 0x27: /* fxxxl */
1598 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 1612 switch(op >> 4) {
1608 1613 case 0:
1609   - ot = OT_LONG;
1610   - is_int = 0;
  1614 + gen_op_flds_FT0_A0();
1611 1615 break;
1612 1616 case 1:
1613   - ot = OT_LONG;
1614   - is_int = 1;
  1617 + gen_op_fildl_FT0_A0();
1615 1618 break;
1616 1619 case 2:
1617   - ot = OT_QUAD;
1618   - is_int = 0;
  1620 + gen_op_fldl_FT0_A0();
1619 1621 break;
1620 1622 case 3:
1621 1623 default:
1622   - ot = OT_WORD;
1623   - is_int = 1;
  1624 + gen_op_fild_FT0_A0();
1624 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 1630 /* fcomp needs pop */
1645   - gen_insn0(OP_FPOP);
  1631 + gen_op_fpop();
1646 1632 }
1647 1633 }
1648 1634 break;
... ... @@ -1659,49 +1645,47 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1659 1645 case 0x3a: /* fists */
1660 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 1648 switch(op & 7) {
1683 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 1666 break;
1693 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 1683 if ((op & 7) == 3)
1701   - gen_insn0(OP_FPOP);
  1684 + gen_op_fpop();
1702 1685 break;
1703 1686 }
1704 1687 break;
  1688 +#if 0
1705 1689 case 0x2f: /* fnstsw mem */
1706 1690 gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
1707 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 1695 case 0x3e: /* fbstp */
1712 1696 error("float BCD not hanlded");
1713 1697 return -1;
  1698 +#endif
1714 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 1702 break;
1719 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 1706 break;
1724 1707 default:
1725 1708 error("unhandled memory FP\n");
... ... @@ -1727,22 +1710,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1727 1710 }
1728 1711 } else {
1729 1712 /* register float ops */
1730   - opreg = rm + OR_ST0;
  1713 + opreg = rm;
1731 1714  
1732 1715 switch(op) {
1733 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 1719 break;
1737 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 1722 break;
1742 1723 case 0x0a: /* grp d9/2 */
1743 1724 switch(rm) {
1744 1725 case 0: /* fnop */
1745   - gen_insn0(OP_NOP);
1746 1726 break;
1747 1727 default:
1748 1728 error("unhandled FP GRP d9/2\n");
... ... @@ -1752,16 +1732,17 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1752 1732 case 0x0c: /* grp d9/4 */
1753 1733 switch(rm) {
1754 1734 case 0: /* fchs */
1755   - gen_insn3(OP_FSUBQ, OR_ST0, OR_ZERO, OR_ST0);
  1735 + gen_op_fchs_ST0();
1756 1736 break;
1757 1737 case 1: /* fabs */
1758   - gen_insn2(OP_FABSQ, OR_ST0, OR_ST0);
  1738 + gen_op_fabs_ST0();
1759 1739 break;
1760 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 1743 break;
1763 1744 case 5: /* fxam */
1764   - gen_insn3(OP_FSPECIAL, OR_ZERO, OR_ST0, OR_ZERO);
  1745 + gen_op_fxam_ST0();
1765 1746 break;
1766 1747 default:
1767 1748 return -1;
... ... @@ -1769,76 +1750,88 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1769 1750 break;
1770 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 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 1779 break;
1782 1780 case 0x0e: /* grp d9/6 */
1783 1781 switch(rm) {
1784 1782 case 0: /* f2xm1 */
1785   - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
  1783 + gen_op_f2xm1();
1786 1784 break;
1787 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 1787 break;
1791 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 1790 break;
1798 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 1793 break;
1802 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 1796 break;
1807 1797 case 5: /* fprem1 */
1808   - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
  1798 + gen_op_fprem1();
1809 1799 break;
1810 1800 case 6: /* fdecstp */
1811   - gen_insn0(OP_FPUSH);
  1801 + gen_op_fdecstp();
1812 1802 break;
1813 1803 default:
1814   - case 7: /* fdecstp */
1815   - gen_insn0(OP_FPOP);
  1804 + case 7: /* fincstp */
  1805 + gen_op_fincstp();
1816 1806 break;
1817 1807 }
1818 1808 break;
1819 1809 case 0x0f: /* grp d9/7 */
1820 1810 switch(rm) {
1821 1811 case 0: /* fprem */
1822   - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
  1812 + gen_op_fprem();
1823 1813 break;
1824 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 1819 break;
1828 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 1822 break;
1833 1823 case 5: /* fscale */
1834   - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1);
  1824 + gen_op_fscale();
1835 1825 break;
1836   - case 2: /* fsqrt */
1837 1826 case 4: /* frndint */
  1827 + gen_op_frndint();
  1828 + break;
1838 1829 case 6: /* fsin */
  1830 + gen_op_fsin();
  1831 + break;
1839 1832 default:
1840 1833 case 7: /* fcos */
1841   - gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
  1834 + gen_op_fcos();
1842 1835 break;
1843 1836 }
1844 1837 break;
... ... @@ -1846,58 +1839,54 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1846 1839 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
1847 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 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 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 1851 if (op >= 0x30)
1867   - gen_insn0(OP_FPOP);
  1852 + gen_op_fpop();
1868 1853 }
1869 1854 break;
1870 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 1858 break;
1873 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 1863 break;
1877 1864 case 0x15: /* da/5 */
1878 1865 switch(rm) {
1879 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 1871 break;
1884 1872 default:
1885 1873 return -1;
1886 1874 }
1887 1875 break;
1888 1876 case 0x2a: /* fst sti */
1889   - gen_mov(opreg, OR_ST0);
  1877 + gen_op_fmov_STN_ST0(opreg);
1890 1878 break;
1891 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 1882 break;
1895 1883 case 0x33: /* de/3 */
1896 1884 switch(rm) {
1897 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 1890 break;
1902 1891 default:
1903 1892 return -1;
... ... @@ -1905,9 +1894,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1905 1894 break;
1906 1895 case 0x3c: /* df/4 */
1907 1896 switch(rm) {
  1897 +#if 0
1908 1898 case 0:
1909 1899 gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
1910 1900 break;
  1901 +#endif
1911 1902 default:
1912 1903 return -1;
1913 1904 }
... ... @@ -1918,7 +1909,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
1918 1909 }
1919 1910 }
1920 1911 break;
1921   -#endif
1922 1912 /************************/
1923 1913 /* string ops */
1924 1914 case 0xa4: /* movsS */
... ...