Revision 8422b113
b/target-i386/exec.h | ||
---|---|---|
325 | 325 |
#define floatx_abs floatx80_abs |
326 | 326 |
#define floatx_chs floatx80_chs |
327 | 327 |
#define floatx_round_to_int floatx80_round_to_int |
328 |
#define floatx_compare floatx80_compare |
|
329 |
#define floatx_compare_quiet floatx80_compare_quiet |
|
328 | 330 |
#define sin sinl |
329 | 331 |
#define cos cosl |
330 | 332 |
#define sqrt sqrtl |
... | ... | |
340 | 342 |
#define floatx_abs float64_abs |
341 | 343 |
#define floatx_chs float64_chs |
342 | 344 |
#define floatx_round_to_int float64_round_to_int |
345 |
#define floatx_compare float64_compare |
|
346 |
#define floatx_compare_quiet float64_compare_quiet |
|
343 | 347 |
#endif |
344 | 348 |
|
345 | 349 |
extern CPU86_LDouble sin(CPU86_LDouble x); |
... | ... | |
547 | 551 |
void save_native_fp_state(CPUState *env); |
548 | 552 |
float approx_rsqrt(float a); |
549 | 553 |
float approx_rcp(float a); |
550 |
double helper_sqrt(double a); |
|
551 |
int fpu_isnan(double a); |
|
552 | 554 |
void update_fp_status(void); |
553 | 555 |
|
554 | 556 |
extern const uint8_t parity_table[256]; |
b/target-i386/helper.c | ||
---|---|---|
3223 | 3223 |
|
3224 | 3224 |
#endif |
3225 | 3225 |
|
3226 |
/* XXX: do it */ |
|
3227 |
int fpu_isnan(double a) |
|
3228 |
{ |
|
3229 |
return 0; |
|
3230 |
} |
|
3231 |
|
|
3232 | 3226 |
float approx_rsqrt(float a) |
3233 | 3227 |
{ |
3234 | 3228 |
return 1.0 / sqrt(a); |
b/target-i386/op.c | ||
---|---|---|
1952 | 1952 |
|
1953 | 1953 |
/* FPU operations */ |
1954 | 1954 |
|
1955 |
/* XXX: handle nans */ |
|
1956 | 1955 |
void OPPROTO op_fcom_ST0_FT0(void) |
1957 | 1956 |
{ |
1958 |
env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ |
|
1959 |
if (ST0 < FT0) |
|
1960 |
env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ |
|
1961 |
else if (ST0 == FT0) |
|
1962 |
env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ |
|
1957 |
int cc; |
|
1958 |
switch(floatx_compare(ST0, FT0, &env->fp_status)) { |
|
1959 |
case -1: |
|
1960 |
cc = 0x0100; |
|
1961 |
break; |
|
1962 |
case 0: |
|
1963 |
cc = 0x4000; |
|
1964 |
break; |
|
1965 |
case 1: |
|
1966 |
cc = 0x0000; |
|
1967 |
break; |
|
1968 |
case 2: |
|
1969 |
default: |
|
1970 |
cc = 0x4500; |
|
1971 |
break; |
|
1972 |
} |
|
1973 |
env->fpus = (env->fpus & ~0x4500) | cc; |
|
1963 | 1974 |
FORCE_RET(); |
1964 | 1975 |
} |
1965 | 1976 |
|
1966 |
/* XXX: handle nans */ |
|
1967 | 1977 |
void OPPROTO op_fucom_ST0_FT0(void) |
1968 | 1978 |
{ |
1969 |
env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */ |
|
1970 |
if (ST0 < FT0) |
|
1971 |
env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */ |
|
1972 |
else if (ST0 == FT0) |
|
1973 |
env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */ |
|
1979 |
int cc; |
|
1980 |
switch(floatx_compare_quiet(ST0, FT0, &env->fp_status)) { |
|
1981 |
case -1: |
|
1982 |
cc = 0x0100; |
|
1983 |
break; |
|
1984 |
case 0: |
|
1985 |
cc = 0x4000; |
|
1986 |
break; |
|
1987 |
case 1: |
|
1988 |
cc = 0x0000; |
|
1989 |
break; |
|
1990 |
case 2: |
|
1991 |
default: |
|
1992 |
cc = 0x4500; |
|
1993 |
break; |
|
1994 |
} |
|
1995 |
env->fpus = (env->fpus & ~0x4500) | cc; |
|
1974 | 1996 |
FORCE_RET(); |
1975 | 1997 |
} |
1976 | 1998 |
|
1977 |
/* XXX: handle nans */ |
|
1978 | 1999 |
void OPPROTO op_fcomi_ST0_FT0(void) |
1979 | 2000 |
{ |
1980 |
int eflags; |
|
2001 |
int eflags, cc; |
|
2002 |
switch(floatx_compare(ST0, FT0, &env->fp_status)) { |
|
2003 |
case -1: |
|
2004 |
cc = CC_C; |
|
2005 |
break; |
|
2006 |
case 0: |
|
2007 |
cc = CC_Z; |
|
2008 |
break; |
|
2009 |
case 1: |
|
2010 |
cc = 0; |
|
2011 |
break; |
|
2012 |
case 2: |
|
2013 |
default: |
|
2014 |
cc = CC_Z | CC_P | CC_C; |
|
2015 |
break; |
|
2016 |
} |
|
1981 | 2017 |
eflags = cc_table[CC_OP].compute_all(); |
1982 |
eflags &= ~(CC_Z | CC_P | CC_C); |
|
1983 |
if (ST0 < FT0) |
|
1984 |
eflags |= CC_C; |
|
1985 |
else if (ST0 == FT0) |
|
1986 |
eflags |= CC_Z; |
|
2018 |
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | cc; |
|
1987 | 2019 |
CC_SRC = eflags; |
1988 | 2020 |
FORCE_RET(); |
1989 | 2021 |
} |
1990 | 2022 |
|
1991 |
/* XXX: handle nans */ |
|
1992 | 2023 |
void OPPROTO op_fucomi_ST0_FT0(void) |
1993 | 2024 |
{ |
1994 |
int eflags; |
|
2025 |
int eflags, cc; |
|
2026 |
switch(floatx_compare_quiet(ST0, FT0, &env->fp_status)) { |
|
2027 |
case -1: |
|
2028 |
cc = CC_C; |
|
2029 |
break; |
|
2030 |
case 0: |
|
2031 |
cc = CC_Z; |
|
2032 |
break; |
|
2033 |
case 1: |
|
2034 |
cc = 0; |
|
2035 |
break; |
|
2036 |
case 2: |
|
2037 |
default: |
|
2038 |
cc = CC_Z | CC_P | CC_C; |
|
2039 |
break; |
|
2040 |
} |
|
1995 | 2041 |
eflags = cc_table[CC_OP].compute_all(); |
1996 |
eflags &= ~(CC_Z | CC_P | CC_C); |
|
1997 |
if (ST0 < FT0) |
|
1998 |
eflags |= CC_C; |
|
1999 |
else if (ST0 == FT0) |
|
2000 |
eflags |= CC_Z; |
|
2042 |
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | cc; |
|
2001 | 2043 |
CC_SRC = eflags; |
2002 | 2044 |
FORCE_RET(); |
2003 | 2045 |
} |
b/target-i386/ops_sse.h | ||
---|---|---|
704 | 704 |
/* float to float conversions */ |
705 | 705 |
void OPPROTO op_cvtps2pd(void) |
706 | 706 |
{ |
707 |
float s0, s1; |
|
707 |
float32 s0, s1;
|
|
708 | 708 |
Reg *d, *s; |
709 | 709 |
d = (Reg *)((char *)env + PARAM1); |
710 | 710 |
s = (Reg *)((char *)env + PARAM2); |
... | ... | |
1031 | 1031 |
Reg *d, *s;\ |
1032 | 1032 |
d = (Reg *)((char *)env + PARAM1);\ |
1033 | 1033 |
s = (Reg *)((char *)env + PARAM2);\ |
1034 |
d->XMM_L(0) = F(d->XMM_S(0), s->XMM_S(0));\ |
|
1035 |
d->XMM_L(1) = F(d->XMM_S(1), s->XMM_S(1));\ |
|
1036 |
d->XMM_L(2) = F(d->XMM_S(2), s->XMM_S(2));\ |
|
1037 |
d->XMM_L(3) = F(d->XMM_S(3), s->XMM_S(3));\ |
|
1034 |
d->XMM_L(0) = F(32, d->XMM_S(0), s->XMM_S(0));\
|
|
1035 |
d->XMM_L(1) = F(32, d->XMM_S(1), s->XMM_S(1));\
|
|
1036 |
d->XMM_L(2) = F(32, d->XMM_S(2), s->XMM_S(2));\
|
|
1037 |
d->XMM_L(3) = F(32, d->XMM_S(3), s->XMM_S(3));\
|
|
1038 | 1038 |
}\ |
1039 | 1039 |
\ |
1040 | 1040 |
void OPPROTO op_ ## name ## ss (void)\ |
... | ... | |
1042 | 1042 |
Reg *d, *s;\ |
1043 | 1043 |
d = (Reg *)((char *)env + PARAM1);\ |
1044 | 1044 |
s = (Reg *)((char *)env + PARAM2);\ |
1045 |
d->XMM_L(0) = F(d->XMM_S(0), s->XMM_S(0));\ |
|
1045 |
d->XMM_L(0) = F(32, d->XMM_S(0), s->XMM_S(0));\
|
|
1046 | 1046 |
}\ |
1047 | 1047 |
void OPPROTO op_ ## name ## pd (void)\ |
1048 | 1048 |
{\ |
1049 | 1049 |
Reg *d, *s;\ |
1050 | 1050 |
d = (Reg *)((char *)env + PARAM1);\ |
1051 | 1051 |
s = (Reg *)((char *)env + PARAM2);\ |
1052 |
d->XMM_Q(0) = F(d->XMM_D(0), s->XMM_D(0));\ |
|
1053 |
d->XMM_Q(1) = F(d->XMM_D(1), s->XMM_D(1));\ |
|
1052 |
d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0));\
|
|
1053 |
d->XMM_Q(1) = F(64, d->XMM_D(1), s->XMM_D(1));\
|
|
1054 | 1054 |
}\ |
1055 | 1055 |
\ |
1056 | 1056 |
void OPPROTO op_ ## name ## sd (void)\ |
... | ... | |
1058 | 1058 |
Reg *d, *s;\ |
1059 | 1059 |
d = (Reg *)((char *)env + PARAM1);\ |
1060 | 1060 |
s = (Reg *)((char *)env + PARAM2);\ |
1061 |
d->XMM_Q(0) = F(d->XMM_D(0), s->XMM_D(0));\ |
|
1061 |
d->XMM_Q(0) = F(64, d->XMM_D(0), s->XMM_D(0));\
|
|
1062 | 1062 |
} |
1063 | 1063 |
|
1064 |
#define FPU_CMPEQ(a, b) (a) == (b) ? -1 : 0
|
|
1065 |
#define FPU_CMPLT(a, b) (a) < (b) ? -1 : 0
|
|
1066 |
#define FPU_CMPLE(a, b) (a) <= (b) ? -1 : 0
|
|
1067 |
#define FPU_CMPUNORD(a, b) (fpu_isnan(a) || fpu_isnan(b)) ? - 1 : 0
|
|
1068 |
#define FPU_CMPNEQ(a, b) (a) == (b) ? 0 : -1
|
|
1069 |
#define FPU_CMPNLT(a, b) (a) < (b) ? 0 : -1
|
|
1070 |
#define FPU_CMPNLE(a, b) (a) <= (b) ? 0 : -1
|
|
1071 |
#define FPU_CMPORD(a, b) (!fpu_isnan(a) && !fpu_isnan(b)) ? - 1 : 0
|
|
1064 |
#define FPU_CMPEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? -1 : 0
|
|
1065 |
#define FPU_CMPLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? -1 : 0
|
|
1066 |
#define FPU_CMPLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? -1 : 0
|
|
1067 |
#define FPU_CMPUNORD(size, a, b) float ## size ## _unordered(a, b, &env->sse_status) ? - 1 : 0
|
|
1068 |
#define FPU_CMPNEQ(size, a, b) float ## size ## _eq(a, b, &env->sse_status) ? 0 : -1
|
|
1069 |
#define FPU_CMPNLT(size, a, b) float ## size ## _lt(a, b, &env->sse_status) ? 0 : -1
|
|
1070 |
#define FPU_CMPNLE(size, a, b) float ## size ## _le(a, b, &env->sse_status) ? 0 : -1
|
|
1071 |
#define FPU_CMPORD(size, a, b) float ## size ## _unordered(a, b, &env->sse_status) ? 0 : -1
|
|
1072 | 1072 |
|
1073 | 1073 |
SSE_OP_CMP(cmpeq, FPU_CMPEQ) |
1074 | 1074 |
SSE_OP_CMP(cmplt, FPU_CMPLT) |
... | ... | |
1082 | 1082 |
void OPPROTO op_ucomiss(void) |
1083 | 1083 |
{ |
1084 | 1084 |
int eflags; |
1085 |
float s0, s1; |
|
1085 |
float32 s0, s1;
|
|
1086 | 1086 |
Reg *d, *s; |
1087 | 1087 |
d = (Reg *)((char *)env + PARAM1); |
1088 | 1088 |
s = (Reg *)((char *)env + PARAM2); |
1089 | 1089 |
|
1090 | 1090 |
s0 = d->XMM_S(0); |
1091 | 1091 |
s1 = s->XMM_S(0); |
1092 |
if (s0 < s1) |
|
1092 |
switch(float32_compare_quiet(s0, s1, &env->sse_status)) { |
|
1093 |
case -1: |
|
1093 | 1094 |
eflags = CC_C; |
1094 |
else if (s0 == s1) |
|
1095 |
break; |
|
1096 |
case 0: |
|
1095 | 1097 |
eflags = CC_Z; |
1096 |
else |
|
1098 |
break; |
|
1099 |
case 1: |
|
1097 | 1100 |
eflags = 0; |
1101 |
break; |
|
1102 |
case 2: |
|
1103 |
default: |
|
1104 |
eflags = CC_Z | CC_P | CC_C; |
|
1105 |
break; |
|
1106 |
} |
|
1098 | 1107 |
CC_SRC = eflags; |
1099 | 1108 |
FORCE_RET(); |
1100 | 1109 |
} |
... | ... | |
1102 | 1111 |
void OPPROTO op_comiss(void) |
1103 | 1112 |
{ |
1104 | 1113 |
int eflags; |
1105 |
float s0, s1; |
|
1114 |
float32 s0, s1;
|
|
1106 | 1115 |
Reg *d, *s; |
1107 | 1116 |
d = (Reg *)((char *)env + PARAM1); |
1108 | 1117 |
s = (Reg *)((char *)env + PARAM2); |
1109 | 1118 |
|
1110 | 1119 |
s0 = d->XMM_S(0); |
1111 | 1120 |
s1 = s->XMM_S(0); |
1112 |
if (s0 < s1) |
|
1121 |
switch(float32_compare(s0, s1, &env->sse_status)) { |
|
1122 |
case -1: |
|
1113 | 1123 |
eflags = CC_C; |
1114 |
else if (s0 == s1) |
|
1124 |
break; |
|
1125 |
case 0: |
|
1115 | 1126 |
eflags = CC_Z; |
1116 |
else |
|
1127 |
break; |
|
1128 |
case 1: |
|
1117 | 1129 |
eflags = 0; |
1130 |
break; |
|
1131 |
case 2: |
|
1132 |
default: |
|
1133 |
eflags = CC_Z | CC_P | CC_C; |
|
1134 |
break; |
|
1135 |
} |
|
1118 | 1136 |
CC_SRC = eflags; |
1119 | 1137 |
FORCE_RET(); |
1120 | 1138 |
} |
... | ... | |
1122 | 1140 |
void OPPROTO op_ucomisd(void) |
1123 | 1141 |
{ |
1124 | 1142 |
int eflags; |
1125 |
double d0, d1;
|
|
1143 |
float64 d0, d1;
|
|
1126 | 1144 |
Reg *d, *s; |
1127 | 1145 |
d = (Reg *)((char *)env + PARAM1); |
1128 | 1146 |
s = (Reg *)((char *)env + PARAM2); |
1129 | 1147 |
|
1130 | 1148 |
d0 = d->XMM_D(0); |
1131 | 1149 |
d1 = s->XMM_D(0); |
1132 |
if (d0 < d1) |
|
1150 |
switch(float64_compare_quiet(d0, d1, &env->sse_status)) { |
|
1151 |
case -1: |
|
1133 | 1152 |
eflags = CC_C; |
1134 |
else if (d0 == d1) |
|
1153 |
break; |
|
1154 |
case 0: |
|
1135 | 1155 |
eflags = CC_Z; |
1136 |
else |
|
1156 |
break; |
|
1157 |
case 1: |
|
1137 | 1158 |
eflags = 0; |
1159 |
break; |
|
1160 |
case 2: |
|
1161 |
default: |
|
1162 |
eflags = CC_Z | CC_P | CC_C; |
|
1163 |
break; |
|
1164 |
} |
|
1138 | 1165 |
CC_SRC = eflags; |
1139 | 1166 |
FORCE_RET(); |
1140 | 1167 |
} |
... | ... | |
1142 | 1169 |
void OPPROTO op_comisd(void) |
1143 | 1170 |
{ |
1144 | 1171 |
int eflags; |
1145 |
double d0, d1;
|
|
1172 |
float64 d0, d1;
|
|
1146 | 1173 |
Reg *d, *s; |
1147 | 1174 |
d = (Reg *)((char *)env + PARAM1); |
1148 | 1175 |
s = (Reg *)((char *)env + PARAM2); |
1149 | 1176 |
|
1150 | 1177 |
d0 = d->XMM_D(0); |
1151 | 1178 |
d1 = s->XMM_D(0); |
1152 |
if (d0 < d1) |
|
1179 |
switch(float64_compare(d0, d1, &env->sse_status)) { |
|
1180 |
case -1: |
|
1153 | 1181 |
eflags = CC_C; |
1154 |
else if (d0 == d1) |
|
1182 |
break; |
|
1183 |
case 0: |
|
1155 | 1184 |
eflags = CC_Z; |
1156 |
else |
|
1185 |
break; |
|
1186 |
case 1: |
|
1157 | 1187 |
eflags = 0; |
1188 |
break; |
|
1189 |
case 2: |
|
1190 |
default: |
|
1191 |
eflags = CC_Z | CC_P | CC_C; |
|
1192 |
break; |
|
1193 |
} |
|
1158 | 1194 |
CC_SRC = eflags; |
1159 | 1195 |
FORCE_RET(); |
1160 | 1196 |
} |
Also available in: Unified diff