Added ./configure option --enable-all-optimizations which turns on

all available optimizations in one shot.

Finished one last case of an instruction which could but didn't use
  the Read-Modify-Write variants of access.cc functions.

Started going through the integer instructions, merging obvious cases
  where there are two "if (modrm==11b) {" clauses and very little
  action in between, and cleaning up the aweful indentation leftover
  from many years ago when those instructions were implemented using
  cut-and-paste.  We may get a little extra performance out of these
  mods, but they'll also be easier after I'm finished to enhance
  with asm() statements to knock out the lazy flags processing on x86.
This commit is contained in:
Kevin Lawton 2002-09-30 02:02:06 +00:00
parent 81b1db7b47
commit 00c14e4efe
5 changed files with 4861 additions and 3010 deletions

6297
bochs/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@ dnl // Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
AC_INIT(bochs.h)
AC_REVISION([[$Id: configure.in,v 1.135 2002-09-27 20:06:57 bdenney Exp $]])
AC_REVISION([[$Id: configure.in,v 1.136 2002-09-30 02:02:05 kevinlawton Exp $]])
AC_CONFIG_HEADER(config.h)
dnl // Put Bochs version information right here so that it gets substituted
@ -605,14 +605,14 @@ AC_ARG_ENABLE(guest2host-tlb,
[ --enable-guest2host-tlb support guest to host addr TLB for speed],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(BX_SupportGuest2HostTLB, 1)
speedup_guest2host_tlb=1
else
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportGuest2HostTLB, 0)
speedup_guest2host_tlb=0
fi],
[
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportGuest2HostTLB, 0)
speedup_guest2host_tlb=0
]
)
@ -621,14 +621,14 @@ AC_ARG_ENABLE(repeat-speedups,
[ --enable-repeat-speedups support repeated IO and mem copy speedups],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(BX_SupportRepeatSpeedups, 1)
speedup_repeat=1
else
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportRepeatSpeedups, 0)
speedup_repeat=0
fi],
[
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportRepeatSpeedups, 0)
speedup_repeat=0
]
)
@ -637,14 +637,14 @@ AC_ARG_ENABLE(icache,
[ --enable-icache support instruction cache (runs faster)],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(BX_SupportICache, 1)
speedup_iCache=1
else
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportICache, 0)
speedup_iCache=0
fi],
[
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportICache, 0)
speedup_iCache=0
]
)
@ -675,14 +675,14 @@ AC_ARG_ENABLE(host-specific-asms,
[ --enable-host-specific-asms support for host specific inline assembly],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(BX_SupportHostAsms, 1)
speedup_host_specific_asms=1
else
AC_MSG_RESULT(no)
AC_DEFINE(BX_SupportHostAsms, 0)
speedup_host_specific_asms=0
fi],
[
AC_MSG_RESULT(yes)
AC_DEFINE(BX_SupportHostAsms, 1)
speedup_host_specific_asms=1
]
)
@ -833,6 +833,62 @@ AC_ARG_ENABLE(disasm,
)
AC_SUBST(DISASM_VAR)
AC_MSG_CHECKING(for ALL optimizations enabled)
AC_ARG_ENABLE(all-optimizations,
[ --enable-all-optimizations compile in all possible optimizations],
[if test "$enableval" = yes; then
AC_MSG_RESULT(yes)
speedups_all=1
else
AC_MSG_RESULT(no)
speedups_all=0
fi
],
[
AC_MSG_RESULT(no)
speedups_all=0
]
)
#
# Optimizations section. Decide what the status of various optimizations
# should be based on configure choices and other factors.
#
if test "$speedups_all" = 1; then
# Configure requested to force all options enabled.
speedup_guest2host_tlb=1
speedup_repeat=1
speedup_iCache=1
speedup_host_specific_asms=1
fi
if test "$speedup_guest2host_tlb" = 1; then
AC_DEFINE(BX_SupportGuest2HostTLB, 1)
else
AC_DEFINE(BX_SupportGuest2HostTLB, 0)
fi
if test "$speedup_repeat" = 1; then
AC_DEFINE(BX_SupportRepeatSpeedups, 1)
else
AC_DEFINE(BX_SupportRepeatSpeedups, 0)
fi
if test "$speedup_iCache" = 1; then
AC_DEFINE(BX_SupportICache, 1)
else
AC_DEFINE(BX_SupportICache, 0)
fi
if test "$speedup_host_specific_asms" = 1; then
AC_DEFINE(BX_SupportHostAsms, 1)
else
AC_DEFINE(BX_SupportHostAsms, 0)
fi
READLINE_LIB=""
rl_without_curses_ok=no
rl_with_curses_ok=no

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: arith16.cc,v 1.21 2002-09-29 19:21:36 kevinlawton Exp $
// $Id: arith16.cc,v 1.22 2002-09-30 02:02:06 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -86,32 +86,22 @@ BX_CPU_C::DEC_RX(bxInstruction_c *i)
void
BX_CPU_C::ADD_EwGw(bxInstruction_c *i)
{
Bit16u op2_16, op1_16, sum_16;
Bit16u op2_16, op1_16, sum_16;
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op2_16 is a register, RMAddr(i) is an index of a register */
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
sum_16 = op1_16 + op2_16;
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
sum_16 = op1_16 + op2_16;
Write_RMW_virtual_word(sum_16);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
write_virtual_word(i->seg(), RMAddr(i), &sum_16);
}
SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_INSTR_ADD16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_INSTR_ADD16);
}
@ -154,7 +144,6 @@ BX_CPU_C::ADD_GwEGw(bxInstruction_c *i)
Bit16u op1_16, op2_16, sum_16;
op1_16 = BX_READ_16BIT_REG(i->nnn());
op2_16 = BX_READ_16BIT_REG(i->rm());
#if (defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -185,18 +174,16 @@ BX_CPU_C::ADD_GwEGw(bxInstruction_c *i)
void
BX_CPU_C::ADD_AXIw(bxInstruction_c *i)
{
Bit16u op1_16, op2_16, sum_16;
Bit16u op1_16, op2_16, sum_16;
op1_16 = AX;
op1_16 = AX;
op2_16 = i->Iw();
op2_16 = i->Iw();
sum_16 = op1_16 + op2_16;
sum_16 = op1_16 + op2_16;
AX = sum_16;
/* now write sum back to destination */
AX = sum_16;
SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_INSTR_ADD16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_INSTR_ADD16);
}
void
@ -207,33 +194,21 @@ BX_CPU_C::ADC_EwGw(bxInstruction_c *i)
temp_CF = getB_CF();
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op2_16 is a register, RMAddr(i) is an index of a register */
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
sum_16 = op1_16 + op2_16 + temp_CF;
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
sum_16 = op1_16 + op2_16 + temp_CF;
Write_RMW_virtual_word(sum_16);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
Write_RMW_virtual_word(sum_16);
}
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
}
@ -246,25 +221,21 @@ BX_CPU_C::ADC_GwEw(bxInstruction_c *i)
temp_CF = getB_CF();
/* op1_16 is a register, RMAddr(i) is an index of a register */
op1_16 = BX_READ_16BIT_REG(i->nnn());
op1_16 = BX_READ_16BIT_REG(i->nnn());
/* op2_16 is a register or memory reference */
if (i->modC0()) {
op2_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
if (i->modC0()) {
op2_16 = BX_READ_16BIT_REG(i->rm());
}
else {
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
sum_16 = op1_16 + op2_16 + temp_CF;
sum_16 = op1_16 + op2_16 + temp_CF;
/* now write sum back to destination */
BX_WRITE_16BIT_REG(i->nnn(), sum_16);
BX_WRITE_16BIT_REG(i->nnn(), sum_16);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
}
@ -276,17 +247,15 @@ BX_CPU_C::ADC_AXIw(bxInstruction_c *i)
temp_CF = getB_CF();
op1_16 = AX;
op1_16 = AX;
op2_16 = i->Iw();
op2_16 = i->Iw();
sum_16 = op1_16 + op2_16 + temp_CF;
sum_16 = op1_16 + op2_16 + temp_CF;
AX = sum_16;
/* now write sum back to destination */
AX = sum_16;
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
}
@ -298,34 +267,23 @@ BX_CPU_C::SBB_EwGw(bxInstruction_c *i)
Boolean temp_CF;
Bit16u op2_16, op1_16, diff_16;
temp_CF = getB_CF();
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op2_16 is a register, RMAddr(i) is an index of a register */
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
diff_16 = op1_16 - (op2_16 + temp_CF);
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
diff_16 = op1_16 - (op2_16 + temp_CF);
Write_RMW_virtual_word(diff_16);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
Write_RMW_virtual_word(diff_16);
}
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
}
@ -336,29 +294,23 @@ BX_CPU_C::SBB_GwEw(bxInstruction_c *i)
temp_CF = getB_CF();
Bit16u op1_16, op2_16, diff_16;
Bit16u op1_16, op2_16, diff_16;
op1_16 = BX_READ_16BIT_REG(i->nnn());
if (i->modC0()) {
op2_16 = BX_READ_16BIT_REG(i->rm());
}
else {
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
/* op1_16 is a register, RMAddr(i) is an index of a register */
op1_16 = BX_READ_16BIT_REG(i->nnn());
diff_16 = op1_16 - (op2_16 + temp_CF);
/* op2_16 is a register or memory reference */
if (i->modC0()) {
op2_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
BX_WRITE_16BIT_REG(i->nnn(), diff_16);
diff_16 = op1_16 - (op2_16 + temp_CF);
/* now write diff back to destination */
BX_WRITE_16BIT_REG(i->nnn(), diff_16);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
}
@ -370,18 +322,15 @@ BX_CPU_C::SBB_AXIw(bxInstruction_c *i)
temp_CF = getB_CF();
op1_16 = AX;
op2_16 = i->Iw();
op1_16 = AX;
diff_16 = op1_16 - (op2_16 + temp_CF);
op2_16 = i->Iw();
AX = diff_16;
diff_16 = op1_16 - (op2_16 + temp_CF);
/* now write diff back to destination */
AX = diff_16;
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
}
@ -394,109 +343,80 @@ BX_CPU_C::SBB_EwIw(bxInstruction_c *i)
temp_CF = getB_CF();
op2_16 = i->Iw();
op2_16 = i->Iw();
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
diff_16 = op1_16 - (op2_16 + temp_CF);
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
diff_16 = op1_16 - (op2_16 + temp_CF);
Write_RMW_virtual_word(diff_16);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
Write_RMW_virtual_word(diff_16);
}
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, diff_16, BX_INSTR_SBB16,
temp_CF);
}
void
BX_CPU_C::SUB_EwGw(bxInstruction_c *i)
{
Bit16u op2_16, op1_16, diff_16;
Bit16u op2_16, op1_16, diff_16;
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op2_16 is a register, RMAddr(i) is an index of a register */
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
diff_16 = op1_16 - op2_16;
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
diff_16 = op1_16 - op2_16;
Write_RMW_virtual_word(diff_16);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
Write_RMW_virtual_word(diff_16);
}
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
}
void
BX_CPU_C::SUB_GwEw(bxInstruction_c *i)
{
Bit16u op1_16, op2_16, diff_16;
Bit16u op1_16, op2_16, diff_16;
op1_16 = BX_READ_16BIT_REG(i->nnn());
/* op1_16 is a register, RMAddr(i) is an index of a register */
op1_16 = BX_READ_16BIT_REG(i->nnn());
if (i->modC0()) {
op2_16 = BX_READ_16BIT_REG(i->rm());
}
else {
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
/* op2_16 is a register or memory reference */
if (i->modC0()) {
op2_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_word(i->seg(), RMAddr(i), &op2_16);
}
diff_16 = op1_16 - op2_16;
diff_16 = op1_16 - op2_16;
BX_WRITE_16BIT_REG(i->nnn(), diff_16);
/* now write diff back to destination */
BX_WRITE_16BIT_REG(i->nnn(), diff_16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
}
void
BX_CPU_C::SUB_AXIw(bxInstruction_c *i)
{
Bit16u op1_16, op2_16, diff_16;
Bit16u op1_16, op2_16, diff_16;
op1_16 = AX;
op1_16 = AX;
op2_16 = i->Iw();
op2_16 = i->Iw();
diff_16 = op1_16 - op2_16;
diff_16 = op1_16 - op2_16;
AX = diff_16;
/* now write diff back to destination */
AX = diff_16;
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
}
@ -578,7 +498,6 @@ BX_CPU_C::CMP_AXIw(bxInstruction_c *i)
Bit16u op1_16, op2_16;
op1_16 = AX;
op2_16 = i->Iw();
#if (defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -616,12 +535,12 @@ BX_CPU_C::CWD(bxInstruction_c *i)
{
/* CWD: no flags are affected */
if (AX & 0x8000) {
DX = 0xFFFF;
}
else {
DX = 0x0000;
}
if (AX & 0x8000) {
DX = 0xFFFF;
}
else {
DX = 0x0000;
}
}
@ -630,45 +549,35 @@ BX_CPU_C::XADD_EwGw(bxInstruction_c *i)
{
#if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
Bit16u op2_16, op1_16, sum_16;
Bit16u op2_16, op1_16, sum_16;
/* XADD dst(r/m), src(r)
* temp <-- src + dst | sum = op2 + op1
* src <-- dst | op2 = op1
* dst <-- tmp | op1 = sum
*/
/* XADD dst(r/m), src(r)
* temp <-- src + dst | sum = op2 + op1
* src <-- dst | op2 = op1
* dst <-- tmp | op1 = sum
*/
/* op2 is a register, RMAddr(i) is an index of a register */
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op1 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
op2_16 = BX_READ_16BIT_REG(i->nnn());
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
sum_16 = op1_16 + op2_16;
// and write destination into source
// Note: if both op1 & op2 are registers, the last one written
// should be the sum, as op1 & op2 may be the same register.
// For example: XADD AL, AL
BX_WRITE_16BIT_REG(i->nnn(), op1_16);
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
sum_16 = op1_16 + op2_16;
Write_RMW_virtual_word(sum_16);
/* and write destination into source */
BX_WRITE_16BIT_REG(i->nnn(), op1_16);
}
/* now write sum back to destination */
if (i->modC0()) {
// and write destination into source
// Note: if both op1 & op2 are registers, the last one written
// should be the sum, as op1 & op2 may be the same register.
// For example: XADD AL, AL
BX_WRITE_16BIT_REG(i->nnn(), op1_16);
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
Write_RMW_virtual_word(sum_16);
/* and write destination into source */
BX_WRITE_16BIT_REG(i->nnn(), op1_16);
}
SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_INSTR_XADD16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, sum_16, BX_INSTR_XADD16);
#else
BX_PANIC(("XADD_EvGv: not supported on < 80486"));
#endif
@ -750,61 +659,44 @@ BX_CPU_C::ADC_EwIw(bxInstruction_c *i)
temp_CF = getB_CF();
op2_16 = i->Iw();
op2_16 = i->Iw();
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
sum_16 = op1_16 + op2_16 + temp_CF;
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
sum_16 = op1_16 + op2_16 + temp_CF;
Write_RMW_virtual_word(sum_16);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), sum_16);
}
else {
Write_RMW_virtual_word(sum_16);
}
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
SET_FLAGS_OSZAPC_16_CF(op1_16, op2_16, sum_16, BX_INSTR_ADC16,
temp_CF);
}
void
BX_CPU_C::SUB_EwIw(bxInstruction_c *i)
{
Bit16u op2_16, op1_16, diff_16;
Bit16u op2_16, op1_16, diff_16;
op2_16 = i->Iw();
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
op2_16 = i->Iw();
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
diff_16 = op1_16 - op2_16;
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
diff_16 = op1_16 - op2_16;
Write_RMW_virtual_word(diff_16);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
Write_RMW_virtual_word(diff_16);
}
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
SET_FLAGS_OSZAPC_16(op1_16, op2_16, diff_16, BX_INSTR_SUB16);
}
void
@ -847,85 +739,61 @@ BX_CPU_C::CMP_EwIw(bxInstruction_c *i)
void
BX_CPU_C::NEG_Ew(bxInstruction_c *i)
{
Bit16u op1_16, diff_16;
Bit16u op1_16, diff_16;
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
diff_16 = 0 - op1_16;
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
diff_16 = 0 - op1_16;
Write_RMW_virtual_word(diff_16);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), diff_16);
}
else {
Write_RMW_virtual_word(diff_16);
}
SET_FLAGS_OSZAPC_16(op1_16, 0, diff_16, BX_INSTR_NEG16);
SET_FLAGS_OSZAPC_16(op1_16, 0, diff_16, BX_INSTR_NEG16);
}
void
BX_CPU_C::INC_Ew(bxInstruction_c *i)
{
Bit16u op1_16;
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
Bit16u op1_16;
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
op1_16++;
BX_WRITE_16BIT_REG(i->rm(), op1_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
op1_16++;
Write_RMW_virtual_word(op1_16);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), op1_16);
}
else {
Write_RMW_virtual_word(op1_16);
}
SET_FLAGS_OSZAP_16(0, 0, op1_16, BX_INSTR_INC16);
SET_FLAGS_OSZAP_16(0, 0, op1_16, BX_INSTR_INC16);
}
void
BX_CPU_C::DEC_Ew(bxInstruction_c *i)
{
Bit16u op1_16;
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
Bit16u op1_16;
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
op1_16--;
BX_WRITE_16BIT_REG(i->rm(), op1_16);
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
op1_16--;
Write_RMW_virtual_word(op1_16);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), op1_16);
}
else {
Write_RMW_virtual_word(op1_16);
}
SET_FLAGS_OSZAP_16(0, 0, op1_16, BX_INSTR_DEC16);
SET_FLAGS_OSZAP_16(0, 0, op1_16, BX_INSTR_DEC16);
}
@ -934,40 +802,38 @@ BX_CPU_C::CMPXCHG_EwGw(bxInstruction_c *i)
{
#if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
Bit16u op2_16, op1_16, diff_16;
Bit16u op2_16, op1_16, diff_16;
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
}
else {
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
diff_16 = AX - op1_16;
SET_FLAGS_OSZAPC_16(AX, op1_16, diff_16, BX_INSTR_CMP16);
if (diff_16 == 0) { // if accumulator == dest
// ZF = 1
set_ZF(1);
// dest <-- src
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* op1_16 is a register or memory reference */
if (i->modC0()) {
op1_16 = BX_READ_16BIT_REG(i->rm());
BX_WRITE_16BIT_REG(i->rm(), op2_16);
}
else {
/* pointer, segment address pair */
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
diff_16 = AX - op1_16;
SET_FLAGS_OSZAPC_16(AX, op1_16, diff_16, BX_INSTR_CMP16);
if (diff_16 == 0) { // if accumulator == dest
// ZF = 1
set_ZF(1);
// dest <-- src
op2_16 = BX_READ_16BIT_REG(i->nnn());
if (i->modC0()) {
BX_WRITE_16BIT_REG(i->rm(), op2_16);
}
else {
Write_RMW_virtual_word(op2_16);
}
}
else {
// ZF = 0
set_ZF(0);
// accumulator <-- dest
AX = op1_16;
Write_RMW_virtual_word(op2_16);
}
}
else {
// ZF = 0
set_ZF(0);
// accumulator <-- dest
AX = op1_16;
}
#else
BX_PANIC(("CMPXCHG_EwGw:"));

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: arith32.cc,v 1.23 2002-09-29 19:21:36 kevinlawton Exp $
// $Id: arith32.cc,v 1.24 2002-09-30 02:02:06 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -108,32 +108,22 @@ BX_CPU_C::DEC_ERX(bxInstruction_c *i)
void
BX_CPU_C::ADD_EdGd(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, sum_32;
Bit32u op2_32, op1_32, sum_32;
/* op2_32 is a register, RMAddr(i) is an index of a register */
op2_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
sum_32 = op1_32 + op2_32;
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
sum_32 = op1_32 + op2_32;
Write_RMW_virtual_dword(sum_32);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
Write_RMW_virtual_dword(sum_32);
}
SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
}
@ -163,7 +153,6 @@ BX_CPU_C::ADD_GdEEd(bxInstruction_c *i)
sum_32 = op1_32 + op2_32;
#endif
/* now write sum back to destination */
BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
#if !(defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -177,7 +166,6 @@ BX_CPU_C::ADD_GdEGd(bxInstruction_c *i)
Bit32u op1_32, op2_32, sum_32;
op1_32 = BX_READ_32BIT_REG(i->nnn());
op2_32 = BX_READ_32BIT_REG(i->rm());
#if (defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -197,7 +185,6 @@ BX_CPU_C::ADD_GdEGd(bxInstruction_c *i)
sum_32 = op1_32 + op2_32;
#endif
/* now write sum back to destination */
BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
#if !(defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -209,19 +196,16 @@ BX_CPU_C::ADD_GdEGd(bxInstruction_c *i)
void
BX_CPU_C::ADD_EAXId(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, sum_32;
Bit32u op1_32, op2_32, sum_32;
op1_32 = EAX;
op1_32 = EAX;
op2_32 = i->Id();
op2_32 = i->Id();
sum_32 = op1_32 + op2_32;
sum_32 = op1_32 + op2_32;
RAX = sum_32;
/* now write sum back to destination */
RAX = sum_32;
SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_ADD32);
}
void
@ -231,34 +215,23 @@ BX_CPU_C::ADC_EdGd(bxInstruction_c *i)
temp_CF = getB_CF();
Bit32u op2_32, op1_32, sum_32;
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, sum_32;
/* op2_32 is a register, RMAddr(i) is an index of a register */
op2_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
sum_32 = op1_32 + op2_32 + temp_CF;
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
sum_32 = op1_32 + op2_32 + temp_CF;
Write_RMW_virtual_dword(sum_32);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
Write_RMW_virtual_dword(sum_32);
}
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
}
@ -269,29 +242,23 @@ BX_CPU_C::ADC_GdEd(bxInstruction_c *i)
temp_CF = getB_CF();
Bit32u op1_32, op2_32, sum_32;
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, sum_32;
op1_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register, RMAddr(i) is an index of a register */
op1_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op2_32 = BX_READ_32BIT_REG(i->rm());
}
else {
read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
}
/* op2_32 is a register or memory reference */
if (i->modC0()) {
op2_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
}
sum_32 = op1_32 + op2_32 + temp_CF;
sum_32 = op1_32 + op2_32 + temp_CF;
BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
/* now write sum back to destination */
BX_WRITE_32BIT_REGZ(i->nnn(), sum_32);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
}
@ -302,20 +269,17 @@ BX_CPU_C::ADC_EAXId(bxInstruction_c *i)
temp_CF = getB_CF();
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, sum_32;
Bit32u op1_32, op2_32, sum_32;
op1_32 = EAX;
op1_32 = EAX;
op2_32 = i->Id();
op2_32 = i->Id();
sum_32 = op1_32 + op2_32 + temp_CF;
sum_32 = op1_32 + op2_32 + temp_CF;
RAX = sum_32;
/* now write sum back to destination */
RAX = sum_32;
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
}
@ -328,34 +292,23 @@ BX_CPU_C::SBB_EdGd(bxInstruction_c *i)
temp_CF = getB_CF();
Bit32u op2_32, op1_32, diff_32;
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, diff_32;
/* op2_32 is a register, RMAddr(i) is an index of a register */
op2_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
diff_32 = op1_32 - (op2_32 + temp_CF);
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
diff_32 = op1_32 - (op2_32 + temp_CF);
Write_RMW_virtual_dword(diff_32);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
Write_RMW_virtual_dword(diff_32);
}
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
}
@ -366,29 +319,23 @@ BX_CPU_C::SBB_GdEd(bxInstruction_c *i)
temp_CF = getB_CF();
Bit32u op1_32, op2_32, diff_32;
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, diff_32;
op1_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register, RMAddr(i) is an index of a register */
op1_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op2_32 = BX_READ_32BIT_REG(i->rm());
}
else {
read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
}
/* op2_32 is a register or memory reference */
if (i->modC0()) {
op2_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
}
diff_32 = op1_32 - (op2_32 + temp_CF);
diff_32 = op1_32 - (op2_32 + temp_CF);
BX_WRITE_32BIT_REGZ(i->nnn(), diff_32);
/* now write diff back to destination */
BX_WRITE_32BIT_REGZ(i->nnn(), diff_32);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
}
@ -399,20 +346,17 @@ BX_CPU_C::SBB_EAXId(bxInstruction_c *i)
temp_CF = getB_CF();
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, diff_32;
Bit32u op1_32, op2_32, diff_32;
op1_32 = EAX;
op1_32 = EAX;
op2_32 = i->Id();
op2_32 = i->Id();
diff_32 = op1_32 - (op2_32 + temp_CF);
diff_32 = op1_32 - (op2_32 + temp_CF);
RAX = diff_32;
/* now write diff back to destination */
RAX = diff_32;
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
}
@ -424,110 +368,82 @@ BX_CPU_C::SBB_EdId(bxInstruction_c *i)
temp_CF = getB_CF();
Bit32u op2_32, op1_32, diff_32;
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, diff_32;
op2_32 = i->Id();
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = i->Id();
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
diff_32 = op1_32 - (op2_32 + temp_CF);
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
diff_32 = op1_32 - (op2_32 + temp_CF);
Write_RMW_virtual_dword(diff_32);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
Write_RMW_virtual_dword(diff_32);
}
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, diff_32, BX_INSTR_SBB32,
temp_CF);
}
void
BX_CPU_C::SUB_EdGd(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, diff_32;
Bit32u op2_32, op1_32, diff_32;
/* op2_32 is a register, RMAddr(i) is an index of a register */
op2_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
diff_32 = op1_32 - op2_32;
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
diff_32 = op1_32 - op2_32;
Write_RMW_virtual_dword(diff_32);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
Write_RMW_virtual_dword(diff_32);
}
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
}
void
BX_CPU_C::SUB_GdEd(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, diff_32;
Bit32u op1_32, op2_32, diff_32;
/* op1_32 is a register, RMAddr(i) is an index of a register */
op1_32 = BX_READ_32BIT_REG(i->nnn());
op1_32 = BX_READ_32BIT_REG(i->nnn());
/* op2_32 is a register or memory reference */
if (i->modC0()) {
op2_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
}
if (i->modC0()) {
op2_32 = BX_READ_32BIT_REG(i->rm());
}
else {
read_virtual_dword(i->seg(), RMAddr(i), &op2_32);
}
diff_32 = op1_32 - op2_32;
diff_32 = op1_32 - op2_32;
/* now write diff back to destination */
BX_WRITE_32BIT_REGZ(i->nnn(), diff_32);
BX_WRITE_32BIT_REGZ(i->nnn(), diff_32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
}
void
BX_CPU_C::SUB_EAXId(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op1_32, op2_32, diff_32;
Bit32u op1_32, op2_32, diff_32;
op1_32 = EAX;
op1_32 = EAX;
op2_32 = i->Id();
op2_32 = i->Id();
diff_32 = op1_32 - op2_32;
diff_32 = op1_32 - op2_32;
RAX = diff_32;
/* now write diff back to destination */
RAX = diff_32;
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
}
@ -609,7 +525,6 @@ BX_CPU_C::CMP_EAXId(bxInstruction_c *i)
Bit32u op1_32, op2_32;
op1_32 = EAX;
op2_32 = i->Id();
#if (defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -638,10 +553,10 @@ BX_CPU_C::CMP_EAXId(bxInstruction_c *i)
BX_CPU_C::CWDE(bxInstruction_c *i)
{
/* CBW: no flags are effected */
Bit32u temp;
Bit32u temp;
temp = (Bit16s) AX;
RAX = temp;
temp = (Bit16s) AX;
RAX = temp;
}
void
@ -649,12 +564,12 @@ BX_CPU_C::CDQ(bxInstruction_c *i)
{
/* CDQ: no flags are affected */
if (EAX & 0x80000000) {
RDX = 0xFFFFFFFF;
}
else {
RDX = 0x00000000;
}
if (EAX & 0x80000000) {
RDX = 0xFFFFFFFF;
}
else {
RDX = 0x00000000;
}
}
// Some info on the opcodes at {0F,A6} and {0F,A7}
@ -690,47 +605,37 @@ BX_CPU_C::XADD_EdGd(bxInstruction_c *i)
{
#if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
Bit32u op2_32, op1_32, sum_32;
Bit32u op2_32, op1_32, sum_32;
/* XADD dst(r/m), src(r)
* temp <-- src + dst | sum = op2 + op1
* src <-- dst | op2 = op1
* dst <-- tmp | op1 = sum
*/
/* XADD dst(r/m), src(r)
* temp <-- src + dst | sum = op2 + op1
* src <-- dst | op2 = op1
* dst <-- tmp | op1 = sum
*/
/* op2 is a register, RMAddr(i) is an index of a register */
op2_32 = BX_READ_32BIT_REG(i->nnn());
/* op1 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
sum_32 = op1_32 + op2_32;
// and write destination into source
// Note: if both op1 & op2 are registers, the last one written
// should be the sum, as op1 & op2 may be the same register.
// For example: XADD AL, AL
BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
sum_32 = op1_32 + op2_32;
Write_RMW_virtual_dword(sum_32);
/* and write destination into source */
BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
}
/* now write sum back to destination */
if (i->modC0()) {
// and write destination into source
// Note: if both op1 & op2 are registers, the last one written
// should be the sum, as op1 & op2 may be the same register.
// For example: XADD AL, AL
BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
Write_RMW_virtual_dword(sum_32);
/* and write destination into source */
BX_WRITE_32BIT_REGZ(i->nnn(), op1_32);
}
SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_XADD32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, sum_32, BX_INSTR_XADD32);
#else
#panic "XADD_EdGd"
#endif
}
@ -776,7 +681,6 @@ BX_CPU_C::ADD_EGdId(bxInstruction_c *i)
Bit32u op2_32, op1_32, sum_32;
op2_32 = i->Id();
op1_32 = BX_READ_32BIT_REG(i->rm());
#if (defined(__i386__) && defined(__GNUC__) && BX_SupportHostAsms)
@ -811,63 +715,45 @@ BX_CPU_C::ADC_EdId(bxInstruction_c *i)
temp_CF = getB_CF();
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, sum_32;
Bit32u op2_32, op1_32, sum_32;
op2_32 = i->Id();
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = i->Id();
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
sum_32 = op1_32 + op2_32 + temp_CF;
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
sum_32 = op1_32 + op2_32 + temp_CF;
Write_RMW_virtual_dword(sum_32);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), sum_32);
}
else {
Write_RMW_virtual_dword(sum_32);
}
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
SET_FLAGS_OSZAPC_32_CF(op1_32, op2_32, sum_32, BX_INSTR_ADC32,
temp_CF);
}
void
BX_CPU_C::SUB_EdId(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op2_32, op1_32, diff_32;
Bit32u op2_32, op1_32, diff_32;
op2_32 = i->Id();
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
op2_32 = i->Id();
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
diff_32 = op1_32 - op2_32;
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
diff_32 = op1_32 - op2_32;
Write_RMW_virtual_dword(diff_32);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
Write_RMW_virtual_dword(diff_32);
}
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
SET_FLAGS_OSZAPC_32(op1_32, op2_32, diff_32, BX_INSTR_SUB32);
}
void
@ -911,85 +797,60 @@ BX_CPU_C::CMP_EdId(bxInstruction_c *i)
void
BX_CPU_C::NEG_Ed(bxInstruction_c *i)
{
/* for 32 bit operand size mode */
Bit32u op1_32, diff_32;
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
Bit32u op1_32, diff_32;
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
diff_32 = 0 - op1_32;
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
diff_32 = 0 - op1_32;
Write_RMW_virtual_dword(diff_32);
}
/* now write diff back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), diff_32);
}
else {
Write_RMW_virtual_dword(diff_32);
}
SET_FLAGS_OSZAPC_32(op1_32, 0, diff_32, BX_INSTR_NEG32);
SET_FLAGS_OSZAPC_32(op1_32, 0, diff_32, BX_INSTR_NEG32);
}
void
BX_CPU_C::INC_Ed(bxInstruction_c *i)
{
Bit32u op1_32;
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
Bit32u op1_32;
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
op1_32++;
BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
op1_32++;
Write_RMW_virtual_dword(op1_32);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
}
else {
Write_RMW_virtual_dword(op1_32);
}
SET_FLAGS_OSZAP_32(0, 0, op1_32, BX_INSTR_INC32);
SET_FLAGS_OSZAP_32(0, 0, op1_32, BX_INSTR_INC32);
}
void
BX_CPU_C::DEC_Ed(bxInstruction_c *i)
{
Bit32u op1_32;
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
Bit32u op1_32;
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
op1_32--;
BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
op1_32--;
Write_RMW_virtual_dword(op1_32);
}
/* now write sum back to destination */
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), op1_32);
}
else {
Write_RMW_virtual_dword(op1_32);
}
SET_FLAGS_OSZAP_32(0, 0, op1_32, BX_INSTR_DEC32);
SET_FLAGS_OSZAP_32(0, 0, op1_32, BX_INSTR_DEC32);
}
@ -998,40 +859,38 @@ BX_CPU_C::CMPXCHG_EdGd(bxInstruction_c *i)
{
#if (BX_CPU_LEVEL >= 4) || (BX_CPU_LEVEL_HACKED >= 4)
Bit32u op2_32, op1_32, diff_32;
Bit32u op2_32, op1_32, diff_32;
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
}
else {
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
diff_32 = EAX - op1_32;
SET_FLAGS_OSZAPC_32(EAX, op1_32, diff_32, BX_INSTR_CMP32);
if (diff_32 == 0) { // if accumulator == dest
// ZF = 1
set_ZF(1);
// dest <-- src
op2_32 = BX_READ_32BIT_REG(i->nnn());
/* op1_32 is a register or memory reference */
if (i->modC0()) {
op1_32 = BX_READ_32BIT_REG(i->rm());
BX_WRITE_32BIT_REGZ(i->rm(), op2_32);
}
else {
/* pointer, segment address pair */
read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32);
}
diff_32 = EAX - op1_32;
SET_FLAGS_OSZAPC_32(EAX, op1_32, diff_32, BX_INSTR_CMP32);
if (diff_32 == 0) { // if accumulator == dest
// ZF = 1
set_ZF(1);
// dest <-- src
op2_32 = BX_READ_32BIT_REG(i->nnn());
if (i->modC0()) {
BX_WRITE_32BIT_REGZ(i->rm(), op2_32);
}
else {
Write_RMW_virtual_dword(op2_32);
}
}
else {
// ZF = 0
set_ZF(0);
// accumulator <-- dest
RAX = op1_32;
Write_RMW_virtual_dword(op2_32);
}
}
else {
// ZF = 0
set_ZF(0);
// accumulator <-- dest
RAX = op1_32;
}
#else
BX_PANIC(("CMPXCHG_EdGd:"));
#endif
@ -1042,36 +901,35 @@ BX_CPU_C::CMPXCHG8B(bxInstruction_c *i)
{
#if (BX_CPU_LEVEL >= 5) || (BX_CPU_LEVEL_HACKED >= 5)
Bit32u op1_64_lo, op1_64_hi, diff;
Bit32u op1_64_lo, op1_64_hi, diff;
if (i->modC0()) {
BX_INFO(("CMPXCHG8B: dest is reg: #UD"));
UndefinedOpcode(i);
}
if (i->modC0()) {
BX_INFO(("CMPXCHG8B: dest is reg: #UD"));
UndefinedOpcode(i);
}
/* pointer, segment address pair */
read_virtual_dword(i->seg(), RMAddr(i), &op1_64_lo);
read_RMW_virtual_dword(i->seg(), RMAddr(i) + 4, &op1_64_hi);
read_virtual_dword(i->seg(), RMAddr(i), &op1_64_lo);
read_RMW_virtual_dword(i->seg(), RMAddr(i) + 4, &op1_64_hi);
diff = EAX - op1_64_lo;
diff |= EDX - op1_64_hi;
diff = EAX - op1_64_lo;
diff |= EDX - op1_64_hi;
// SET_FLAGS_OSZAPC_32(EAX, op1_32, diff_32, BX_INSTR_CMP32);
if (diff == 0) { // if accumulator == dest
// ZF = 1
set_ZF(1);
// dest <-- src
Write_RMW_virtual_dword(ECX);
write_virtual_dword(i->seg(), RMAddr(i), &EBX);
}
else {
// ZF = 0
set_ZF(0);
// accumulator <-- dest
RAX = op1_64_lo;
RDX = op1_64_hi;
}
if (diff == 0) { // if accumulator == dest
// ZF = 1
set_ZF(1);
// dest <-- src
Write_RMW_virtual_dword(ECX);
write_virtual_dword(i->seg(), RMAddr(i), &EBX);
}
else {
// ZF = 0
set_ZF(0);
// accumulator <-- dest
RAX = op1_64_lo;
RDX = op1_64_hi;
}
#else
BX_INFO(("CMPXCHG8B: not implemented yet"));

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: arith8.cc,v 1.18 2002-09-28 01:16:09 kevinlawton Exp $
// $Id: arith8.cc,v 1.19 2002-09-30 02:02:06 kevinlawton Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -41,24 +41,16 @@ BX_CPU_C::ADD_EbGb(bxInstruction_c *i)
{
Bit8u op2, op1, sum;
/* op2 is a register, RMAddr(i) is an index of a register */
op2 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op1 is a register or memory reference */
if (i->modC0()) {
op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
}
sum = op1 + op2;
/* now write sum back to destination */
if (i->modC0()) {
sum = op1 + op2;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
sum = op1 + op2;
Write_RMW_virtual_byte(sum);
}
@ -72,22 +64,17 @@ BX_CPU_C::ADD_GbEb(bxInstruction_c *i)
{
Bit8u op1, op2, sum;
/* op1 is a register, RMAddr(i) is an index of a register */
op1 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
sum = op1 + op2;
}
else {
/* pointer, segment address pair */
read_virtual_byte(i->seg(), RMAddr(i), &op2);
sum = op1 + op2;
}
sum = op1 + op2;
/* now write sum back to destination, which is a register */
BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), sum);
SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
@ -101,12 +88,10 @@ BX_CPU_C::ADD_ALIb(bxInstruction_c *i)
op1 = AL;
op2 = i->Ib();
sum = op1 + op2;
/* now write sum back to destination, which is a register */
AL = sum;
SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_ADD8);
@ -121,27 +106,16 @@ BX_CPU_C::ADC_EbGb(bxInstruction_c *i)
temp_CF = getB_CF();
/* op2 is a register, RMAddr(i) is an index of a register */
op2 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op1 is a register or memory reference */
if (i->modC0()) {
op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
}
sum = op1 + op2 + temp_CF;
/* now write sum back to destination */
if (i->modC0()) {
sum = op1 + op2 + temp_CF;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
sum = op1 + op2 + temp_CF;
Write_RMW_virtual_byte(sum);
}
@ -157,16 +131,12 @@ BX_CPU_C::ADC_GbEb(bxInstruction_c *i)
temp_CF = getB_CF();
/* op1 is a register, RMAddr(i) is an index of a register */
op1 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op2 is a register or memory reference */
if (i->modC0()) {
op2 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_virtual_byte(i->seg(), RMAddr(i), &op2);
}
@ -175,7 +145,6 @@ BX_CPU_C::ADC_GbEb(bxInstruction_c *i)
SET_FLAGS_OSZAPC_8_CF(op1, op2, sum, BX_INSTR_ADC8,
temp_CF);
/* now write sum back to destination, which is a register */
BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), sum);
}
@ -190,12 +159,10 @@ BX_CPU_C::ADC_ALIb(bxInstruction_c *i)
op1 = AL;
op2 = i->Ib();
sum = op1 + op2 + temp_CF;
/* now write sum back to destination, which is a register */
AL = sum;
SET_FLAGS_OSZAPC_8_CF(op1, op2, sum, BX_INSTR_ADC8,
@ -212,25 +179,16 @@ BX_CPU_C::SBB_EbGb(bxInstruction_c *i)
temp_CF = getB_CF();
/* op2 is a register, RMAddr(i) is an index of a register */
op2_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}
diff_8 = op1_8 - (op2_8 + temp_CF);
/* now write diff back to destination */
if (i->modC0()) {
diff_8 = op1_8 - (op2_8 + temp_CF);
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
diff_8 = op1_8 - (op2_8 + temp_CF);
Write_RMW_virtual_byte(diff_8);
}
@ -247,22 +205,17 @@ BX_CPU_C::SBB_GbEb(bxInstruction_c *i)
temp_CF = getB_CF();
/* op1 is a register, RMAddr(i) is an index of a register */
op1_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op2 is a register or memory reference */
if (i->modC0()) {
op2_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_virtual_byte(i->seg(), RMAddr(i), &op2_8);
}
diff_8 = op1_8 - (op2_8 + temp_CF);
/* now write diff back to destination, which is a register */
BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), diff_8);
SET_FLAGS_OSZAPC_8_CF(op1_8, op2_8, diff_8, BX_INSTR_SBB8,
@ -278,14 +231,11 @@ BX_CPU_C::SBB_ALIb(bxInstruction_c *i)
temp_CF = getB_CF();
op1_8 = AL;
op2_8 = i->Ib();
diff_8 = op1_8 - (op2_8 + temp_CF);
/* now write diff back to destination, which is a register */
AL = diff_8;
SET_FLAGS_OSZAPC_8_CF(op1_8, op2_8, diff_8, BX_INSTR_SBB8,
@ -303,22 +253,14 @@ BX_CPU_C::SBB_EbIb(bxInstruction_c *i)
op2_8 = i->Ib();
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}
diff_8 = op1_8 - (op2_8 + temp_CF);
/* now write diff back to destination */
if (i->modC0()) {
diff_8 = op1_8 - (op2_8 + temp_CF);
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
diff_8 = op1_8 - (op2_8 + temp_CF);
Write_RMW_virtual_byte(diff_8);
}
@ -333,26 +275,16 @@ BX_CPU_C::SUB_EbGb(bxInstruction_c *i)
{
Bit8u op2_8, op1_8, diff_8;
/* op2 is a register, RMAddr(i) is an index of a register */
op2_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}
diff_8 = op1_8 - op2_8;
/* now write diff back to destination */
if (i->modC0()) {
diff_8 = op1_8 - op2_8;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
diff_8 = op1_8 - op2_8;
Write_RMW_virtual_byte(diff_8);
}
@ -365,22 +297,17 @@ BX_CPU_C::SUB_GbEb(bxInstruction_c *i)
{
Bit8u op1_8, op2_8, diff_8;
/* op1 is a register, RMAddr(i) is an index of a register */
op1_8 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op2 is a register or memory reference */
if (i->modC0()) {
op2_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_virtual_byte(i->seg(), RMAddr(i), &op2_8);
}
diff_8 = op1_8 - op2_8;
/* now write diff back to destination, which is a register */
BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), diff_8);
SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB8);
@ -393,12 +320,10 @@ BX_CPU_C::SUB_ALIb(bxInstruction_c *i)
Bit8u op1_8, op2_8, diff_8;
op1_8 = AL;
op2_8 = i->Ib();
diff_8 = op1_8 - op2_8;
/* now write diff back to destination, which is a register */
AL = diff_8;
SET_FLAGS_OSZAPC_8(op1_8, op2_8, diff_8, BX_INSTR_SUB8);
@ -523,22 +448,11 @@ BX_CPU_C::XADD_EbGb(bxInstruction_c *i)
* dst <-- tmp | op1 = sum
*/
/* op2 is a register, RMAddr(i) is an index of a register */
op2 = BX_READ_8BIT_REGx(i->nnn(),i->extend8bitL());
/* op1 is a register or memory reference */
if (i->modC0()) {
op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
}
sum = op1 + op2;
/* now write sum back to destination */
if (i->modC0()) {
sum = op1 + op2;
// and write destination into source
// Note: if both op1 & op2 are registers, the last one written
// should be the sum, as op1 & op2 may be the same register.
@ -547,12 +461,13 @@ BX_CPU_C::XADD_EbGb(bxInstruction_c *i)
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
sum = op1 + op2;
Write_RMW_virtual_byte(sum);
/* and write destination into source */
BX_WRITE_8BIT_REGx(i->nnn(), i->extend8bitL(), op1);
}
SET_FLAGS_OSZAPC_8(op1, op2, sum, BX_INSTR_XADD8);
#else
BX_PANIC(("XADD_EbGb: not supported on < 80486"));
@ -565,25 +480,16 @@ BX_CPU_C::ADD_EbIb(bxInstruction_c *i)
{
Bit8u op2, op1, sum;
op2 = i->Ib();
/* op1 is a register or memory reference */
if (i->modC0()) {
op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
}
sum = op1 + op2;
/* now write sum back to destination */
if (i->modC0()) {
sum = op1 + op2;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
sum = op1 + op2;
Write_RMW_virtual_byte(sum);
}
@ -600,22 +506,14 @@ BX_CPU_C::ADC_EbIb(bxInstruction_c *i)
op2 = i->Ib();
/* op1 is a register or memory reference */
if (i->modC0()) {
op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
}
sum = op1 + op2 + temp_CF;
/* now write sum back to destination */
if (i->modC0()) {
sum = op1 + op2 + temp_CF;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), sum);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
sum = op1 + op2 + temp_CF;
Write_RMW_virtual_byte(sum);
}
@ -629,25 +527,16 @@ BX_CPU_C::SUB_EbIb(bxInstruction_c *i)
{
Bit8u op2_8, op1_8, diff_8;
op2_8 = i->Ib();
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}
diff_8 = op1_8 - op2_8;
/* now write diff back to destination */
if (i->modC0()) {
diff_8 = op1_8 - op2_8;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
diff_8 = op1_8 - op2_8;
Write_RMW_virtual_byte(diff_8);
}
@ -695,22 +584,14 @@ BX_CPU_C::NEG_Eb(bxInstruction_c *i)
{
Bit8u op1_8, diff_8;
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}
diff_8 = 0 - op1_8;
/* now write diff back to destination */
if (i->modC0()) {
diff_8 = 0 - op1_8;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), diff_8);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
diff_8 = 0 - op1_8;
Write_RMW_virtual_byte(diff_8);
}
@ -723,23 +604,14 @@ BX_CPU_C::INC_Eb(bxInstruction_c *i)
{
Bit8u op1;
/* op1 is a register or memory reference */
if (i->modC0()) {
op1 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
}
op1++;
/* now write sum back to destination */
if (i->modC0()) {
op1++;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), op1);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1);
op1++;
Write_RMW_virtual_byte(op1);
}
@ -752,22 +624,14 @@ BX_CPU_C::DEC_Eb(bxInstruction_c *i)
{
Bit8u op1_8;
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}
op1_8--;
/* now write sum back to destination */
if (i->modC0()) {
op1_8--;
BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), op1_8);
}
else {
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
op1_8--;
Write_RMW_virtual_byte(op1_8);
}
@ -782,12 +646,10 @@ BX_CPU_C::CMPXCHG_EbGb(bxInstruction_c *i)
Bit8u op2_8, op1_8, diff_8;
/* op1_8 is a register or memory reference */
if (i->modC0()) {
op1_8 = BX_READ_8BIT_REGx(i->rm(),i->extend8bitL());
}
else {
/* pointer, segment address pair */
read_RMW_virtual_byte(i->seg(), RMAddr(i), &op1_8);
}