Commit 4d40895f2c30354c48ad9181e366e8d738f9b4d7

Authored by bellard
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,7 +981,11 @@ void helper_lar(void)
981 #ifndef USE_X86LDOUBLE 981 #ifndef USE_X86LDOUBLE
982 void helper_fldt_ST0_A0(void) 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 void helper_fstt_ST0_A0(void) 991 void helper_fstt_ST0_A0(void)
@@ -996,81 +1000,47 @@ void helper_fstt_ST0_A0(void) @@ -996,81 +1000,47 @@ void helper_fstt_ST0_A0(void)
996 1000
997 void helper_fbld_ST0_A0(void) 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 unsigned int v; 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 void helper_fbst_ST0_A0(void) 1020 void helper_fbst_ST0_A0(void)
1045 { 1021 {
1046 - CPU86_LDouble fptemp;  
1047 - CPU86_LDouble fpsrcop; 1022 + CPU86_LDouble tmp;
1048 int v; 1023 int v;
1049 uint8_t *mem_ref, *mem_end; 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 mem_ref = (uint8_t *)A0; 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 } else { 1034 } else {
1058 - stw(mem_end, 0x0000); 1035 + stb(mem_end, 0x00);
1059 } 1036 }
1060 while (mem_ref < mem_end) { 1037 while (mem_ref < mem_end) {
1061 - if (fpsrcop == 0.0) 1038 + if (val == 0)
1062 break; 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 stb(mem_ref++, v); 1043 stb(mem_ref++, v);
1073 - fpsrcop = fptemp;  
1074 } 1044 }
1075 while (mem_ref < mem_end) { 1045 while (mem_ref < mem_end) {
1076 stb(mem_ref++, 0); 1046 stb(mem_ref++, 0);