Fixed bug [ 912496 ] IDIV can cause simulator divide error

This commit is contained in:
Stanislav Shwartsman 2004-08-18 19:27:52 +00:00
parent 91ac899439
commit 729e0abd2a
4 changed files with 52 additions and 75 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: mult16.cc,v 1.13 2004-08-14 19:34:02 sshwarts Exp $
// $Id: mult16.cc,v 1.14 2004-08-18 19:27:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -35,7 +35,6 @@ BX_CPU_C::MUL_AXEw(bxInstruction_c *i)
{
Bit16u op1_16, op2_16, product_16h, product_16l;
Bit32u product_32;
bx_bool temp_flag;
op1_16 = AX;
@ -49,12 +48,10 @@ BX_CPU_C::MUL_AXEw(bxInstruction_c *i)
}
product_32 = ((Bit32u) op1_16) * ((Bit32u) op2_16);
product_16l = (product_32 & 0xFFFF);
product_16h = product_32 >> 16;
/* now write product back to destination */
AX = product_16l;
DX = product_16h;
@ -62,11 +59,10 @@ BX_CPU_C::MUL_AXEw(bxInstruction_c *i)
* MUL affects the following flags: C,O
*/
temp_flag = (product_16h != 0);
bx_bool temp_flag = (product_16h != 0);
SET_FLAGS_OxxxxC(temp_flag, temp_flag);
}
void
BX_CPU_C::IMUL_AXEw(bxInstruction_c *i)
{
@ -86,12 +82,10 @@ BX_CPU_C::IMUL_AXEw(bxInstruction_c *i)
}
product_32 = ((Bit32s) op1_16) * ((Bit32s) op2_16);
product_16l = (product_32 & 0xFFFF);
product_16h = product_32 >> 16;
/* now write product back to destination */
AX = product_16l;
DX = product_16h;
@ -112,7 +106,6 @@ BX_CPU_C::IMUL_AXEw(bxInstruction_c *i)
}
}
void
BX_CPU_C::DIV_AXEw(bxInstruction_c *i)
{
@ -130,16 +123,15 @@ BX_CPU_C::DIV_AXEw(bxInstruction_c *i)
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
if (op2_16 == 0) {
if (op2_16 == 0)
exception(BX_DE_EXCEPTION, 0, 0);
}
quotient_32 = op1_32 / op2_16;
remainder_16 = op1_32 % op2_16;
quotient_16l = quotient_32 & 0xFFFF;
if (quotient_32 != quotient_16l) {
if (quotient_32 != quotient_16l)
exception(BX_DE_EXCEPTION, 0, 0);
}
/* set EFLAGS:
* DIV affects the following flags: O,S,Z,A,P,C are undefined
@ -172,16 +164,19 @@ BX_CPU_C::IDIV_AXEw(bxInstruction_c *i)
read_virtual_word(i->seg(), RMAddr(i), (Bit16u *) &op2_16);
}
if (op2_16 == 0) {
if (op2_16 == 0)
exception(BX_DE_EXCEPTION, 0, 0);
}
/* check MIN_INT divided by -1 case */
if (op1_32 == BX_MIN_BIT32S && op2_16 == -1)
exception(BX_DE_EXCEPTION, 0, 0);
quotient_32 = op1_32 / op2_16;
remainder_16 = op1_32 % op2_16;
quotient_16l = quotient_32 & 0xFFFF;
if (quotient_32 != quotient_16l) {
if (quotient_32 != quotient_16l)
exception(BX_DE_EXCEPTION, 0, 0);
}
/* set EFLAGS:
* IDIV affects the following flags: O,S,Z,A,P,C are undefined
@ -196,7 +191,6 @@ BX_CPU_C::IDIV_AXEw(bxInstruction_c *i)
DX = remainder_16;
}
void
BX_CPU_C::IMUL_GwEwIw(bxInstruction_c *i)
{

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: mult32.cc,v 1.13 2004-08-13 20:00:03 sshwarts Exp $
// $Id: mult32.cc,v 1.14 2004-08-18 19:27:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -42,7 +42,6 @@ BX_CPU_C::MUL_EAXEd(bxInstruction_c *i)
{
Bit32u op1_32, op2_32, product_32h, product_32l;
Bit64u product_64;
bx_bool temp_flag;
op1_32 = EAX;
@ -56,12 +55,10 @@ BX_CPU_C::MUL_EAXEd(bxInstruction_c *i)
}
product_64 = ((Bit64u) op1_32) * ((Bit64u) op2_32);
product_32l = (Bit32u) (product_64 & 0xFFFFFFFF);
product_32h = (Bit32u) (product_64 >> 32);
/* now write product back to destination */
RAX = product_32l;
RDX = product_32h;
@ -69,11 +66,10 @@ BX_CPU_C::MUL_EAXEd(bxInstruction_c *i)
* MUL affects the following flags: C,O
*/
temp_flag = (product_32h != 0);
bx_bool temp_flag = (product_32h != 0);
SET_FLAGS_OxxxxC(temp_flag, temp_flag);
}
void
BX_CPU_C::IMUL_EAXEd(bxInstruction_c *i)
{
@ -93,12 +89,10 @@ BX_CPU_C::IMUL_EAXEd(bxInstruction_c *i)
}
product_64 = ((Bit64s) op1_32) * ((Bit64s) op2_32);
product_32l = (Bit32u) (product_64 & 0xFFFFFFFF);
product_32h = (Bit32u) (product_64 >> 32);
/* now write product back to destination */
RAX = product_32l;
RDX = product_32h;
@ -119,7 +113,6 @@ BX_CPU_C::IMUL_EAXEd(bxInstruction_c *i)
}
}
void
BX_CPU_C::DIV_EAXEd(bxInstruction_c *i)
{
@ -159,7 +152,6 @@ BX_CPU_C::DIV_EAXEd(bxInstruction_c *i)
RDX = remainder_32;
}
void
BX_CPU_C::IDIV_EAXEd(bxInstruction_c *i)
{
@ -177,9 +169,12 @@ BX_CPU_C::IDIV_EAXEd(bxInstruction_c *i)
read_virtual_dword(i->seg(), RMAddr(i), (Bit32u *) &op2_32);
}
if (op2_32 == 0) {
if (op2_32 == 0)
exception(BX_DE_EXCEPTION, 0, 0);
/* check MIN_INT divided by -1 case */
if (op1_64 == BX_MIN_BIT64S && op2_32 == -1)
exception(BX_DE_EXCEPTION, 0, 0);
}
quotient_64 = op1_64 / op2_32;
remainder_32 = (Bit32s) (op1_64 % op2_32);
@ -199,7 +194,6 @@ BX_CPU_C::IDIV_EAXEd(bxInstruction_c *i)
RDX = remainder_32;
}
void
BX_CPU_C::IMUL_GdEdId(bxInstruction_c *i)
{

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: mult64.cc,v 1.9 2004-04-07 19:46:13 sshwarts Exp $
// $Id: mult64.cc,v 1.10 2004-08-18 19:27:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -25,7 +25,6 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#define LOG_THIS BX_CPU_THIS_PTR
@ -110,12 +109,9 @@ void long_shr(Bit128u *a)
unsigned long_sub(Bit128u *a,Bit128u *b)
{
Bit64u t;
int c;
t = a->lo;
Bit64u t = a->lo;
a->lo -= b->lo;
c = (a->lo > t);
int c = (a->lo > t);
t = a -> hi;
a->hi -= b->hi + c;
return(a->hi > t);
@ -214,7 +210,6 @@ BX_CPU_C::MUL_RAXEq(bxInstruction_c *i)
{
Bit64u op1_64, op2_64;
Bit128u product_128;
bx_bool temp_flag;
op1_64 = RAX;
@ -241,7 +236,7 @@ BX_CPU_C::MUL_RAXEq(bxInstruction_c *i)
* MUL affects the following flags: C,O
*/
temp_flag = (product_128.hi != 0);
bx_bool temp_flag = (product_128.hi != 0);
SET_FLAGS_OxxxxC(temp_flag, temp_flag);
}
@ -289,7 +284,6 @@ BX_CPU_C::IMUL_RAXEq(bxInstruction_c *i)
}
}
void
BX_CPU_C::DIV_RAXEq(bxInstruction_c *i)
{
@ -330,7 +324,6 @@ BX_CPU_C::DIV_RAXEq(bxInstruction_c *i)
RDX = remainder_64;
}
void
BX_CPU_C::IDIV_RAXEq(bxInstruction_c *i)
{
@ -352,6 +345,13 @@ BX_CPU_C::IDIV_RAXEq(bxInstruction_c *i)
if (op2_64 == 0)
exception(BX_DE_EXCEPTION, 0, 0);
/* check MIN_INT divided by -1 case */
if (op2_64 == -1)
{
if ((op1_128.ho == BX_CONT64(0x8000000000000000)) && (!op1_128.lo))
exception(BX_DE_EXCEPTION, 0, 0);
}
// quotient_128 = op1_128 / op2_64;
// remainder_64 = (Bit64s) (op1_128 % op2_64);
// quotient_64l = (Bit64s) (quotient_128 & 0xFFFFFFFFFFFFFFFF);
@ -371,7 +371,6 @@ BX_CPU_C::IDIV_RAXEq(bxInstruction_c *i)
RDX = remainder_64;
}
void
BX_CPU_C::IMUL_GqEqId(bxInstruction_c *i)
{

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: mult8.cc,v 1.13 2004-08-13 20:00:03 sshwarts Exp $
// $Id: mult8.cc,v 1.14 2004-08-18 19:27:52 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -34,8 +34,6 @@
BX_CPU_C::MUL_ALEb(bxInstruction_c *i)
{
Bit8u op2, op1;
Bit16u product_16;
bx_bool temp_flag;
op1 = AL;
@ -48,26 +46,23 @@ BX_CPU_C::MUL_ALEb(bxInstruction_c *i)
read_virtual_byte(i->seg(), RMAddr(i), &op2);
}
product_16 = op1 * op2;
Bit16u product_16 = op1 * op2;
/* set EFLAGS:
* MUL affects the following flags: C,O
*/
temp_flag = ((product_16 & 0xFF00) != 0);
bx_bool temp_flag = ((product_16 & 0xFF00) != 0);
SET_FLAGS_OxxxxC(temp_flag, temp_flag);
/* now write product back to destination */
AX = product_16;
}
void
BX_CPU_C::IMUL_ALEb(bxInstruction_c *i)
{
Bit8s op2, op1;
Bit16s product_16;
Bit16u upper_bits;
op1 = AL;
@ -80,7 +75,7 @@ BX_CPU_C::IMUL_ALEb(bxInstruction_c *i)
read_virtual_byte(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
product_16 = op1 * op2;
Bit16s product_16 = op1 * op2;
/* now write product back to destination */
AX = product_16;
@ -90,7 +85,7 @@ BX_CPU_C::IMUL_ALEb(bxInstruction_c *i)
* IMUL r/m8: condition for clearing CF & OF:
* AL = sign-extend of AL to 16 bits
*/
upper_bits = AX & 0xff80;
Bit16u upper_bits = AX & 0xff80;
if (upper_bits==0xff80 || upper_bits==0x0000) {
SET_FLAGS_OxxxxC(0, 0);
}
@ -99,7 +94,6 @@ BX_CPU_C::IMUL_ALEb(bxInstruction_c *i)
}
}
void
BX_CPU_C::DIV_ALEb(bxInstruction_c *i)
{
@ -143,7 +137,6 @@ BX_CPU_C::DIV_ALEb(bxInstruction_c *i)
AH = remainder_8;
}
void
BX_CPU_C::IDIV_ALEb(bxInstruction_c *i)
{
@ -161,22 +154,19 @@ BX_CPU_C::IDIV_ALEb(bxInstruction_c *i)
read_virtual_byte(i->seg(), RMAddr(i), (Bit8u *) &op2);
}
if (op2 == 0) {
if (op2 == 0)
exception(BX_DE_EXCEPTION, 0, 0);
/* check MIN_INT divided by -1 case */
if (op1 == BX_MIN_BIT16S && op2 == -1)
exception(BX_DE_EXCEPTION, 0, 0);
}
quotient_16 = op1 / op2;
remainder_8 = op1 % op2;
quotient_8l = quotient_16 & 0xFF;
if (quotient_16 != quotient_8l) {
BX_INFO(("quotient_16: %04x, remainder_8: %02x, quotient_8l: %02x",
(unsigned) quotient_16, (unsigned) remainder_8, (unsigned) quotient_8l));
AL = quotient_8l;
AH = remainder_8;
BX_INFO(("AH: %02x, AL: %02x", (unsigned) AH, (unsigned) AL));
if (quotient_16 != quotient_8l)
exception(BX_DE_EXCEPTION, 0, 0);
}
/* set EFLAGS:
* DIV affects the following flags: O,S,Z,A,P,C are undefined