1073 |
EBX = 0x756e6547; |
EBX = 0x756e6547; |
1074 |
ECX = 0x6c65746e; |
ECX = 0x6c65746e; |
1075 |
EDX = 0x49656e69; |
EDX = 0x49656e69; |
1076 |
} else { |
} else if (EAX == 1) { |
1077 |
/* EAX = 1 info */ |
/* EAX = 1 info */ |
1078 |
EAX = 0x52b; |
EAX = 0x52b; |
1079 |
EBX = 0; |
EBX = 0; |
1899 |
ST0 = *(long double *)A0; |
ST0 = *(long double *)A0; |
1900 |
} |
} |
1901 |
#else |
#else |
1902 |
void helper_fldt_ST0_A0(void) |
static inline CPU86_LDouble helper_fldt(uint8_t *ptr) |
1903 |
{ |
{ |
1904 |
CPU86_LDoubleU temp; |
CPU86_LDoubleU temp; |
1905 |
int upper, e; |
int upper, e; |
1906 |
/* mantissa */ |
/* mantissa */ |
1907 |
upper = lduw((uint8_t *)A0 + 8); |
upper = lduw(ptr + 8); |
1908 |
/* XXX: handle overflow ? */ |
/* XXX: handle overflow ? */ |
1909 |
e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ |
e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ |
1910 |
e |= (upper >> 4) & 0x800; /* sign */ |
e |= (upper >> 4) & 0x800; /* sign */ |
1911 |
temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52); |
temp.ll = ((ldq(ptr) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52); |
1912 |
ST0 = temp.d; |
return temp.d; |
1913 |
|
} |
1914 |
|
|
1915 |
|
void helper_fldt_ST0_A0(void) |
1916 |
|
{ |
1917 |
|
ST0 = helper_fldt((uint8_t *)A0); |
1918 |
} |
} |
1919 |
|
|
1920 |
void OPPROTO op_fldt_ST0_A0(void) |
void OPPROTO op_fldt_ST0_A0(void) |
2013 |
*(long double *)A0 = ST0; |
*(long double *)A0 = ST0; |
2014 |
} |
} |
2015 |
#else |
#else |
2016 |
void helper_fstt_ST0_A0(void) |
|
2017 |
|
static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr) |
2018 |
{ |
{ |
2019 |
CPU86_LDoubleU temp; |
CPU86_LDoubleU temp; |
2020 |
int e; |
int e; |
2021 |
temp.d = ST0; |
temp.d = f; |
2022 |
/* mantissa */ |
/* mantissa */ |
2023 |
stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63)); |
stq(ptr, (MANTD(temp) << 11) | (1LL << 63)); |
2024 |
/* exponent + sign */ |
/* exponent + sign */ |
2025 |
e = EXPD(temp) - EXPBIAS + 16383; |
e = EXPD(temp) - EXPBIAS + 16383; |
2026 |
e |= SIGND(temp) >> 16; |
e |= SIGND(temp) >> 16; |
2027 |
stw((uint8_t *)A0 + 8, e); |
stw(ptr + 8, e); |
2028 |
|
} |
2029 |
|
|
2030 |
|
void helper_fstt_ST0_A0(void) |
2031 |
|
{ |
2032 |
|
helper_fstt(ST0, (uint8_t *)A0); |
2033 |
} |
} |
2034 |
|
|
2035 |
void OPPROTO op_fstt_ST0_A0(void) |
void OPPROTO op_fstt_ST0_A0(void) |
2265 |
FORCE_RET(); |
FORCE_RET(); |
2266 |
} |
} |
2267 |
|
|
2268 |
|
/* XXX: handle nans */ |
2269 |
|
void OPPROTO op_fcomi_ST0_FT0(void) |
2270 |
|
{ |
2271 |
|
int eflags; |
2272 |
|
eflags = cc_table[CC_OP].compute_all(); |
2273 |
|
eflags &= ~(CC_Z | CC_P | CC_C); |
2274 |
|
if (ST0 < FT0) |
2275 |
|
eflags |= CC_C; |
2276 |
|
else if (ST0 == FT0) |
2277 |
|
eflags |= CC_Z; |
2278 |
|
CC_SRC = eflags; |
2279 |
|
FORCE_RET(); |
2280 |
|
} |
2281 |
|
|
2282 |
|
/* XXX: handle nans */ |
2283 |
|
void OPPROTO op_fucomi_ST0_FT0(void) |
2284 |
|
{ |
2285 |
|
int eflags; |
2286 |
|
eflags = cc_table[CC_OP].compute_all(); |
2287 |
|
eflags &= ~(CC_Z | CC_P | CC_C); |
2288 |
|
if (ST0 < FT0) |
2289 |
|
eflags |= CC_C; |
2290 |
|
else if (ST0 == FT0) |
2291 |
|
eflags |= CC_Z; |
2292 |
|
CC_SRC = eflags; |
2293 |
|
FORCE_RET(); |
2294 |
|
} |
2295 |
|
|
2296 |
void OPPROTO op_fadd_ST0_FT0(void) |
void OPPROTO op_fadd_ST0_FT0(void) |
2297 |
{ |
{ |
2298 |
ST0 += FT0; |
ST0 += FT0; |
2789 |
env->fptags[7] = 1; |
env->fptags[7] = 1; |
2790 |
} |
} |
2791 |
|
|
2792 |
|
void helper_fstenv(uint8_t *ptr, int data32) |
2793 |
|
{ |
2794 |
|
int fpus, fptag, exp, i; |
2795 |
|
uint64_t mant; |
2796 |
|
CPU86_LDoubleU tmp; |
2797 |
|
|
2798 |
|
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; |
2799 |
|
fptag = 0; |
2800 |
|
for (i=7; i>=0; i--) { |
2801 |
|
fptag <<= 2; |
2802 |
|
if (env->fptags[i]) { |
2803 |
|
fptag |= 3; |
2804 |
|
} else { |
2805 |
|
tmp.d = env->fpregs[i]; |
2806 |
|
exp = EXPD(tmp); |
2807 |
|
mant = MANTD(tmp); |
2808 |
|
if (exp == 0 && mant == 0) { |
2809 |
|
/* zero */ |
2810 |
|
fptag |= 1; |
2811 |
|
} else if (exp == 0 || exp == MAXEXPD |
2812 |
|
#ifdef USE_X86LDOUBLE |
2813 |
|
|| (mant & (1LL << 63)) == 0 |
2814 |
|
#endif |
2815 |
|
) { |
2816 |
|
/* NaNs, infinity, denormal */ |
2817 |
|
fptag |= 2; |
2818 |
|
} |
2819 |
|
} |
2820 |
|
} |
2821 |
|
if (data32) { |
2822 |
|
/* 32 bit */ |
2823 |
|
stl(ptr, env->fpuc); |
2824 |
|
stl(ptr + 4, fpus); |
2825 |
|
stl(ptr + 8, fptag); |
2826 |
|
stl(ptr + 12, 0); |
2827 |
|
stl(ptr + 16, 0); |
2828 |
|
stl(ptr + 20, 0); |
2829 |
|
stl(ptr + 24, 0); |
2830 |
|
} else { |
2831 |
|
/* 16 bit */ |
2832 |
|
stw(ptr, env->fpuc); |
2833 |
|
stw(ptr + 2, fpus); |
2834 |
|
stw(ptr + 4, fptag); |
2835 |
|
stw(ptr + 6, 0); |
2836 |
|
stw(ptr + 8, 0); |
2837 |
|
stw(ptr + 10, 0); |
2838 |
|
stw(ptr + 12, 0); |
2839 |
|
} |
2840 |
|
} |
2841 |
|
|
2842 |
|
void helper_fldenv(uint8_t *ptr, int data32) |
2843 |
|
{ |
2844 |
|
int i, fpus, fptag; |
2845 |
|
|
2846 |
|
if (data32) { |
2847 |
|
env->fpuc = lduw(ptr); |
2848 |
|
fpus = lduw(ptr + 4); |
2849 |
|
fptag = lduw(ptr + 8); |
2850 |
|
} |
2851 |
|
else { |
2852 |
|
env->fpuc = lduw(ptr); |
2853 |
|
fpus = lduw(ptr + 2); |
2854 |
|
fptag = lduw(ptr + 4); |
2855 |
|
} |
2856 |
|
env->fpstt = (fpus >> 11) & 7; |
2857 |
|
env->fpus = fpus & ~0x3800; |
2858 |
|
for(i = 0;i < 7; i++) { |
2859 |
|
env->fptags[i] = ((fptag & 3) == 3); |
2860 |
|
fptag >>= 2; |
2861 |
|
} |
2862 |
|
} |
2863 |
|
|
2864 |
|
void helper_fsave(uint8_t *ptr, int data32) |
2865 |
|
{ |
2866 |
|
CPU86_LDouble tmp; |
2867 |
|
int i; |
2868 |
|
|
2869 |
|
helper_fstenv(ptr, data32); |
2870 |
|
|
2871 |
|
ptr += (14 << data32); |
2872 |
|
for(i = 0;i < 8; i++) { |
2873 |
|
tmp = ST(i); |
2874 |
|
#ifdef USE_X86LDOUBLE |
2875 |
|
*(long double *)ptr = tmp; |
2876 |
|
#else |
2877 |
|
helper_fstt(tmp, ptr); |
2878 |
|
#endif |
2879 |
|
ptr += 10; |
2880 |
|
} |
2881 |
|
|
2882 |
|
/* fninit */ |
2883 |
|
env->fpus = 0; |
2884 |
|
env->fpstt = 0; |
2885 |
|
env->fpuc = 0x37f; |
2886 |
|
env->fptags[0] = 1; |
2887 |
|
env->fptags[1] = 1; |
2888 |
|
env->fptags[2] = 1; |
2889 |
|
env->fptags[3] = 1; |
2890 |
|
env->fptags[4] = 1; |
2891 |
|
env->fptags[5] = 1; |
2892 |
|
env->fptags[6] = 1; |
2893 |
|
env->fptags[7] = 1; |
2894 |
|
} |
2895 |
|
|
2896 |
|
void helper_frstor(uint8_t *ptr, int data32) |
2897 |
|
{ |
2898 |
|
CPU86_LDouble tmp; |
2899 |
|
int i; |
2900 |
|
|
2901 |
|
helper_fldenv(ptr, data32); |
2902 |
|
ptr += (14 << data32); |
2903 |
|
|
2904 |
|
for(i = 0;i < 8; i++) { |
2905 |
|
#ifdef USE_X86LDOUBLE |
2906 |
|
tmp = *(long double *)ptr; |
2907 |
|
#else |
2908 |
|
tmp = helper_fldt(ptr); |
2909 |
|
#endif |
2910 |
|
ST(i) = tmp; |
2911 |
|
ptr += 10; |
2912 |
|
} |
2913 |
|
} |
2914 |
|
|
2915 |
|
void OPPROTO op_fnstenv_A0(void) |
2916 |
|
{ |
2917 |
|
helper_fstenv((uint8_t *)A0, PARAM1); |
2918 |
|
} |
2919 |
|
|
2920 |
|
void OPPROTO op_fldenv_A0(void) |
2921 |
|
{ |
2922 |
|
helper_fldenv((uint8_t *)A0, PARAM1); |
2923 |
|
} |
2924 |
|
|
2925 |
|
void OPPROTO op_fnsave_A0(void) |
2926 |
|
{ |
2927 |
|
helper_fsave((uint8_t *)A0, PARAM1); |
2928 |
|
} |
2929 |
|
|
2930 |
|
void OPPROTO op_frstor_A0(void) |
2931 |
|
{ |
2932 |
|
helper_frstor((uint8_t *)A0, PARAM1); |
2933 |
|
} |
2934 |
|
|
2935 |
/* threading support */ |
/* threading support */ |
2936 |
void OPPROTO op_lock(void) |
void OPPROTO op_lock(void) |
2937 |
{ |
{ |