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 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);
... ...