2002-09-13 19:53:22 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2011-02-25 00:54:04 +03:00
|
|
|
// $Id$
|
2002-09-13 19:53:22 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2018-02-16 10:57:32 +03:00
|
|
|
// Copyright (C) 2001-2018 The Bochs Project
|
2002-09-13 19:53:22 +04:00
|
|
|
//
|
|
|
|
// This library is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation; either
|
|
|
|
// version 2 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
|
|
// License along with this library; if not, write to the Free Software
|
2009-01-16 21:18:59 +03:00
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
|
2007-11-18 02:28:33 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2002-09-13 19:53:22 +04:00
|
|
|
|
|
|
|
#define NEED_CPU_REG_SHORTCUTS 1
|
|
|
|
#include "bochs.h"
|
2006-03-07 01:03:16 +03:00
|
|
|
#include "cpu.h"
|
2002-09-13 19:53:22 +04:00
|
|
|
#define LOG_THIS BX_CPU_THIS_PTR
|
|
|
|
|
2020-05-19 19:01:23 +03:00
|
|
|
#include "wide_int.h"
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2020-05-19 19:01:23 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2018-02-16 10:57:32 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_RAXEqR(bxInstruction_c *i)
|
2002-09-13 19:53:22 +04:00
|
|
|
{
|
2005-05-13 18:15:35 +04:00
|
|
|
Bit128u product_128;
|
2008-02-03 00:46:54 +03:00
|
|
|
|
2008-08-11 01:16:12 +04:00
|
|
|
Bit64u op1_64 = RAX;
|
2012-08-05 17:52:40 +04:00
|
|
|
Bit64u op2_64 = BX_READ_64BIT_REG(i->src());
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
// product_128 = ((Bit128u) op1_64) * ((Bit128u) op2_64);
|
|
|
|
// product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF);
|
|
|
|
// product_64h = (Bit64u) (product_128 >> 64);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
long_mul(&product_128,op1_64,op2_64);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* now write product back to destination */
|
|
|
|
RAX = product_128.lo;
|
|
|
|
RDX = product_128.hi;
|
2007-11-30 00:45:10 +03:00
|
|
|
|
|
|
|
/* set EFLAGS */
|
2007-12-06 19:57:59 +03:00
|
|
|
SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
|
|
|
|
if(product_128.hi != 0)
|
|
|
|
{
|
2017-10-16 01:01:32 +03:00
|
|
|
BX_CPU_THIS_PTR oszapc.assert_flags_OxxxxC();
|
2007-12-06 19:57:59 +03:00
|
|
|
}
|
2011-07-07 00:01:18 +04:00
|
|
|
|
|
|
|
BX_NEXT_INSTR(i);
|
2002-09-13 19:53:22 +04:00
|
|
|
}
|
|
|
|
|
2018-02-16 10:57:32 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_RAXEqR(bxInstruction_c *i)
|
2002-09-13 19:53:22 +04:00
|
|
|
{
|
2005-05-13 18:15:35 +04:00
|
|
|
Bit128s product_128;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2008-08-11 01:16:12 +04:00
|
|
|
Bit64s op1_64 = RAX;
|
2012-08-05 17:52:40 +04:00
|
|
|
Bit64s op2_64 = BX_READ_64BIT_REG(i->src());
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
// product_128 = ((Bit128s) op1_64) * ((Bit128s) op2_64);
|
|
|
|
// product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF);
|
|
|
|
// product_64h = (Bit64u) (product_128 >> 64);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
long_imul(&product_128,op1_64,op2_64);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* now write product back to destination */
|
|
|
|
RAX = product_128.lo;
|
|
|
|
RDX = product_128.hi;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* set eflags:
|
|
|
|
* IMUL r/m64: condition for clearing CF & OF:
|
|
|
|
* RDX:RAX = sign-extend of RAX
|
|
|
|
*/
|
2007-12-06 19:57:59 +03:00
|
|
|
|
2010-04-15 23:50:57 +04:00
|
|
|
SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
|
2009-10-27 21:30:13 +03:00
|
|
|
|
2010-04-15 23:50:57 +04:00
|
|
|
/* magic compare between RDX:RAX and sign extended RAX */
|
2009-10-27 21:30:13 +03:00
|
|
|
if (((Bit64u)(product_128.hi) + (product_128.lo >> 63)) != 0) {
|
2017-10-16 01:01:32 +03:00
|
|
|
BX_CPU_THIS_PTR oszapc.assert_flags_OxxxxC();
|
2007-12-06 19:57:59 +03:00
|
|
|
}
|
2011-07-07 00:01:18 +04:00
|
|
|
|
|
|
|
BX_NEXT_INSTR(i);
|
2002-09-13 19:53:22 +04:00
|
|
|
}
|
|
|
|
|
2018-02-16 10:57:32 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_RAXEqR(bxInstruction_c *i)
|
2002-09-13 19:53:22 +04:00
|
|
|
{
|
2008-08-11 01:16:12 +04:00
|
|
|
Bit64u remainder_64, quotient_64l;
|
2005-05-13 18:15:35 +04:00
|
|
|
Bit128u op1_128, quotient_128;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2012-08-05 17:52:40 +04:00
|
|
|
Bit64u op2_64 = BX_READ_64BIT_REG(i->src());
|
2005-05-13 18:15:35 +04:00
|
|
|
if (op2_64 == 0) {
|
2010-03-14 18:51:27 +03:00
|
|
|
exception(BX_DE_EXCEPTION, 0);
|
2005-05-13 18:15:35 +04:00
|
|
|
}
|
2004-04-07 23:23:06 +04:00
|
|
|
|
2008-08-11 01:16:12 +04:00
|
|
|
op1_128.lo = RAX;
|
|
|
|
op1_128.hi = RDX;
|
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
// quotient_128 = op1_128 / op2_64;
|
|
|
|
// remainder_64 = (Bit64u) (op1_128 % op2_64);
|
|
|
|
// quotient_64l = (Bit64u) (quotient_128 & 0xFFFFFFFFFFFFFFFF);
|
2004-04-07 23:23:06 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
long_div("ient_128,&remainder_64,&op1_128,op2_64);
|
|
|
|
quotient_64l = quotient_128.lo;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
if (quotient_128.hi != 0)
|
2010-03-14 18:51:27 +03:00
|
|
|
exception(BX_DE_EXCEPTION, 0);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* set EFLAGS:
|
|
|
|
* DIV affects the following flags: O,S,Z,A,P,C are undefined
|
|
|
|
*/
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* now write quotient back to destination */
|
|
|
|
RAX = quotient_64l;
|
|
|
|
RDX = remainder_64;
|
2011-07-07 00:01:18 +04:00
|
|
|
|
|
|
|
BX_NEXT_INSTR(i);
|
2002-09-13 19:53:22 +04:00
|
|
|
}
|
|
|
|
|
2018-02-16 10:57:32 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_RAXEqR(bxInstruction_c *i)
|
2002-09-13 19:53:22 +04:00
|
|
|
{
|
2008-08-11 01:16:12 +04:00
|
|
|
Bit64s remainder_64, quotient_64l;
|
2005-05-13 18:15:35 +04:00
|
|
|
Bit128s op1_128, quotient_128;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
op1_128.lo = RAX;
|
|
|
|
op1_128.hi = RDX;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2008-08-11 01:16:12 +04:00
|
|
|
/* check MIN_INT case */
|
|
|
|
if ((op1_128.hi == (Bit64s) BX_CONST64(0x8000000000000000)) && (!op1_128.lo))
|
2010-03-14 18:51:27 +03:00
|
|
|
exception(BX_DE_EXCEPTION, 0);
|
2008-08-11 01:16:12 +04:00
|
|
|
|
2012-08-05 17:52:40 +04:00
|
|
|
Bit64s op2_64 = BX_READ_64BIT_REG(i->src());
|
2008-02-03 00:46:54 +03:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
if (op2_64 == 0) {
|
2010-03-14 18:51:27 +03:00
|
|
|
exception(BX_DE_EXCEPTION, 0);
|
2005-05-13 18:15:35 +04:00
|
|
|
}
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
// quotient_128 = op1_128 / op2_64;
|
|
|
|
// remainder_64 = (Bit64s) (op1_128 % op2_64);
|
|
|
|
// quotient_64l = (Bit64s) (quotient_128 & 0xFFFFFFFFFFFFFFFF);
|
2004-04-07 23:23:06 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
long_idiv("ient_128,&remainder_64,&op1_128,op2_64);
|
|
|
|
quotient_64l = quotient_128.lo;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2007-10-02 01:08:26 +04:00
|
|
|
if ((!(quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) 0) ||
|
2011-04-25 19:20:27 +04:00
|
|
|
((quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) BX_CONST64(0xffffffffffffffff)))
|
2005-05-13 18:15:35 +04:00
|
|
|
{
|
2010-03-14 18:51:27 +03:00
|
|
|
exception(BX_DE_EXCEPTION, 0);
|
2005-05-13 18:15:35 +04:00
|
|
|
}
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* set EFLAGS:
|
|
|
|
* IDIV affects the following flags: O,S,Z,A,P,C are undefined
|
|
|
|
*/
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* now write quotient back to destination */
|
|
|
|
RAX = quotient_64l;
|
|
|
|
RDX = remainder_64;
|
2011-07-07 00:01:18 +04:00
|
|
|
|
|
|
|
BX_NEXT_INSTR(i);
|
2002-09-13 19:53:22 +04:00
|
|
|
}
|
|
|
|
|
2018-02-16 10:57:32 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqIdR(bxInstruction_c *i)
|
2002-09-13 19:53:22 +04:00
|
|
|
{
|
2005-05-13 18:15:35 +04:00
|
|
|
Bit128s product_128;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2012-08-05 17:52:40 +04:00
|
|
|
Bit64s op1_64 = BX_READ_64BIT_REG(i->src());
|
2011-04-25 19:20:27 +04:00
|
|
|
Bit64s op2_64 = (Bit32s) i->Id();
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2011-04-25 19:20:27 +04:00
|
|
|
long_imul(&product_128,op1_64,op2_64);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* now write product back to destination */
|
2012-08-05 17:52:40 +04:00
|
|
|
BX_WRITE_64BIT_REG(i->dst(), product_128.lo);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2007-12-06 19:57:59 +03:00
|
|
|
SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
|
2009-10-27 21:30:13 +03:00
|
|
|
|
|
|
|
if (((Bit64u)(product_128.hi) + (product_128.lo >> 63)) != 0) {
|
2017-10-16 01:01:32 +03:00
|
|
|
BX_CPU_THIS_PTR oszapc.assert_flags_OxxxxC();
|
2007-12-06 19:57:59 +03:00
|
|
|
}
|
2011-07-07 00:01:18 +04:00
|
|
|
|
|
|
|
BX_NEXT_INSTR(i);
|
2002-09-13 19:53:22 +04:00
|
|
|
}
|
|
|
|
|
2018-02-16 10:57:32 +03:00
|
|
|
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqR(bxInstruction_c *i)
|
2002-09-13 19:53:22 +04:00
|
|
|
{
|
2005-05-13 18:15:35 +04:00
|
|
|
Bit128s product_128;
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2012-08-05 17:52:40 +04:00
|
|
|
Bit64s op1_64 = BX_READ_64BIT_REG(i->dst());
|
|
|
|
Bit64s op2_64 = BX_READ_64BIT_REG(i->src());
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
long_imul(&product_128,op1_64,op2_64);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2005-05-13 18:15:35 +04:00
|
|
|
/* now write product back to destination */
|
2012-08-05 17:52:40 +04:00
|
|
|
BX_WRITE_64BIT_REG(i->dst(), product_128.lo);
|
2002-09-13 19:53:22 +04:00
|
|
|
|
2007-12-06 19:57:59 +03:00
|
|
|
SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo);
|
2009-10-27 21:30:13 +03:00
|
|
|
|
|
|
|
if (((Bit64u)(product_128.hi) + (product_128.lo >> 63)) != 0) {
|
2017-10-16 01:01:32 +03:00
|
|
|
BX_CPU_THIS_PTR oszapc.assert_flags_OxxxxC();
|
2007-12-06 19:57:59 +03:00
|
|
|
}
|
2011-07-07 00:01:18 +04:00
|
|
|
|
|
|
|
BX_NEXT_INSTR(i);
|
2002-09-13 19:53:22 +04:00
|
|
|
}
|
2002-11-19 08:47:45 +03:00
|
|
|
|
|
|
|
#endif /* if BX_SUPPORT_X86_64 */
|