Bochs/bochs/cpu/mult64.cc

209 lines
5.5 KiB
C++
Raw Normal View History

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001-2018 The Bochs Project
//
// 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
/////////////////////////////////////////////////////////////////////////
#define NEED_CPU_REG_SHORTCUTS 1
#include "bochs.h"
#include "cpu.h"
#define LOG_THIS BX_CPU_THIS_PTR
#include "wide_int.h"
#if BX_SUPPORT_X86_64
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_RAXEqR(bxInstruction_c *i)
{
Bit128u product_128;
2008-02-03 00:46:54 +03:00
Bit64u op1_64 = RAX;
Bit64u op2_64 = BX_READ_64BIT_REG(i->src());
// product_128 = ((Bit128u) op1_64) * ((Bit128u) op2_64);
// product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF);
// product_64h = (Bit64u) (product_128 >> 64);
long_mul(&product_128,op1_64,op2_64);
/* now write product back to destination */
RAX = product_128.lo;
RDX = product_128.hi;
2007-11-30 00:45:10 +03:00
/* set EFLAGS */
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();
}
BX_NEXT_INSTR(i);
}
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_RAXEqR(bxInstruction_c *i)
{
Bit128s product_128;
Bit64s op1_64 = RAX;
Bit64s op2_64 = BX_READ_64BIT_REG(i->src());
// product_128 = ((Bit128s) op1_64) * ((Bit128s) op2_64);
// product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF);
// product_64h = (Bit64u) (product_128 >> 64);
long_imul(&product_128,op1_64,op2_64);
/* now write product back to destination */
RAX = product_128.lo;
RDX = product_128.hi;
/* set eflags:
* IMUL r/m64: condition for clearing CF & OF:
* RDX:RAX = sign-extend of RAX
*/
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();
}
BX_NEXT_INSTR(i);
}
void BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_RAXEqR(bxInstruction_c *i)
{
Bit64u remainder_64, quotient_64l;
Bit128u op1_128, quotient_128;
Bit64u op2_64 = BX_READ_64BIT_REG(i->src());
if (op2_64 == 0) {
exception(BX_DE_EXCEPTION, 0);
}
2004-04-07 23:23:06 +04:00
op1_128.lo = RAX;
op1_128.hi = RDX;
// 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
long_div(&quotient_128,&remainder_64,&op1_128,op2_64);
quotient_64l = quotient_128.lo;
if (quotient_128.hi != 0)
exception(BX_DE_EXCEPTION, 0);
/* set EFLAGS:
* DIV affects the following flags: O,S,Z,A,P,C are undefined
*/
/* now write quotient back to destination */
RAX = quotient_64l;
RDX = remainder_64;
BX_NEXT_INSTR(i);
}
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_RAXEqR(bxInstruction_c *i)
{
Bit64s remainder_64, quotient_64l;
Bit128s op1_128, quotient_128;
op1_128.lo = RAX;
op1_128.hi = RDX;
/* check MIN_INT case */
if ((op1_128.hi == (Bit64s) BX_CONST64(0x8000000000000000)) && (!op1_128.lo))
exception(BX_DE_EXCEPTION, 0);
Bit64s op2_64 = BX_READ_64BIT_REG(i->src());
2008-02-03 00:46:54 +03:00
if (op2_64 == 0) {
exception(BX_DE_EXCEPTION, 0);
}
// 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
long_idiv(&quotient_128,&remainder_64,&op1_128,op2_64);
quotient_64l = quotient_128.lo;
2007-10-02 01:08:26 +04:00
if ((!(quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) 0) ||
((quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) BX_CONST64(0xffffffffffffffff)))
{
exception(BX_DE_EXCEPTION, 0);
}
/* set EFLAGS:
* IDIV affects the following flags: O,S,Z,A,P,C are undefined
*/
/* now write quotient back to destination */
RAX = quotient_64l;
RDX = remainder_64;
BX_NEXT_INSTR(i);
}
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqIdR(bxInstruction_c *i)
{
Bit128s product_128;
Bit64s op1_64 = BX_READ_64BIT_REG(i->src());
Bit64s op2_64 = (Bit32s) i->Id();
long_imul(&product_128,op1_64,op2_64);
/* now write product back to destination */
BX_WRITE_64BIT_REG(i->dst(), product_128.lo);
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();
}
BX_NEXT_INSTR(i);
}
void BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqR(bxInstruction_c *i)
{
Bit128s product_128;
Bit64s op1_64 = BX_READ_64BIT_REG(i->dst());
Bit64s op2_64 = BX_READ_64BIT_REG(i->src());
long_imul(&product_128,op1_64,op2_64);
/* now write product back to destination */
BX_WRITE_64BIT_REG(i->dst(), product_128.lo);
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();
}
BX_NEXT_INSTR(i);
}
- apply patch.ifdef-disabled-options. Comments from that patch are below: For a whole lot of configure options, I put #if...#endif around code that is specific to the option, even in files which are normally only compiled when the option is on. This allows me to create a MS Visual C++ 6.0 workspace that supports many of these options. The workspace will basically compile every file all the time, but the code for disabled options will be commented out by the #if...#endif. This may one day lead to simplification of the Makefiles and configure scripts, but for the moment I'm leaving Makefiles and configure scripts alone. Affected options: BX_SUPPORT_APIC (cpu/apic.cc) BX_SUPPORT_X86_64 (cpu/*64.cc) BX_DEBUGGER (debug/*) BX_DISASM (disasm/*) BX_WITH_nameofgui (gui/*) BX_SUPPORT_CDROM (iodev/cdrom.cc) BX_NE2K_SUPPORT (iodev/eth*.cc, iodev/ne2k.cc) BX_SUPPORT_APIC (iodev/ioapic.cc) BX_IODEBUG_SUPPORT (iodev/iodebug.cc) BX_PCI_SUPPORT (iodev/pci*.cc) BX_SUPPORT_SB16 (iodev/sb*.cc) Modified Files: cpu/apic.cc cpu/arith64.cc cpu/ctrl_xfer64.cc cpu/data_xfer64.cc cpu/fetchdecode64.cc cpu/logical64.cc cpu/mult64.cc cpu/resolve64.cc cpu/shift64.cc cpu/stack64.cc debug/Makefile.in debug/crc.cc debug/dbg_main.cc debug/lexer.l debug/linux.cc debug/parser.c debug/parser.y disasm/dis_decode.cc disasm/dis_groups.cc gui/amigaos.cc gui/beos.cc gui/carbon.cc gui/macintosh.cc gui/rfb.cc gui/sdl.cc gui/term.cc gui/win32.cc gui/wx.cc gui/wxdialog.cc gui/wxmain.cc gui/x.cc iodev/cdrom.cc iodev/eth.cc iodev/eth_arpback.cc iodev/eth_fbsd.cc iodev/eth_linux.cc iodev/eth_null.cc iodev/eth_packetmaker.cc iodev/eth_tap.cc iodev/eth_tuntap.cc iodev/eth_win32.cc iodev/ioapic.cc iodev/iodebug.cc iodev/ne2k.cc iodev/pci.cc iodev/pci2isa.cc iodev/sb16.cc iodev/soundlnx.cc iodev/soundwin.cc
2002-11-19 08:47:45 +03:00
#endif /* if BX_SUPPORT_X86_64 */