Revision 927f621e

b/Makefile
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 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 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 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 $@ $<
b/TODO
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)
b/cpu-i386.h
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 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 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 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 */
b/dyngen.c
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 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
        }
b/op-i386.c
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 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 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

  
b/translate-i386.c
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 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 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 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 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 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 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 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 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 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 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 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 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 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 1909
            }
1919 1910
        }
1920 1911
        break;
1921
#endif
1922 1912
        /************************/
1923 1913
        /* string ops */
1924 1914
    case 0xa4: /* movsS */

Also available in: Unified diff