Commit 4d40895f2c30354c48ad9181e366e8d738f9b4d7
1 parent
e477b8b8
more accurate bcd convert - fixed FPU exceptions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@304 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
31 additions
and
61 deletions
helper-i386.c
| ... | ... | @@ -981,7 +981,11 @@ void helper_lar(void) |
| 981 | 981 | #ifndef USE_X86LDOUBLE |
| 982 | 982 | void helper_fldt_ST0_A0(void) |
| 983 | 983 | { |
| 984 | - ST0 = helper_fldt((uint8_t *)A0); | |
| 984 | + int new_fpstt; | |
| 985 | + new_fpstt = (env->fpstt - 1) & 7; | |
| 986 | + env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0); | |
| 987 | + env->fpstt = new_fpstt; | |
| 988 | + env->fptags[new_fpstt] = 0; /* validate stack entry */ | |
| 985 | 989 | } |
| 986 | 990 | |
| 987 | 991 | void helper_fstt_ST0_A0(void) |
| ... | ... | @@ -996,81 +1000,47 @@ void helper_fstt_ST0_A0(void) |
| 996 | 1000 | |
| 997 | 1001 | void helper_fbld_ST0_A0(void) |
| 998 | 1002 | { |
| 999 | - uint8_t *seg; | |
| 1000 | - CPU86_LDouble fpsrcop; | |
| 1001 | - int m32i; | |
| 1003 | + CPU86_LDouble tmp; | |
| 1004 | + uint64_t val; | |
| 1002 | 1005 | unsigned int v; |
| 1006 | + int i; | |
| 1003 | 1007 | |
| 1004 | - /* in this code, seg/m32i will be used as temporary ptr/int */ | |
| 1005 | - seg = (uint8_t *)A0 + 8; | |
| 1006 | - v = ldub(seg--); | |
| 1007 | - /* XXX: raise exception */ | |
| 1008 | - if (v != 0) | |
| 1009 | - return; | |
| 1010 | - v = ldub(seg--); | |
| 1011 | - /* XXX: raise exception */ | |
| 1012 | - if ((v & 0xf0) != 0) | |
| 1013 | - return; | |
| 1014 | - m32i = v; /* <-- d14 */ | |
| 1015 | - v = ldub(seg--); | |
| 1016 | - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d13 */ | |
| 1017 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */ | |
| 1018 | - v = ldub(seg--); | |
| 1019 | - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d11 */ | |
| 1020 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */ | |
| 1021 | - v = ldub(seg--); | |
| 1022 | - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d9 */ | |
| 1023 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */ | |
| 1024 | - fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0; | |
| 1025 | - | |
| 1026 | - v = ldub(seg--); | |
| 1027 | - m32i = (v >> 4); /* <-- d7 */ | |
| 1028 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */ | |
| 1029 | - v = ldub(seg--); | |
| 1030 | - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d5 */ | |
| 1031 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */ | |
| 1032 | - v = ldub(seg--); | |
| 1033 | - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d3 */ | |
| 1034 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */ | |
| 1035 | - v = ldub(seg); | |
| 1036 | - m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d1 */ | |
| 1037 | - m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */ | |
| 1038 | - fpsrcop += ((CPU86_LDouble)m32i); | |
| 1039 | - if ( ldub(seg+9) & 0x80 ) | |
| 1040 | - fpsrcop = -fpsrcop; | |
| 1041 | - ST0 = fpsrcop; | |
| 1008 | + val = 0; | |
| 1009 | + for(i = 8; i >= 0; i--) { | |
| 1010 | + v = ldub((uint8_t *)A0 + i); | |
| 1011 | + val = (val * 100) + ((v >> 4) * 10) + (v & 0xf); | |
| 1012 | + } | |
| 1013 | + tmp = val; | |
| 1014 | + if (ldub((uint8_t *)A0 + 9) & 0x80) | |
| 1015 | + tmp = -tmp; | |
| 1016 | + fpush(); | |
| 1017 | + ST0 = tmp; | |
| 1042 | 1018 | } |
| 1043 | 1019 | |
| 1044 | 1020 | void helper_fbst_ST0_A0(void) |
| 1045 | 1021 | { |
| 1046 | - CPU86_LDouble fptemp; | |
| 1047 | - CPU86_LDouble fpsrcop; | |
| 1022 | + CPU86_LDouble tmp; | |
| 1048 | 1023 | int v; |
| 1049 | 1024 | uint8_t *mem_ref, *mem_end; |
| 1025 | + int64_t val; | |
| 1050 | 1026 | |
| 1051 | - fpsrcop = rint(ST0); | |
| 1027 | + tmp = rint(ST0); | |
| 1028 | + val = (int64_t)tmp; | |
| 1052 | 1029 | mem_ref = (uint8_t *)A0; |
| 1053 | - mem_end = mem_ref + 8; | |
| 1054 | - if ( fpsrcop < 0.0 ) { | |
| 1055 | - stw(mem_end, 0x8000); | |
| 1056 | - fpsrcop = -fpsrcop; | |
| 1030 | + mem_end = mem_ref + 9; | |
| 1031 | + if (val < 0) { | |
| 1032 | + stb(mem_end, 0x80); | |
| 1033 | + val = -val; | |
| 1057 | 1034 | } else { |
| 1058 | - stw(mem_end, 0x0000); | |
| 1035 | + stb(mem_end, 0x00); | |
| 1059 | 1036 | } |
| 1060 | 1037 | while (mem_ref < mem_end) { |
| 1061 | - if (fpsrcop == 0.0) | |
| 1038 | + if (val == 0) | |
| 1062 | 1039 | break; |
| 1063 | - fptemp = floor(fpsrcop/10.0); | |
| 1064 | - v = ((int)(fpsrcop - fptemp*10.0)); | |
| 1065 | - if (fptemp == 0.0) { | |
| 1066 | - stb(mem_ref++, v); | |
| 1067 | - break; | |
| 1068 | - } | |
| 1069 | - fpsrcop = fptemp; | |
| 1070 | - fptemp = floor(fpsrcop/10.0); | |
| 1071 | - v |= (((int)(fpsrcop - fptemp*10.0)) << 4); | |
| 1040 | + v = val % 100; | |
| 1041 | + val = val / 100; | |
| 1042 | + v = ((v / 10) << 4) | (v % 10); | |
| 1072 | 1043 | stb(mem_ref++, v); |
| 1073 | - fpsrcop = fptemp; | |
| 1074 | 1044 | } |
| 1075 | 1045 | while (mem_ref < mem_end) { |
| 1076 | 1046 | stb(mem_ref++, 0); | ... | ... |