From 729e0abd2a5ea59183e89ae64a5d62d908bae1e5 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Wed, 18 Aug 2004 19:27:52 +0000 Subject: [PATCH] Fixed bug [ 912496 ] IDIV can cause simulator divide error --- bochs/cpu/mult16.cc | 42 ++++++++++++++++++------------------------ bochs/cpu/mult32.cc | 28 +++++++++++----------------- bochs/cpu/mult64.cc | 25 ++++++++++++------------- bochs/cpu/mult8.cc | 32 +++++++++++--------------------- 4 files changed, 52 insertions(+), 75 deletions(-) diff --git a/bochs/cpu/mult16.cc b/bochs/cpu/mult16.cc index 49acd4c74..4799c8ce8 100644 --- a/bochs/cpu/mult16.cc +++ b/bochs/cpu/mult16.cc @@ -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; @@ -48,13 +47,11 @@ BX_CPU_C::MUL_AXEw(bxInstruction_c *i) read_virtual_word(i->seg(), RMAddr(i), &op2_16); } - product_32 = ((Bit32u) op1_16) * ((Bit32u) op2_16); - + 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) { @@ -85,13 +81,11 @@ BX_CPU_C::IMUL_AXEw(bxInstruction_c *i) read_virtual_word(i->seg(), RMAddr(i), (Bit16u *) &op2_16); } - product_32 = ((Bit32s) op1_16) * ((Bit32s) op2_16); - + 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; + + 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); - } - quotient_32 = op1_32 / op2_16; + + /* 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) { @@ -215,7 +209,7 @@ BX_CPU_C::IMUL_GwEwIw(bxInstruction_c *i) read_virtual_word(i->seg(), RMAddr(i), (Bit16u *) &op2_16); } - product_32 = op2_16 * op3_16; + product_32 = op2_16 * op3_16; product_16l = (product_32 & 0xFFFF); /* now write product back to destination */ @@ -253,7 +247,7 @@ BX_CPU_C::IMUL_GwEw(bxInstruction_c *i) op1_16 = BX_READ_16BIT_REG(i->nnn()); - product_32 = op1_16 * op2_16; + product_32 = op1_16 * op2_16; product_16l = (product_32 & 0xFFFF); /* now write product back to destination */ diff --git a/bochs/cpu/mult32.cc b/bochs/cpu/mult32.cc index bfe0a1ab6..cda948657 100644 --- a/bochs/cpu/mult32.cc +++ b/bochs/cpu/mult32.cc @@ -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; @@ -55,13 +54,11 @@ BX_CPU_C::MUL_EAXEd(bxInstruction_c *i) read_virtual_dword(i->seg(), RMAddr(i), &op2_32); } - product_64 = ((Bit64u) op1_32) * ((Bit64u) op2_32); - + 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) { @@ -92,13 +88,11 @@ BX_CPU_C::IMUL_EAXEd(bxInstruction_c *i) read_virtual_dword(i->seg(), RMAddr(i), (Bit32u *) &op2_32); } - product_64 = ((Bit64s) op1_32) * ((Bit64s) op2_32); - + 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) { @@ -141,7 +134,7 @@ BX_CPU_C::DIV_EAXEd(bxInstruction_c *i) exception(BX_DE_EXCEPTION, 0, 0); } - quotient_64 = op1_64 / op2_32; + quotient_64 = op1_64 / op2_32; remainder_32 = (Bit32u) (op1_64 % op2_32); quotient_32l = (Bit32u) (quotient_64 & 0xFFFFFFFF); @@ -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,11 +169,14 @@ 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); - } - quotient_64 = op1_64 / op2_32; + /* 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); quotient_32l = (Bit32s) (quotient_64 & 0xFFFFFFFF); @@ -199,7 +194,6 @@ BX_CPU_C::IDIV_EAXEd(bxInstruction_c *i) RDX = remainder_32; } - void BX_CPU_C::IMUL_GdEdId(bxInstruction_c *i) { diff --git a/bochs/cpu/mult64.cc b/bochs/cpu/mult64.cc index 7d3d9d3f7..6bde9528c 100644 --- a/bochs/cpu/mult64.cc +++ b/bochs/cpu/mult64.cc @@ -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,8 +210,7 @@ BX_CPU_C::MUL_RAXEq(bxInstruction_c *i) { Bit64u op1_64, op2_64; Bit128u product_128; - bx_bool temp_flag; - + op1_64 = RAX; /* op2 is a register or memory reference */ @@ -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) { diff --git a/bochs/cpu/mult8.cc b/bochs/cpu/mult8.cc index 0c572a86b..62e6ed27c 100644 --- a/bochs/cpu/mult8.cc +++ b/bochs/cpu/mult8.cc @@ -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