Fixed the IDIV instructions on 286+ again, this time properly, fixes hang with the NCR 53C810 BIOS v4.0x.

This commit is contained in:
OBattler
2017-12-14 03:33:07 +01:00
parent ed384101fd
commit 28426e53af
2 changed files with 115 additions and 83 deletions

View File

@@ -463,28 +463,30 @@ int divl(uint32_t val)
} }
int idivl(int32_t val) int idivl(int32_t val)
{ {
int64_t num, quo; uint64_t tempsrc;
int32_t rem, quo32; int64_t tempws, tempws2 = 0;
if (val==0) if (val == 0) {
{ divexcp(); /* Divide by zero. */
divexcp(); return 1;
return 1; }
}
num=(((uint64_t)EDX)<<32)|EAX; tempsrc = (uint64_t) EDX;
quo=num/val; tempsrc = (tempsrc << 32) | EAX;
rem=num%val; tempws = ((int64_t)tempsrc) / ((int64_t)((int32_t)val));
quo32=(int32_t)(quo&0xFFFFFFFF);
if ((quo > 0x000000007FFFFFFFLL) || (quo < 0xFFFFFFFF80000000LL)) if ((tempws > 2147483647LL) || (tempws < -2147483648LL)) {
{ divexcp();
divexcp(); return 1;
return 1; }
}
EDX=rem; tempws = (int32_t) tempws;
EAX=quo32; tempws2 = (int32_t) ((int64_t)tempsrc) % ((int64_t)((int32_t)val));
return 0;
DX = (uint32_t) tempws2;
AX = (uint32_t) tempws;
return 0;
} }

View File

@@ -64,7 +64,7 @@ static int opSETALC(uint32_t fetchdat)
static int opF6_a16(uint32_t fetchdat) static int opF6_a16(uint32_t fetchdat)
{ {
int tempws, tempws2 = 0; int32_t tempws, tempws2 = 0;
uint16_t tempw, src16; uint16_t tempw, src16;
uint8_t src, dst; uint8_t src, dst;
@@ -130,23 +130,29 @@ static int opF6_a16(uint32_t fetchdat)
PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break; break;
case 0x38: /*IDIV AL,b*/ case 0x38: /*IDIV AL,b*/
tempws = (int)(int16_t)AX; if (dst == 0) {
if (dst != 0) tempws2 = tempws / (int)((int8_t)dst); x86_int(0); /* Divide by zero. */
if (dst && ((tempws2 > 0x0000007F) || (tempws2 < 0xFFFFFF80))) return 1;
{ }
AH = (tempws % (int)((int8_t)dst)) & 0xff;
AL = tempws2 & 0xff; tempws = ((int)((int16_t)AX)) / ((int)((int8_t)dst));
if (!cpu_iscyrix)
{ if ((tempws > 127) || (tempws < -128)) {
flags_rebuild(); x86_int(0);
flags|=0x8D5; /*Not a Cyrix*/ return 1;
} }
}
else tempws = (int8_t) tempws;
{ tempws2 = (int8_t) ((int)((int16_t)AX)) % ((int)((int8_t)dst));
x86_int(0);
return 1; AH = (uint8_t) tempws2;
} AL = (uint8_t) tempws;
if (!cpu_iscyrix) {
flags_rebuild();
flags|=0x8D5; /*Not a Cyrix*/
}
CLOCK_CYCLES(19); CLOCK_CYCLES(19);
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break; break;
@@ -225,23 +231,29 @@ static int opF6_a32(uint32_t fetchdat)
PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); PREFETCH_RUN(is486 ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break; break;
case 0x38: /*IDIV AL,b*/ case 0x38: /*IDIV AL,b*/
tempws = (int)(int16_t)AX; if (dst == 0) {
if (dst != 0) tempws2 = tempws / (int)((int8_t)dst); x86_int(0); /* Divide by zero. */
if (dst && ((tempws2 > 0x0000007F) || (tempws2 < 0xFFFFFF80))) return 1;
{ }
AH = (tempws % (int)((int8_t)dst)) & 0xff;
AL = tempws2 & 0xff; tempws = ((int)((int16_t)AX)) / ((int)((int8_t)dst));
if (!cpu_iscyrix)
{ if ((tempws > 127) || (tempws < -128)) {
flags_rebuild(); x86_int(0);
flags|=0x8D5; /*Not a Cyrix*/ return 1;
} }
}
else tempws = (int8_t) tempws;
{ tempws2 = (int8_t) ((int)((int16_t)AX)) % ((int)((int8_t)dst));
x86_int(0);
return 1; AH = (uint8_t) tempws2;
} AL = (uint8_t) tempws;
if (!cpu_iscyrix) {
flags_rebuild();
flags|=0x8D5; /*Not a Cyrix*/
}
CLOCK_CYCLES(19); CLOCK_CYCLES(19);
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break; break;
@@ -258,7 +270,8 @@ static int opF6_a32(uint32_t fetchdat)
static int opF7_w_a16(uint32_t fetchdat) static int opF7_w_a16(uint32_t fetchdat)
{ {
uint32_t templ, templ2; uint32_t templ, templ2;
int tempws, tempws2 = 0; uint32_t tempsrc;
int32_t tempws, tempws2 = 0;
uint16_t src, dst; uint16_t src, dst;
fetch_ea_16(fetchdat); fetch_ea_16(fetchdat);
@@ -321,20 +334,28 @@ static int opF7_w_a16(uint32_t fetchdat)
CLOCK_CYCLES(is486 ? 24 : 22); CLOCK_CYCLES(is486 ? 24 : 22);
PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break; break;
case 0x38: /*IDIV AX,w*/ case 0x38: /*IDIV DX:AX,w*/
tempws = (int)((DX << 16)|AX); if (dst == 0) {
if (dst) tempws2 = tempws / (int)((int16_t)dst); x86_int(0); /* Divide by zero. */
if ((dst != 0) && ((tempws2 > 0x00007FFF) || (tempws2 < 0xFFFF8000))) return 1;
{ }
DX = tempws % (int)((int16_t)dst);
AX = tempws2 & 0xffff; tempsrc = (DX << 16) | AX;
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ tempws = ((int32_t)tempsrc) / ((int32_t)((int16_t)dst));
}
else if ((tempws > 32767) || (tempws < -32768)) {
{ x86_int(0);
x86_int(0); return 1;
return 1; }
}
tempws = (int16_t) tempws;
tempws2 = (int16_t) ((int32_t)tempsrc) % ((int32_t)((int16_t)dst));
DX = (uint16_t) tempws2;
AX = (uint16_t) tempws;
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
CLOCK_CYCLES(27); CLOCK_CYCLES(27);
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0); PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break; break;
@@ -348,6 +369,7 @@ static int opF7_w_a16(uint32_t fetchdat)
static int opF7_w_a32(uint32_t fetchdat) static int opF7_w_a32(uint32_t fetchdat)
{ {
uint32_t templ, templ2; uint32_t templ, templ2;
uint32_t tempsrc;
int tempws, tempws2 = 0; int tempws, tempws2 = 0;
uint16_t src, dst; uint16_t src, dst;
@@ -411,20 +433,28 @@ static int opF7_w_a32(uint32_t fetchdat)
CLOCK_CYCLES(is486 ? 24 : 22); CLOCK_CYCLES(is486 ? 24 : 22);
PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); PREFETCH_RUN(is486 ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break; break;
case 0x38: /*IDIV AX,w*/ case 0x38: /*IDIV DX:AX,w*/
tempws = (int)((DX << 16)|AX); if (dst == 0) {
if (dst) tempws2 = tempws / (int)((int16_t)dst); x86_int(0); /* Divide by zero. */
if ((dst != 0) && ((tempws2 > 0x00007FFF) || (tempws2 < 0xFFFF8000))) return 1;
{ }
DX = tempws % (int)((int16_t)dst);
AX = tempws2 & 0xffff; tempsrc = (DX << 16) | AX;
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/ tempws = ((int32_t)tempsrc) / ((int32_t)((int16_t)dst));
}
else if ((tempws > 32767) || (tempws < -32768)) {
{ x86_int(0);
x86_int(0); return 1;
return 1; }
}
tempws = (int16_t) tempws;
tempws2 = (int16_t) ((int32_t)tempsrc) % ((int32_t)((int16_t)dst));
DX = (uint16_t) tempws2;
AX = (uint16_t) tempws;
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
CLOCK_CYCLES(27); CLOCK_CYCLES(27);
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1); PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break; break;