Next step in lazy flags optimization by Darek MihockA -

get rid of shifts from lazy flags code
This commit is contained in:
Stanislav Shwartsman 2007-12-06 20:39:11 +00:00
parent d739cca282
commit 6fcc7d34ab
6 changed files with 195 additions and 307 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: lazy_flags.cc,v 1.41 2007-12-06 16:57:59 sshwarts Exp $
// $Id: lazy_flags.cc,v 1.42 2007-12-06 20:39:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -158,55 +158,6 @@ bx_bool BX_CPU_C::get_CFLazy(void)
#endif
cf = 0;
break;
case BX_INSTR_SHR8:
cf = (BX_CPU_THIS_PTR oszapc.op1_8 >>
(BX_CPU_THIS_PTR oszapc.op2_8 - 1)) & 0x01;
break;
case BX_INSTR_SHR16:
case BX_INSTR_SHRD16:
cf = (BX_CPU_THIS_PTR oszapc.op1_16 >>
(BX_CPU_THIS_PTR oszapc.op2_16 - 1)) & 0x01;
break;
case BX_INSTR_SHR32:
case BX_INSTR_SHRD32:
cf = (BX_CPU_THIS_PTR oszapc.op1_32 >>
(BX_CPU_THIS_PTR oszapc.op2_32 - 1)) & 0x01;
break;
#if BX_SUPPORT_X86_64
case BX_INSTR_SHR64:
case BX_INSTR_SHRD64:
cf = (BX_CPU_THIS_PTR oszapc.op1_64 >>
(BX_CPU_THIS_PTR oszapc.op2_64 - 1)) & 0x01;
break;
#endif
case BX_INSTR_SHL8:
if (BX_CPU_THIS_PTR oszapc.op2_8 <= 8) {
cf = (BX_CPU_THIS_PTR oszapc.op1_8 >>
(8 - BX_CPU_THIS_PTR oszapc.op2_8)) & 0x01;
}
else {
cf = 0;
}
break;
case BX_INSTR_SHL16:
if (BX_CPU_THIS_PTR oszapc.op2_16 <= 16) {
cf = (BX_CPU_THIS_PTR oszapc.op1_16 >>
(16 - BX_CPU_THIS_PTR oszapc.op2_16)) & 0x01;
}
else {
cf = 0;
}
break;
case BX_INSTR_SHL32:
cf = (BX_CPU_THIS_PTR oszapc.op1_32 >>
(32 - BX_CPU_THIS_PTR oszapc.op2_32)) & 0x01;
break;
#if BX_SUPPORT_X86_64
case BX_INSTR_SHL64:
cf = (BX_CPU_THIS_PTR oszapc.op1_64 >>
(64 - BX_CPU_THIS_PTR oszapc.op2_64)) & 0x01;
break;
#endif
default:
cf = 0; // Keep compiler quiet.
BX_PANIC(("get_CF: OSZAPC: unknown instr %u",
@ -280,18 +231,7 @@ bx_bool BX_CPU_C::get_AFLazy(void)
case BX_INSTR_LOGIC32:
#if BX_SUPPORT_X86_64
case BX_INSTR_LOGIC64:
case BX_INSTR_SHR64:
case BX_INSTR_SHRD64:
case BX_INSTR_SHL64:
#endif
case BX_INSTR_SHR8:
case BX_INSTR_SHR16:
case BX_INSTR_SHR32:
case BX_INSTR_SHRD16:
case BX_INSTR_SHRD32:
case BX_INSTR_SHL8:
case BX_INSTR_SHL16:
case BX_INSTR_SHL32:
af = 0;
break;
default:
@ -383,76 +323,6 @@ bx_bool BX_CPU_C::get_OFLazy(void)
#endif
of = 0;
break;
case BX_INSTR_SHR8:
if (BX_CPU_THIS_PTR oszapc.op2_8 == 1)
of = (BX_CPU_THIS_PTR oszapc.op1_8 >= 0x80);
else
of = 0; /* undocumented, but hardware really does it */
break;
case BX_INSTR_SHR16:
if (BX_CPU_THIS_PTR oszapc.op2_16 == 1)
of = (BX_CPU_THIS_PTR oszapc.op1_16 >= 0x8000);
else
of = 0; /* undocumented, but hardware really does it */
break;
case BX_INSTR_SHR32:
if (BX_CPU_THIS_PTR oszapc.op2_32 == 1)
of = (BX_CPU_THIS_PTR oszapc.op1_32 >= 0x80000000);
else
of = 0; /* undocumented, but hardware really does it */
break;
#if BX_SUPPORT_X86_64
case BX_INSTR_SHR64:
if (BX_CPU_THIS_PTR oszapc.op2_64 == 1)
of = (BX_CPU_THIS_PTR oszapc.op1_64 >= BX_CONST64(0x8000000000000000));
else
of = 0; /* undocumented, but hardware really does it */
break;
#endif
case BX_INSTR_SHRD16:
/* undocumented, but this formula works right for any shift count */
of = (((result_16 << 1) ^ result_16) & 0x8000) > 0;
break;
case BX_INSTR_SHRD32:
/* undocumented, but this formula works right for any shift count */
of = (((result_32 << 1) ^ result_32) & 0x80000000) > 0;
break;
#if BX_SUPPORT_X86_64
case BX_INSTR_SHRD64:
/* undocumented, but this formula works right for any shift count */
of = (((result_64 << 1) ^ result_64) & BX_CONST64(0x8000000000000000)) > 0;
break;
#endif
case BX_INSTR_SHL8:
if (BX_CPU_THIS_PTR oszapc.op2_8 == 1)
of = ((BX_CPU_THIS_PTR oszapc.op1_8 ^ result_8) & 0x80) > 0;
else
of = (((BX_CPU_THIS_PTR oszapc.op1_8 <<
(BX_CPU_THIS_PTR oszapc.op2_8 - 1)) ^ result_8) & 0x80) > 0;
break;
case BX_INSTR_SHL16:
if (BX_CPU_THIS_PTR oszapc.op2_16 == 1)
of = ((BX_CPU_THIS_PTR oszapc.op1_16 ^ result_16) & 0x8000) > 0;
else
of = (((BX_CPU_THIS_PTR oszapc.op1_16 <<
(BX_CPU_THIS_PTR oszapc.op2_16 - 1)) ^ result_16) & 0x8000) > 0;
break;
case BX_INSTR_SHL32:
if (BX_CPU_THIS_PTR oszapc.op2_32 == 1)
of = ((BX_CPU_THIS_PTR oszapc.op1_32 ^ result_32) & 0x80000000) > 0;
else
of = (((BX_CPU_THIS_PTR oszapc.op1_32 <<
(BX_CPU_THIS_PTR oszapc.op2_32 - 1)) ^ result_32) & 0x80000000) > 0;
break;
#if BX_SUPPORT_X86_64
case BX_INSTR_SHL64:
if (BX_CPU_THIS_PTR oszapc.op2_64 == 1)
of = ((BX_CPU_THIS_PTR oszapc.op1_64 ^ result_64) & BX_CONST64(0x8000000000000000)) > 0;
else
of = (((BX_CPU_THIS_PTR oszapc.op1_64 <<
(BX_CPU_THIS_PTR oszapc.op2_64 - 1)) ^ result_64) & BX_CONST64(0x8000000000000000)) > 0;
break;
#endif
case BX_INSTR_NEG8:
case BX_INSTR_INC8:
of = (result_8 == 0x80);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: lazy_flags.h,v 1.28 2007-12-06 16:57:59 sshwarts Exp $
// $Id: lazy_flags.h,v 1.29 2007-12-06 20:39:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -79,21 +79,6 @@
#define BX_INSTR_LOGIC32 31
#define BX_INSTR_LOGIC64 32
// BX_INSTR_SHRD8 not exists, leave number for alignment
#define BX_INSTR_SHRD16 34
#define BX_INSTR_SHRD32 35
#define BX_INSTR_SHRD64 36
#define BX_INSTR_SHL8 37
#define BX_INSTR_SHL16 38
#define BX_INSTR_SHL32 39
#define BX_INSTR_SHL64 40
#define BX_INSTR_SHR8 41
#define BX_INSTR_SHR16 42
#define BX_INSTR_SHR32 43
#define BX_INSTR_SHR64 44
#if BX_SUPPORT_X86_64
#define BX_LF_SIGN_BIT 63
#else

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: shift16.cc,v 1.37 2007-12-06 18:35:33 sshwarts Exp $
// $Id: shift16.cc,v 1.38 2007-12-06 20:39:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -37,6 +37,7 @@ void BX_CPU_C::SHLD_EwGw(bxInstruction_c *i)
Bit16u op1_16, op2_16, result_16;
Bit32u temp_32, result_32;
unsigned count;
unsigned of, cf;
/* op1:op2 << count. result stored in op1 */
if (i->b1() == 0x1a4)
@ -56,13 +57,14 @@ void BX_CPU_C::SHLD_EwGw(bxInstruction_c *i)
}
if (!count) return;
// count is 1..31
op2_16 = BX_READ_16BIT_REG(i->nnn());
/* count < 32, since only lower 5 bits used */
temp_32 = ((Bit32u)(op1_16) << 16) | (op2_16); // double formed by op1:op2
result_32 = temp_32 << count;
// Hack to act like x86 SHLD when count > 16
// hack to act like x86 SHLD when count > 16
if (count > 16) {
// when count > 16 actually shifting op1:op2:op2 << count,
// it is the same as shifting op2:op2 by count-16
@ -79,10 +81,11 @@ void BX_CPU_C::SHLD_EwGw(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
/* set eflags:
* SHLD count affects the following flags: O,S,Z,A,P,C
*/
SET_FLAGS_OSZAPC_16(op1_16, count, result_16, BX_INSTR_SHL16);
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
cf = (temp_32 >> (32 - count)) & 0x1;
of = cf ^ (result_16 >> 15); // of = cf ^ result15
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHRD_EwGw(bxInstruction_c *i)
@ -90,6 +93,7 @@ void BX_CPU_C::SHRD_EwGw(bxInstruction_c *i)
Bit16u op1_16, op2_16, result_16;
Bit32u temp_32, result_32;
unsigned count;
unsigned cf, of;
if (i->b1() == 0x1ac)
count = i->Ib();
@ -108,13 +112,14 @@ void BX_CPU_C::SHRD_EwGw(bxInstruction_c *i)
}
if (!count) return;
// count is 1..31
op2_16 = BX_READ_16BIT_REG(i->nnn());
// Hack to act like x86 SHLD when count > 16
/* count < 32, since only lower 5 bits used */
temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1
result_32 = temp_32 >> count;
// hack to act like x86 SHRD when count > 16
if (count > 16) {
// when count > 16 actually shifting op2:op2:op1 >> count,
// it is the same as shifting op2:op2 by count-16
@ -131,10 +136,11 @@ void BX_CPU_C::SHRD_EwGw(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
/* set eflags:
* SHRD count affects the following flags: O,S,Z,A,P,C
*/
SET_FLAGS_OSZAPC_16(op1_16, count, result_16, BX_INSTR_SHRD16);
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
cf = (op1_16 >> (count - 1)) & 0x1;
of = ((result_16 << 1) ^ result_16) >> 15; // of = result14 ^ result15
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::ROL_Ew(bxInstruction_c *i)
@ -163,7 +169,7 @@ void BX_CPU_C::ROL_Ew(bxInstruction_c *i)
if (count & 0x10) {
bit0 = (op1_16 & 0x1);
bit15 = (op1_16 >> 15);
// of = cf ^ result15
SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0);
}
return;
@ -181,12 +187,9 @@ void BX_CPU_C::ROL_Ew(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
/* set eflags:
* ROL count affects the following flags: C, O
*/
bit0 = (result_16 & 0x1);
bit15 = (result_16 >> 15);
// of = cf ^ result15
SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0);
}
@ -212,11 +215,11 @@ void BX_CPU_C::ROR_Ew(bxInstruction_c *i)
read_RMW_virtual_word(i->seg(), RMAddr(i), &op1_16);
}
if ( (count & 0x0f) == 0 ) {
if ( count & 0x10 ) {
if ((count & 0x0f) == 0) {
if (count & 0x10) {
bit14 = (op1_16 >> 14) & 1;
bit15 = (op1_16 >> 15) & 1;
// of = result14 ^ result15
SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15);
}
return;
@ -234,12 +237,9 @@ void BX_CPU_C::ROR_Ew(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
/* set eflags:
* ROR count affects the following flags: C, O
*/
bit14 = (result_16 >> 14) & 1;
bit15 = (result_16 >> 15) & 1;
// of = result14 ^ result15
SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15);
}
@ -247,10 +247,11 @@ void BX_CPU_C::RCL_Ew(bxInstruction_c *i)
{
Bit16u op1_16, result_16;
unsigned count;
unsigned of, cf;
if ( i->b1() == 0xc1 )
if (i->b1() == 0xc1)
count = i->Ib();
else if ( i->b1() == 0xd1 )
else if (i->b1() == 0xd1)
count = 1;
else // 0xd3
count = CL;
@ -287,19 +288,16 @@ void BX_CPU_C::RCL_Ew(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
/* set eflags:
* RCL count affects the following flags: C, O
*/
bx_bool temp_CF = (op1_16 >> (16 - count)) & 0x01;
set_CF(temp_CF);
set_OF(temp_CF ^ (result_16 >> 15));
cf = (op1_16 >> (16 - count)) & 0x1;
of = cf ^ (result_16 >> 15); // of = cf ^ result15
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::RCR_Ew(bxInstruction_c *i)
{
Bit16u op1_16, result_16;
unsigned count;
unsigned of, cf;
if (i->b1() == 0xc1)
count = i->Ib();
@ -332,18 +330,16 @@ void BX_CPU_C::RCR_Ew(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
/* set eflags:
* RCR count affects the following flags: C, O
*/
set_CF((op1_16 >> (count - 1)) & 0x01);
set_OF((((result_16 << 1) ^ result_16) & 0x8000) > 0);
cf = (op1_16 >> (count - 1)) & 0x1;
of = ((result_16 << 1) ^ result_16) >> 15; // of = result15 ^ result14
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHL_Ew(bxInstruction_c *i)
{
Bit16u op1_16, result_16;
unsigned count;
unsigned of = 0, cf = 0;
if (i->b1() == 0xc1)
count = i->Ib();
@ -365,7 +361,14 @@ void BX_CPU_C::SHL_Ew(bxInstruction_c *i)
if (!count) return;
result_16 = (op1_16 << count);
if (count <= 16) {
result_16 = (op1_16 << count);
cf = (op1_16 >> (16 - count)) & 0x1;
of = cf ^ (result_16 >> 15); // of = cf ^ result15
}
else {
result_16 = 0;
}
/* now write result back to destination */
if (i->modC0()) {
@ -375,13 +378,15 @@ void BX_CPU_C::SHL_Ew(bxInstruction_c *i)
write_RMW_virtual_word(result_16);
}
SET_FLAGS_OSZAPC_16(op1_16, count, result_16, BX_INSTR_SHL16);
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHR_Ew(bxInstruction_c *i)
{
Bit16u op1_16, result_16;
unsigned count;
unsigned of, cf;
if (i->b1() == 0xc1)
count = i->Ib();
@ -404,7 +409,6 @@ void BX_CPU_C::SHR_Ew(bxInstruction_c *i)
if (!count) return;
result_16 = (op1_16 >> count);
SET_FLAGS_OSZAPC_16(op1_16, count, result_16, BX_INSTR_SHR16);
/* now write result back to destination */
if (i->modC0()) {
@ -413,12 +417,20 @@ void BX_CPU_C::SHR_Ew(bxInstruction_c *i)
else {
write_RMW_virtual_word(result_16);
}
cf = (op1_16 >> (count - 1)) & 0x1;
// note, that of == result15 if count == 1 and
// of == 0 if count >= 2
of = ((result_16 << 1) ^ result_16) >> 15;
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SAR_Ew(bxInstruction_c *i)
{
Bit16u op1_16, result_16;
unsigned count;
unsigned count, cf;
if (i->b1() == 0xc1)
count = i->Ib();
@ -448,8 +460,7 @@ void BX_CPU_C::SAR_Ew(bxInstruction_c *i)
result_16 = (op1_16 >> count);
}
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle undefined SF, ZF and AF flags */
set_CF((op1_16 >> (count - 1)) & 0x1);
cf = (op1_16 >> (count - 1)) & 0x1;
}
else {
if (op1_16 & 0x8000) {
@ -459,11 +470,12 @@ void BX_CPU_C::SAR_Ew(bxInstruction_c *i)
result_16 = 0;
}
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle undefined SF, ZF and AF flags */
set_CF(result_16 & 0x1);
cf = (result_16 & 0x1);
}
clear_OF(); /* signed overflow cannot happen in SAR instruction */
SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
/* signed overflow cannot happen in SAR instruction */
SET_FLAGS_OxxxxC(0, cf);
/* now write result back to destination */
if (i->modC0()) {

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: shift32.cc,v 1.36 2007-12-06 16:57:59 sshwarts Exp $
// $Id: shift32.cc,v 1.37 2007-12-06 20:39:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -36,8 +36,7 @@ void BX_CPU_C::SHLD_EdGd(bxInstruction_c *i)
{
Bit32u op1_32, op2_32, result_32;
unsigned count;
/* op1:op2 << count. result stored in op1 */
unsigned of, cf;
if (i->b1() == 0x1a4)
count = i->Ib();
@ -69,16 +68,18 @@ void BX_CPU_C::SHLD_EdGd(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
/* set eflags:
* SHLD count affects the following flags: O,S,Z,A,P,C
*/
SET_FLAGS_OSZAPC_32(op1_32, count, result_32, BX_INSTR_SHL32);
SET_FLAGS_OSZAPC_LOGIC_32(result_32); /* handle SF, ZF and AF flags */
cf = (op1_32 >> (32 - count)) & 0x1;
of = cf ^ (result_32 >> 31); // of = cf ^ result31
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHRD_EdGd(bxInstruction_c *i)
{
Bit32u op1_32, op2_32, result_32;
unsigned count;
unsigned cf, of;
if (i->b1() == 0x1ac)
count = i->Ib();
@ -110,16 +111,18 @@ void BX_CPU_C::SHRD_EdGd(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
/* set eflags:
* SHRD count affects the following flags: O,S,Z,A,P,C
*/
SET_FLAGS_OSZAPC_32(op1_32, count, result_32, BX_INSTR_SHRD32);
SET_FLAGS_OSZAPC_LOGIC_32(result_32); /* handle SF, ZF and AF flags */
cf = (op1_32 >> (count - 1)) & 0x1;
of = ((result_32 << 1) ^ result_32) >> 31; // of = result30 ^ result31
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::ROL_Ed(bxInstruction_c *i)
{
Bit32u op1_32, result_32;
unsigned count;
unsigned bit0, bit31;
if (i->b1() == 0xc1)
count = i->Ib() & 0x1f;
@ -149,19 +152,17 @@ void BX_CPU_C::ROL_Ed(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
/* set eflags:
* ROL count affects the following flags: C, O
*/
bx_bool temp_CF = (result_32 & 0x01);
set_CF(temp_CF);
set_OF(temp_CF ^ (result_32 >> 31));
bit0 = (result_32 & 0x1);
bit31 = (result_32 >> 31);
// of = cf ^ result31
SET_FLAGS_OxxxxC(bit0 ^ bit31, bit0);
}
void BX_CPU_C::ROR_Ed(bxInstruction_c *i)
{
Bit32u op1_32, result_32;
unsigned count;
unsigned bit31, bit30;
if (i->b1() == 0xc1)
count = i->Ib() & 0x1f;
@ -191,20 +192,17 @@ void BX_CPU_C::ROR_Ed(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
/* set eflags:
* ROR count affects the following flags: C, O
*/
bx_bool result_b31 = (result_32 & 0x80000000) != 0;
bx_bool result_b30 = (result_32 & 0x40000000) != 0;
set_CF(result_b31);
set_OF(result_b31 ^ result_b30);
bit31 = (result_32 >> 31) & 1;
bit30 = (result_32 >> 30) & 1;
// of = result30 ^ result31
SET_FLAGS_OxxxxC(bit30 ^ bit31, bit31);
}
void BX_CPU_C::RCL_Ed(bxInstruction_c *i)
{
Bit32u op1_32, result_32;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc1)
count = i->Ib() & 0x1f;
@ -240,19 +238,16 @@ void BX_CPU_C::RCL_Ed(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
/* set eflags:
* RCL count affects the following flags: C, O
*/
bx_bool temp_CF = (op1_32 >> (32 - count)) & 0x01;
set_CF(temp_CF);
set_OF(temp_CF ^ (result_32 >> 31));
cf = (op1_32 >> (32 - count)) & 0x1;
of = cf ^ (result_32 >> 31); // of = cf ^ result31
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::RCR_Ed(bxInstruction_c *i)
{
Bit32u op1_32, result_32;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc1)
count = i->Ib() & 0x1f;
@ -288,18 +283,17 @@ void BX_CPU_C::RCR_Ed(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
/* set eflags:
* RCR count affects the following flags: C, O
*/
cf = (op1_32 >> (count - 1)) & 0x1;
of = ((result_32 << 1) ^ result_32) >> 31; // of = result30 ^ result31
SET_FLAGS_OxxxxC(of, cf);
set_CF((op1_32 >> (count - 1)) & 0x01);
set_OF((((result_32 << 1) ^ result_32) & 0x80000000) > 0);
}
void BX_CPU_C::SHL_Ed(bxInstruction_c *i)
{
Bit32u op1_32, result_32;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc1)
count = i->Ib() & 0x1f;
@ -319,7 +313,10 @@ void BX_CPU_C::SHL_Ed(bxInstruction_c *i)
if (!count) return;
/* count < 32, since only lower 5 bits used */
result_32 = (op1_32 << count);
cf = (op1_32 >> (32 - count)) & 0x1;
of = cf ^ (result_32 >> 31);
/* now write result back to destination */
if (i->modC0()) {
@ -329,13 +326,15 @@ void BX_CPU_C::SHL_Ed(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
SET_FLAGS_OSZAPC_32(op1_32, count, result_32, BX_INSTR_SHL32);
SET_FLAGS_OSZAPC_LOGIC_32(result_32); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHR_Ed(bxInstruction_c *i)
{
Bit32u op1_32, result_32;
unsigned count;
unsigned of, cf;
if (i->b1() == 0xc1)
count = i->Ib() & 0x1f;
@ -356,7 +355,6 @@ void BX_CPU_C::SHR_Ed(bxInstruction_c *i)
if (!count) return;
result_32 = (op1_32 >> count);
SET_FLAGS_OSZAPC_32(op1_32, count, result_32, BX_INSTR_SHR32);
/* now write result back to destination */
if (i->modC0()) {
@ -365,6 +363,14 @@ void BX_CPU_C::SHR_Ed(bxInstruction_c *i)
else {
write_RMW_virtual_dword(result_32);
}
cf = (op1_32 >> (count - 1)) & 0x1;
// note, that of == result31 if count == 1 and
// of == 0 if count >= 2
of = ((result_32 << 1) ^ result_32) >> 31;
SET_FLAGS_OSZAPC_LOGIC_32(result_32); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SAR_Ed(bxInstruction_c *i)
@ -406,7 +412,7 @@ void BX_CPU_C::SAR_Ed(bxInstruction_c *i)
write_RMW_virtual_dword(result_32);
}
SET_FLAGS_OSZAPC_LOGIC_32(result_32); /* handle undefined SF, ZF and AF flags */
SET_FLAGS_OSZAPC_LOGIC_32(result_32); /* handle SF, ZF and AF flags */
set_CF((op1_32 >> (count - 1)) & 1);
clear_OF(); /* signed overflow cannot happen in SAR instruction */
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: shift64.cc,v 1.26 2007-12-06 18:35:33 sshwarts Exp $
// $Id: shift64.cc,v 1.27 2007-12-06 20:39:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -38,8 +38,7 @@ void BX_CPU_C::SHLD_EqGq(bxInstruction_c *i)
{
Bit64u op1_64, op2_64, result_64;
unsigned count;
/* op1:op2 << count. result stored in op1 */
unsigned cf, of;
if (i->b1() == 0x1a4)
count = i->Ib();
@ -71,16 +70,18 @@ void BX_CPU_C::SHLD_EqGq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
/* set eflags:
* SHLD count affects the following flags: O,S,Z,A,P,C
*/
SET_FLAGS_OSZAPC_64(op1_64, count, result_64, BX_INSTR_SHL64);
SET_FLAGS_OSZAPC_LOGIC_64(result_64); /* handle SF, ZF and AF flags */
cf = (op1_64 >> (64 - count)) & 0x1;
of = cf ^ (result_64 >> 63); // of = cf ^ result63
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHRD_EqGq(bxInstruction_c *i)
{
Bit64u op1_64, op2_64, result_64;
unsigned count;
unsigned cf, of;
if (i->b1() == 0x1ac)
count = i->Ib();
@ -112,16 +113,18 @@ void BX_CPU_C::SHRD_EqGq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
/* set eflags:
* SHRD count affects the following flags: O,S,Z,A,P,C
*/
SET_FLAGS_OSZAPC_64(op1_64, count, result_64, BX_INSTR_SHRD64);
SET_FLAGS_OSZAPC_LOGIC_64(result_64); /* handle SF, ZF and AF flags */
cf = (op1_64 >> (count - 1)) & 0x1;
of = ((result_64 << 1) ^ result_64) >> 63; // of = result62 ^ result63
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::ROL_Eq(bxInstruction_c *i)
{
Bit64u op1_64, result_64;
unsigned count;
unsigned bit0, bit63;
if (i->b1() == 0xc1)
count = i->Ib() & 0x3f;
@ -151,19 +154,17 @@ void BX_CPU_C::ROL_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
/* set eflags:
* ROL count affects the following flags: C, O
*/
bx_bool temp_CF = (result_64 & 0x01);
set_CF(temp_CF);
set_OF(temp_CF ^ (result_64 >> 63));
bit0 = (result_64 & 0x1);
bit63 = (result_64 >> 63);
// of = cf ^ result63
SET_FLAGS_OxxxxC(bit0 ^ bit63, bit0);
}
void BX_CPU_C::ROR_Eq(bxInstruction_c *i)
{
Bit64u op1_64, result_64;
Bit64u op1_64, result_64;
unsigned count;
unsigned bit62, bit63;
if (i->b1() == 0xc1)
count = i->Ib() & 0x3f;
@ -193,20 +194,17 @@ void BX_CPU_C::ROR_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
/* set eflags:
* ROR count affects the following flags: C, O
*/
bx_bool result_b63 = (result_64 & BX_CONST64(0x8000000000000000)) != 0;
bx_bool result_b62 = (result_64 & BX_CONST64(0x4000000000000000)) != 0;
set_CF(result_b63);
set_OF(result_b63 ^ result_b62);
bit63 = (result_64 >> 63) & 1;
bit62 = (result_64 >> 62) & 1;
// of = result62 ^ result63
SET_FLAGS_OxxxxC(bit62 ^ bit63, bit63);
}
void BX_CPU_C::RCL_Eq(bxInstruction_c *i)
{
Bit64u op1_64, result_64;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc1)
count = i->Ib() & 0x3f;
@ -242,19 +240,16 @@ void BX_CPU_C::RCL_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
/* set eflags:
* RCL count affects the following flags: C, O
*/
bx_bool temp_CF = (op1_64 >> (64 - count)) & 0x01;
set_CF(temp_CF);
set_OF(temp_CF ^ (result_64 >> 63));
cf = (op1_64 >> (64 - count)) & 0x1;
of = cf ^ (result_64 >> 63); // of = cf ^ result63
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::RCR_Eq(bxInstruction_c *i)
{
Bit64u op1_64, result_64;
unsigned count;
unsigned of, cf;
if (i->b1() == 0xc1)
count = i->Ib() & 0x3f;
@ -290,18 +285,16 @@ void BX_CPU_C::RCR_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
/* set eflags:
* RCR count affects the following flags: C, O
*/
set_CF((op1_64 >> (count - 1)) & 0x01);
set_OF((((result_64 << 1) ^ result_64) & BX_CONST64(0x8000000000000000)) > 0);
cf = (op1_64 >> (count - 1)) & 0x1;
of = ((result_64 << 1) ^ result_64) >> 63;
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHL_Eq(bxInstruction_c *i)
{
Bit64u op1_64, result_64;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc1)
count = i->Ib() & 0x3f;
@ -321,7 +314,10 @@ void BX_CPU_C::SHL_Eq(bxInstruction_c *i)
if (!count) return;
/* count < 64, since only lower 6 bits used */
result_64 = (op1_64 << count);
cf = (op1_64 >> (64 - count)) & 0x1;
of = cf ^ (result_64 >> 63);
/* now write result back to destination */
if (i->modC0()) {
@ -331,13 +327,15 @@ void BX_CPU_C::SHL_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
SET_FLAGS_OSZAPC_64(op1_64, count, result_64, BX_INSTR_SHL64);
SET_FLAGS_OSZAPC_LOGIC_64(result_64); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHR_Eq(bxInstruction_c *i)
{
Bit64u op1_64, result_64;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc1)
count = i->Ib() & 0x3f;
@ -367,7 +365,13 @@ void BX_CPU_C::SHR_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
SET_FLAGS_OSZAPC_64(op1_64, count, result_64, BX_INSTR_SHR64);
cf = (op1_64 >> (count - 1)) & 0x1;
// note, that of == result63 if count == 1 and
// of == 0 if count >= 2
of = ((result_64 << 1) ^ result_64) >> 63;
SET_FLAGS_OSZAPC_LOGIC_64(result_64); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SAR_Eq(bxInstruction_c *i)
@ -393,7 +397,7 @@ void BX_CPU_C::SAR_Eq(bxInstruction_c *i)
if (!count) return;
/* count < 64, since only lower 5 bits used */
/* count < 64, since only lower 6 bits used */
if (op1_64 & BX_CONST64(0x8000000000000000)) {
result_64 = (op1_64 >> count) | (BX_CONST64(0xffffffffffffffff) << (64 - count));
}
@ -409,7 +413,7 @@ void BX_CPU_C::SAR_Eq(bxInstruction_c *i)
write_RMW_virtual_qword(result_64);
}
SET_FLAGS_OSZAPC_LOGIC_64(result_64); /* handle undefined SF, ZF and AF flags */
SET_FLAGS_OSZAPC_LOGIC_64(result_64); /* handle SF, ZF and AF flags */
set_CF((op1_64 >> (count - 1)) & 1);
clear_OF(); /* signed overflow cannot happen in SAR instruction */
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: shift8.cc,v 1.30 2007-12-06 18:35:33 sshwarts Exp $
// $Id: shift8.cc,v 1.31 2007-12-06 20:39:11 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -63,7 +63,7 @@ void BX_CPU_C::ROL_Eb(bxInstruction_c *i)
return;
}
count &= 0x07; // use only lowest 3 bits
count &= 0x7; // use only lowest 3 bits
result_8 = (op1_8 << count) | (op1_8 >> (8 - count));
@ -116,7 +116,8 @@ void BX_CPU_C::ROR_Eb(bxInstruction_c *i)
}
return;
}
count &= 0x07; /* use only bottom 3 bits */
count &= 0x7; /* use only bottom 3 bits */
result_8 = (op1_8 >> count) | (op1_8 << (8 - count));
@ -142,6 +143,7 @@ void BX_CPU_C::RCL_Eb(bxInstruction_c *i)
{
Bit8u op1_8, result_8;
unsigned count;
unsigned of, cf;
if (i->b1() == 0xc0)
count = i->Ib();
@ -179,19 +181,16 @@ void BX_CPU_C::RCL_Eb(bxInstruction_c *i)
write_RMW_virtual_byte(result_8);
}
/* set eflags:
* RCL count affects the following flags: C, O
*/
bx_bool temp_CF = (op1_8 >> (8 - count)) & 0x01;
set_CF(temp_CF);
set_OF(temp_CF ^ (result_8 >> 7));
cf = (op1_8 >> (8 - count)) & 0x01;
of = cf ^ (result_8 >> 7); // of = cf ^ result7
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::RCR_Eb(bxInstruction_c *i)
{
Bit8u op1_8, result_8;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc0)
count = i->Ib();
@ -224,18 +223,16 @@ void BX_CPU_C::RCR_Eb(bxInstruction_c *i)
write_RMW_virtual_byte(result_8);
}
/* set eflags:
* RCR count affects the following flags: C, O
*/
set_CF((op1_8 >> (count - 1)) & 0x01);
set_OF((((result_8 << 1) ^ result_8) & 0x80) > 0);
cf = (op1_8 >> (count - 1)) & 0x1;
of = ((result_8 << 1) ^ result_8) >> 7; // of = result6 ^ result7
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHL_Eb(bxInstruction_c *i)
{
Bit8u op1_8, result_8;
unsigned count;
unsigned of = 0, cf = 0;
if (i->b1() == 0xc0)
count = i->Ib();
@ -257,7 +254,14 @@ void BX_CPU_C::SHL_Eb(bxInstruction_c *i)
if (!count) return;
result_8 = (op1_8 << count);
if (count <= 8) {
result_8 = (op1_8 << count);
cf = (op1_8 >> (8 - count)) & 0x1;
of = cf ^ (result_8 >> 7);
}
else {
result_8 = 0;
}
/* now write result back to destination */
if (i->modC0()) {
@ -267,14 +271,15 @@ void BX_CPU_C::SHL_Eb(bxInstruction_c *i)
write_RMW_virtual_byte(result_8);
}
SET_FLAGS_OSZAPC_8(op1_8, count, result_8, BX_INSTR_SHL8);
SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SHR_Eb(bxInstruction_c *i)
{
Bit8u op1_8, result_8;
unsigned count;
unsigned cf, of;
if (i->b1() == 0xc0)
count = i->Ib();
@ -306,13 +311,19 @@ void BX_CPU_C::SHR_Eb(bxInstruction_c *i)
write_RMW_virtual_byte(result_8);
}
SET_FLAGS_OSZAPC_8(op1_8, count, result_8, BX_INSTR_SHR8);
cf = (op1_8 >> (count - 1)) & 0x1;
// note, that of == result7 if count == 1 and
// of == 0 if count >= 2
of = ((result_8 << 1) ^ result_8) >> 7;
SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* handle SF, ZF and AF flags */
SET_FLAGS_OxxxxC(of, cf);
}
void BX_CPU_C::SAR_Eb(bxInstruction_c *i)
{
Bit8u op1_8, result_8;
unsigned count;
unsigned count, cf;
if (i->b1() == 0xc0)
count = i->Ib();
@ -342,8 +353,7 @@ void BX_CPU_C::SAR_Eb(bxInstruction_c *i)
result_8 = (op1_8 >> count);
}
SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* handle undefined SF, ZF and AF flags */
set_CF((op1_8 >> (count - 1)) & 0x1);
cf = (op1_8 >> (count - 1)) & 0x1;
}
else {
if (op1_8 & 0x80) {
@ -353,11 +363,12 @@ void BX_CPU_C::SAR_Eb(bxInstruction_c *i)
result_8 = 0;
}
SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* handle undefined SF, ZF and AF flags */
set_CF(result_8 & 0x1);
cf = (result_8 & 0x1);
}
clear_OF(); /* signed overflow cannot happen in SAR instruction */
SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* handle SF, ZF and AF flags */
/* signed overflow cannot happen in SAR instruction */
SET_FLAGS_OxxxxC(0, cf);
/* now write result back to destination */
if (i->modC0()) {