///////////////////////////////////////////////////////////////////////// // $Id: lazy_flags.cc,v 1.34 2007-03-18 19:29:17 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // 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 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // This array defines a look-up table for the even parity-ness // of an 8bit quantity, for optimal assignment of the parity bit // in the EFLAGS register const bx_bool bx_parity_lookup[256] = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; bx_bool BX_CPU_C::get_CFLazy(void) { unsigned cf; BX_ASSERT((BX_CPU_THIS_PTR lf_flags_status & 0x00000f) == BX_LF_INDEX_OSZAPC); switch (BX_CPU_THIS_PTR oszapc.instr) { case BX_INSTR_ADD8: cf = (BX_CPU_THIS_PTR oszapc.result_8 < BX_CPU_THIS_PTR oszapc.op1_8); break; case BX_INSTR_ADD16: cf = (BX_CPU_THIS_PTR oszapc.result_16 < BX_CPU_THIS_PTR oszapc.op1_16); break; case BX_INSTR_ADD32: cf = (BX_CPU_THIS_PTR oszapc.result_32 < BX_CPU_THIS_PTR oszapc.op1_32); break; #if BX_SUPPORT_X86_64 case BX_INSTR_ADD64: cf = (BX_CPU_THIS_PTR oszapc.result_64 < BX_CPU_THIS_PTR oszapc.op1_64); break; #endif // used only if CF = 1 when executing ADC instruction case BX_INSTR_ADC8: cf = (BX_CPU_THIS_PTR oszapc.result_8 <= BX_CPU_THIS_PTR oszapc.op1_8); break; // used only if CF = 1 when executing ADC instruction case BX_INSTR_ADC16: cf = (BX_CPU_THIS_PTR oszapc.result_16 <= BX_CPU_THIS_PTR oszapc.op1_16); break; // used only if CF = 1 when executing ADC instruction case BX_INSTR_ADC32: cf = (BX_CPU_THIS_PTR oszapc.result_32 <= BX_CPU_THIS_PTR oszapc.op1_32); break; #if BX_SUPPORT_X86_64 // used only if CF = 1 when executing ADC instruction case BX_INSTR_ADC64: cf = (BX_CPU_THIS_PTR oszapc.result_64 <= BX_CPU_THIS_PTR oszapc.op1_64); break; #endif case BX_INSTR_SUB8: cf = (BX_CPU_THIS_PTR oszapc.op1_8 < BX_CPU_THIS_PTR oszapc.op2_8); break; case BX_INSTR_SUB16: cf = (BX_CPU_THIS_PTR oszapc.op1_16 < BX_CPU_THIS_PTR oszapc.op2_16); break; case BX_INSTR_SUB32: cf = (BX_CPU_THIS_PTR oszapc.op1_32 < BX_CPU_THIS_PTR oszapc.op2_32); break; #if BX_SUPPORT_X86_64 case BX_INSTR_SUB64: cf = (BX_CPU_THIS_PTR oszapc.op1_64 < BX_CPU_THIS_PTR oszapc.op2_64); break; #endif // used only if CF = 1 when executing SBB instruction case BX_INSTR_SBB8: cf = (BX_CPU_THIS_PTR oszapc.op1_8 < BX_CPU_THIS_PTR oszapc.result_8) || (BX_CPU_THIS_PTR oszapc.op2_8==0xff); break; // used only if CF = 1 when executing SBB instruction case BX_INSTR_SBB16: cf = (BX_CPU_THIS_PTR oszapc.op1_16 < BX_CPU_THIS_PTR oszapc.result_16) || (BX_CPU_THIS_PTR oszapc.op2_16==0xffff); break; // used only if CF = 1 when executing SBB instruction case BX_INSTR_SBB32: cf = (BX_CPU_THIS_PTR oszapc.op1_32 < BX_CPU_THIS_PTR oszapc.result_32) || (BX_CPU_THIS_PTR oszapc.op2_32==0xffffffff); break; #if BX_SUPPORT_X86_64 // used only if CF = 1 when executing SBB instruction case BX_INSTR_SBB64: cf = (BX_CPU_THIS_PTR oszapc.op1_64 < BX_CPU_THIS_PTR oszapc.result_64) || (BX_CPU_THIS_PTR oszapc.op2_64==BX_CONST64(0xffffffffffffffff)); break; #endif case BX_INSTR_NEG8: cf = (BX_CPU_THIS_PTR oszapc.result_8 != 0); break; case BX_INSTR_NEG16: cf = (BX_CPU_THIS_PTR oszapc.result_16 != 0); break; case BX_INSTR_NEG32: cf = (BX_CPU_THIS_PTR oszapc.result_32 != 0); break; #if BX_SUPPORT_X86_64 case BX_INSTR_NEG64: cf = (BX_CPU_THIS_PTR oszapc.result_64 != 0); break; #endif case BX_INSTR_LOGIC8: case BX_INSTR_LOGIC16: case BX_INSTR_LOGIC32: case BX_INSTR_BITSCAN16: case BX_INSTR_BITSCAN32: #if BX_SUPPORT_X86_64 case BX_INSTR_LOGIC64: case BX_INSTR_BITSCAN64: #endif cf = 0; break; case BX_INSTR_SAR8: if (BX_CPU_THIS_PTR oszapc.op2_8 < 8) { cf = (BX_CPU_THIS_PTR oszapc.op1_8 >> (BX_CPU_THIS_PTR oszapc.op2_8 - 1)) & 0x01; } else { cf = (BX_CPU_THIS_PTR oszapc.op1_8 & 0x80) > 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_SAR16: if (BX_CPU_THIS_PTR oszapc.op2_16 < 16) { cf = (BX_CPU_THIS_PTR oszapc.op1_16 >> (BX_CPU_THIS_PTR oszapc.op2_16 - 1)) & 0x01; } else { cf = (BX_CPU_THIS_PTR oszapc.op1_16 & 0x8000) > 0; } 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_SAR32: 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_SAR64: 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 case BX_INSTR_IMUL8: cf = ! ((BX_CPU_THIS_PTR oszapc.op1_8 < 0x80 && BX_CPU_THIS_PTR oszapc.op2_8 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_8 & 0x80) && BX_CPU_THIS_PTR oszapc.op2_8 == 0xff)); break; case BX_INSTR_IMUL16: cf = ! ((BX_CPU_THIS_PTR oszapc.op1_16 < 0x8000 && BX_CPU_THIS_PTR oszapc.op2_16 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_16 & 0x8000) && BX_CPU_THIS_PTR oszapc.op2_16 == 0xffff)); break; case BX_INSTR_IMUL32: cf = ! ((BX_CPU_THIS_PTR oszapc.op1_32 < 0x80000000 && BX_CPU_THIS_PTR oszapc.op2_32 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_32 & 0x80000000) && BX_CPU_THIS_PTR oszapc.op2_32 == 0xffffffff)); break; #if BX_SUPPORT_X86_64 case BX_INSTR_IMUL64: cf = ! ((BX_CPU_THIS_PTR oszapc.op1_64 < BX_CONST64(0x8000000000000000) && BX_CPU_THIS_PTR oszapc.op2_64 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_64 & BX_CONST64(0x8000000000000000)) && BX_CPU_THIS_PTR oszapc.op2_64 == BX_CONST64(0xffffffffffffffff))); break; #endif case BX_INSTR_MUL8: cf = (BX_CPU_THIS_PTR oszapc.op2_8 != 0); break; case BX_INSTR_MUL16: cf = (BX_CPU_THIS_PTR oszapc.op2_16 != 0); break; case BX_INSTR_MUL32: cf = (BX_CPU_THIS_PTR oszapc.op2_32 != 0); break; #if BX_SUPPORT_X86_64 case BX_INSTR_MUL64: cf = (BX_CPU_THIS_PTR oszapc.op2_64 != 0); break; #endif default: cf = 0; // Keep compiler quiet. BX_PANIC(("get_CF: OSZAPC: unknown instr %u", (unsigned) BX_CPU_THIS_PTR oszapc.instr)); } BX_CPU_THIS_PTR lf_flags_status &= 0xfffff0; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<0); BX_CPU_THIS_PTR eflags.val32 |= (!!cf)<<0; return(cf); } bx_bool BX_CPU_C::get_AFLazy(void) { unsigned af; switch ((BX_CPU_THIS_PTR lf_flags_status>>8) & 0x00000f) { case BX_LF_INDEX_OSZAPC: switch (BX_CPU_THIS_PTR oszapc.instr) { case BX_INSTR_ADD8: case BX_INSTR_ADC8: case BX_INSTR_SUB8: case BX_INSTR_SBB8: af = ((BX_CPU_THIS_PTR oszapc.op1_8 ^ BX_CPU_THIS_PTR oszapc.op2_8) ^ BX_CPU_THIS_PTR oszapc.result_8) & 0x10; break; case BX_INSTR_ADD16: case BX_INSTR_ADC16: case BX_INSTR_SUB16: case BX_INSTR_SBB16: af = ((BX_CPU_THIS_PTR oszapc.op1_16 ^ BX_CPU_THIS_PTR oszapc.op2_16) ^ BX_CPU_THIS_PTR oszapc.result_16) & 0x10; break; case BX_INSTR_ADD32: case BX_INSTR_ADC32: case BX_INSTR_SUB32: case BX_INSTR_SBB32: af = ((BX_CPU_THIS_PTR oszapc.op1_32 ^ BX_CPU_THIS_PTR oszapc.op2_32) ^ BX_CPU_THIS_PTR oszapc.result_32) & 0x10; break; #if BX_SUPPORT_X86_64 case BX_INSTR_ADD64: case BX_INSTR_ADC64: case BX_INSTR_SUB64: case BX_INSTR_SBB64: af = ((BX_CPU_THIS_PTR oszapc.op1_64 ^ BX_CPU_THIS_PTR oszapc.op2_64) ^ BX_CPU_THIS_PTR oszapc.result_64) & 0x10; break; #endif case BX_INSTR_NEG8: af = (BX_CPU_THIS_PTR oszapc.result_8 & 0x0f) != 0; break; case BX_INSTR_NEG16: af = (BX_CPU_THIS_PTR oszapc.result_16 & 0x0f) != 0; break; case BX_INSTR_NEG32: af = (BX_CPU_THIS_PTR oszapc.result_32 & 0x0f) != 0; break; #if BX_SUPPORT_X86_64 case BX_INSTR_NEG64: af = (BX_CPU_THIS_PTR oszapc.result_64 & 0x0f) != 0; break; #endif case BX_INSTR_LOGIC8: case BX_INSTR_LOGIC16: case BX_INSTR_LOGIC32: case BX_INSTR_BITSCAN16: case BX_INSTR_BITSCAN32: #if BX_SUPPORT_X86_64 case BX_INSTR_LOGIC64: case BX_INSTR_BITSCAN64: case BX_INSTR_SAR64: case BX_INSTR_SHR64: case BX_INSTR_SHRD64: case BX_INSTR_SHL64: case BX_INSTR_IMUL64: case BX_INSTR_MUL64: #endif case BX_INSTR_SAR8: case BX_INSTR_SAR16: case BX_INSTR_SAR32: 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: case BX_INSTR_IMUL8: case BX_INSTR_IMUL16: case BX_INSTR_IMUL32: case BX_INSTR_MUL8: case BX_INSTR_MUL16: case BX_INSTR_MUL32: af = 0; break; default: af = 0; // Keep compiler quiet. BX_PANIC(("get_AF: OSZAPC: unknown instr %u", (unsigned) BX_CPU_THIS_PTR oszapc.instr)); } BX_CPU_THIS_PTR lf_flags_status &= 0xfff0ff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<4); BX_CPU_THIS_PTR eflags.val32 |= (!!af)<<4; return(af); case BX_LF_INDEX_OSZAP: switch (BX_CPU_THIS_PTR oszap.instr) { case BX_INSTR_INC8: af = (BX_CPU_THIS_PTR oszap.result_8 & 0x0f) == 0; break; case BX_INSTR_INC16: af = (BX_CPU_THIS_PTR oszap.result_16 & 0x0f) == 0; break; case BX_INSTR_INC32: af = (BX_CPU_THIS_PTR oszap.result_32 & 0x0f) == 0; break; #if BX_SUPPORT_X86_64 case BX_INSTR_INC64: af = (BX_CPU_THIS_PTR oszap.result_64 & 0x0f) == 0; break; #endif case BX_INSTR_DEC8: af = (BX_CPU_THIS_PTR oszap.result_8 & 0x0f) == 0x0f; break; case BX_INSTR_DEC16: af = (BX_CPU_THIS_PTR oszap.result_16 & 0x0f) == 0x0f; break; case BX_INSTR_DEC32: af = (BX_CPU_THIS_PTR oszap.result_32 & 0x0f) == 0x0f; break; #if BX_SUPPORT_X86_64 case BX_INSTR_DEC64: af = (BX_CPU_THIS_PTR oszap.result_64 & 0x0f) == 0x0f; break; #endif default: af = 0; // Keep compiler quiet. BX_PANIC(("get_AF: OSZAP: unknown instr %u", (unsigned) BX_CPU_THIS_PTR oszap.instr)); } BX_CPU_THIS_PTR lf_flags_status &= 0xfff0ff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<4); BX_CPU_THIS_PTR eflags.val32 |= (!!af)<<4; return(af); default: BX_PANIC(("get_AF: unknown case")); return(0); } } bx_bool BX_CPU_C::get_ZFLazy(void) { unsigned zf; switch ((BX_CPU_THIS_PTR lf_flags_status>>12) & 0x00000f) { case BX_LF_INDEX_OSZAPC: switch (BX_CPU_THIS_PTR oszapc.instr) { case BX_INSTR_LOGIC8: case BX_INSTR_ADD8: case BX_INSTR_ADC8: case BX_INSTR_SUB8: case BX_INSTR_SBB8: case BX_INSTR_NEG8: case BX_INSTR_SAR8: case BX_INSTR_SHR8: case BX_INSTR_SHL8: zf = (BX_CPU_THIS_PTR oszapc.result_8 == 0); break; case BX_INSTR_LOGIC16: case BX_INSTR_ADD16: case BX_INSTR_ADC16: case BX_INSTR_SUB16: case BX_INSTR_SBB16: case BX_INSTR_NEG16: case BX_INSTR_SAR16: case BX_INSTR_SHR16: case BX_INSTR_SHRD16: case BX_INSTR_SHL16: zf = (BX_CPU_THIS_PTR oszapc.result_16 == 0); break; case BX_INSTR_LOGIC32: case BX_INSTR_ADD32: case BX_INSTR_ADC32: case BX_INSTR_SUB32: case BX_INSTR_SBB32: case BX_INSTR_NEG32: case BX_INSTR_SAR32: case BX_INSTR_SHR32: case BX_INSTR_SHRD32: case BX_INSTR_SHL32: zf = (BX_CPU_THIS_PTR oszapc.result_32 == 0); break; #if BX_SUPPORT_X86_64 case BX_INSTR_LOGIC64: case BX_INSTR_ADD64: case BX_INSTR_ADC64: case BX_INSTR_SUB64: case BX_INSTR_SBB64: case BX_INSTR_NEG64: case BX_INSTR_SAR64: case BX_INSTR_SHR64: case BX_INSTR_SHRD64: case BX_INSTR_SHL64: zf = (BX_CPU_THIS_PTR oszapc.result_64 == 0); break; #endif case BX_INSTR_IMUL8: case BX_INSTR_MUL8: zf = (BX_CPU_THIS_PTR oszapc.op1_8 == 0); break; case BX_INSTR_IMUL16: case BX_INSTR_MUL16: zf = (BX_CPU_THIS_PTR oszapc.op1_16 == 0); break; case BX_INSTR_IMUL32: case BX_INSTR_MUL32: zf = (BX_CPU_THIS_PTR oszapc.op1_32 == 0); break; #if BX_SUPPORT_X86_64 case BX_INSTR_IMUL64: case BX_INSTR_MUL64: zf = (BX_CPU_THIS_PTR oszapc.op1_64 == 0); break; #endif case BX_INSTR_BITSCAN16: case BX_INSTR_BITSCAN32: #if BX_SUPPORT_X86_64 case BX_INSTR_BITSCAN64: #endif zf = 0; break; default: zf = 0; BX_PANIC(("get_ZF: OSZAPC: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0xff0fff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<6); BX_CPU_THIS_PTR eflags.val32 |= zf<<6; // zf always exactly 0 or 1. return(zf); case BX_LF_INDEX_OSZAP: switch (BX_CPU_THIS_PTR oszap.instr) { case BX_INSTR_INC8: case BX_INSTR_DEC8: zf = (BX_CPU_THIS_PTR oszap.result_8 == 0); break; case BX_INSTR_INC16: case BX_INSTR_DEC16: zf = (BX_CPU_THIS_PTR oszap.result_16 == 0); break; case BX_INSTR_INC32: case BX_INSTR_DEC32: zf = (BX_CPU_THIS_PTR oszap.result_32 == 0); break; #if BX_SUPPORT_X86_64 case BX_INSTR_INC64: case BX_INSTR_DEC64: zf = (BX_CPU_THIS_PTR oszap.result_64 == 0); break; #endif default: zf = 0; BX_PANIC(("get_ZF: OSZAP: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0xff0fff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<6); BX_CPU_THIS_PTR eflags.val32 |= zf<<6; // zf always exactly 0 or 1. return(zf); default: BX_PANIC(("get_ZF: unknown case")); return(0); } } bx_bool BX_CPU_C::get_SFLazy(void) { unsigned sf; switch ((BX_CPU_THIS_PTR lf_flags_status>>16) & 0x00000f) { case BX_LF_INDEX_OSZAPC: switch (BX_CPU_THIS_PTR oszapc.instr) { case BX_INSTR_LOGIC8: case BX_INSTR_ADD8: case BX_INSTR_ADC8: case BX_INSTR_SUB8: case BX_INSTR_SBB8: case BX_INSTR_NEG8: case BX_INSTR_SAR8: case BX_INSTR_SHR8: case BX_INSTR_SHL8: sf = (BX_CPU_THIS_PTR oszapc.result_8 >= 0x80); break; case BX_INSTR_LOGIC16: case BX_INSTR_ADD16: case BX_INSTR_ADC16: case BX_INSTR_SUB16: case BX_INSTR_SBB16: case BX_INSTR_NEG16: case BX_INSTR_SAR16: case BX_INSTR_SHR16: case BX_INSTR_SHRD16: case BX_INSTR_SHL16: case BX_INSTR_BITSCAN16: sf = (BX_CPU_THIS_PTR oszapc.result_16 >= 0x8000); break; case BX_INSTR_LOGIC32: case BX_INSTR_ADD32: case BX_INSTR_ADC32: case BX_INSTR_SUB32: case BX_INSTR_SBB32: case BX_INSTR_NEG32: case BX_INSTR_SAR32: case BX_INSTR_SHR32: case BX_INSTR_SHRD32: case BX_INSTR_SHL32: case BX_INSTR_BITSCAN32: sf = (BX_CPU_THIS_PTR oszapc.result_32 >= 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_LOGIC64: case BX_INSTR_ADD64: case BX_INSTR_ADC64: case BX_INSTR_SUB64: case BX_INSTR_SBB64: case BX_INSTR_NEG64: case BX_INSTR_SAR64: case BX_INSTR_SHR64: case BX_INSTR_SHRD64: case BX_INSTR_SHL64: case BX_INSTR_BITSCAN64: sf = (BX_CPU_THIS_PTR oszapc.result_64 >= BX_CONST64(0x8000000000000000)); break; #endif case BX_INSTR_IMUL8: case BX_INSTR_MUL8: sf = (BX_CPU_THIS_PTR oszapc.op1_8 >= 0x80); break; case BX_INSTR_IMUL16: case BX_INSTR_MUL16: sf = (BX_CPU_THIS_PTR oszapc.op1_16 >= 0x8000); break; case BX_INSTR_IMUL32: case BX_INSTR_MUL32: sf = (BX_CPU_THIS_PTR oszapc.op1_32 >= 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_IMUL64: case BX_INSTR_MUL64: sf = (BX_CPU_THIS_PTR oszapc.op1_64 >= BX_CONST64(0x8000000000000000)); break; #endif default: sf = 0; // Keep compiler quiet. BX_PANIC(("get_SF: OSZAPC: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0xf0ffff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<7); BX_CPU_THIS_PTR eflags.val32 |= (!!sf)<<7; return(sf); case BX_LF_INDEX_OSZAP: switch (BX_CPU_THIS_PTR oszap.instr) { case BX_INSTR_INC8: case BX_INSTR_DEC8: sf = (BX_CPU_THIS_PTR oszap.result_8 >= 0x80); break; case BX_INSTR_INC16: case BX_INSTR_DEC16: sf = (BX_CPU_THIS_PTR oszap.result_16 >= 0x8000); break; case BX_INSTR_INC32: case BX_INSTR_DEC32: sf = (BX_CPU_THIS_PTR oszap.result_32 >= 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_INC64: case BX_INSTR_DEC64: sf = (BX_CPU_THIS_PTR oszap.result_64 >= BX_CONST64(0x8000000000000000)); break; #endif default: sf = 0; // Keep compiler quiet. BX_PANIC(("get_SF: OSZAP: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0xf0ffff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<7); BX_CPU_THIS_PTR eflags.val32 |= (!!sf)<<7; return(sf); default: BX_PANIC(("get_SF: unknown case")); return(0); } } #define GET_ADD_OVERFLOW(op1, op2, result, mask) \ (((~((op1) ^ (op2)) & ((op2) ^ (result))) & (mask)) != 0) #define GET_SUB_OVERFLOW(op1, op2, result, mask) \ (((((op1) ^ (op2)) & ((op1) ^ (result))) & (mask)) != 0) bx_bool BX_CPU_C::get_OFLazy(void) { unsigned of; switch ((BX_CPU_THIS_PTR lf_flags_status>>20) & 0x00000f) { case BX_LF_INDEX_OSZAPC: switch (BX_CPU_THIS_PTR oszapc.instr) { case BX_INSTR_ADD8: case BX_INSTR_ADC8: of = GET_ADD_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_8, BX_CPU_THIS_PTR oszapc.op2_8, BX_CPU_THIS_PTR oszapc.result_8, 0x80); break; case BX_INSTR_ADD16: case BX_INSTR_ADC16: of = GET_ADD_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_16, BX_CPU_THIS_PTR oszapc.op2_16, BX_CPU_THIS_PTR oszapc.result_16, 0x8000); break; case BX_INSTR_ADD32: case BX_INSTR_ADC32: of = GET_ADD_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_32, BX_CPU_THIS_PTR oszapc.op2_32, BX_CPU_THIS_PTR oszapc.result_32, 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_ADD64: case BX_INSTR_ADC64: of = GET_ADD_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_64, BX_CPU_THIS_PTR oszapc.op2_64, BX_CPU_THIS_PTR oszapc.result_64, BX_CONST64(0x8000000000000000)); break; #endif case BX_INSTR_SUB8: case BX_INSTR_SBB8: of = GET_SUB_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_8, BX_CPU_THIS_PTR oszapc.op2_8, BX_CPU_THIS_PTR oszapc.result_8, 0x80); break; case BX_INSTR_SUB16: case BX_INSTR_SBB16: of = GET_SUB_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_16, BX_CPU_THIS_PTR oszapc.op2_16, BX_CPU_THIS_PTR oszapc.result_16, 0x8000); break; case BX_INSTR_SUB32: case BX_INSTR_SBB32: of = GET_SUB_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_32, BX_CPU_THIS_PTR oszapc.op2_32, BX_CPU_THIS_PTR oszapc.result_32, 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_SUB64: case BX_INSTR_SBB64: of = GET_SUB_OVERFLOW(BX_CPU_THIS_PTR oszapc.op1_64, BX_CPU_THIS_PTR oszapc.op2_64, BX_CPU_THIS_PTR oszapc.result_64, BX_CONST64(0x8000000000000000)); break; #endif case BX_INSTR_NEG8: of = (BX_CPU_THIS_PTR oszapc.result_8 == 0x80); break; case BX_INSTR_NEG16: of = (BX_CPU_THIS_PTR oszapc.result_16 == 0x8000); break; case BX_INSTR_NEG32: of = (BX_CPU_THIS_PTR oszapc.result_32 == 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_NEG64: of = (BX_CPU_THIS_PTR oszapc.result_64 == BX_CONST64(0x8000000000000000)); break; #endif case BX_INSTR_LOGIC8: case BX_INSTR_LOGIC16: case BX_INSTR_LOGIC32: case BX_INSTR_BITSCAN16: case BX_INSTR_BITSCAN32: case BX_INSTR_SAR8: case BX_INSTR_SAR16: case BX_INSTR_SAR32: #if BX_SUPPORT_X86_64 case BX_INSTR_LOGIC64: case BX_INSTR_BITSCAN64: case BX_INSTR_SAR64: #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 = (((BX_CPU_THIS_PTR oszapc.result_16 << 1) ^ BX_CPU_THIS_PTR oszapc.result_16) & 0x8000) > 0; break; case BX_INSTR_SHRD32: /* undocumented, but this formula works right for any shift count */ of = (((BX_CPU_THIS_PTR oszapc.result_32 << 1) ^ BX_CPU_THIS_PTR oszapc.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 = (((BX_CPU_THIS_PTR oszapc.result_64 << 1) ^ BX_CPU_THIS_PTR oszapc.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 ^ BX_CPU_THIS_PTR oszapc.result_8) & 0x80) > 0; else of = (((BX_CPU_THIS_PTR oszapc.op1_8 << (BX_CPU_THIS_PTR oszapc.op2_8 - 1)) ^ BX_CPU_THIS_PTR oszapc.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 ^ BX_CPU_THIS_PTR oszapc.result_16) & 0x8000) > 0; else of = (((BX_CPU_THIS_PTR oszapc.op1_16 << (BX_CPU_THIS_PTR oszapc.op2_16 - 1)) ^ BX_CPU_THIS_PTR oszapc.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 ^ BX_CPU_THIS_PTR oszapc.result_32) & 0x80000000) > 0; else of = (((BX_CPU_THIS_PTR oszapc.op1_32 << (BX_CPU_THIS_PTR oszapc.op2_32 - 1)) ^ BX_CPU_THIS_PTR oszapc.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 ^ BX_CPU_THIS_PTR oszapc.result_64) & BX_CONST64(0x8000000000000000)) > 0; else of = (((BX_CPU_THIS_PTR oszapc.op1_64 << (BX_CPU_THIS_PTR oszapc.op2_64 - 1)) ^ BX_CPU_THIS_PTR oszapc.result_64) & BX_CONST64(0x8000000000000000)) > 0; break; #endif case BX_INSTR_IMUL8: of = ! ((BX_CPU_THIS_PTR oszapc.op1_8 < 0x80 && BX_CPU_THIS_PTR oszapc.op2_8 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_8 & 0x80) && BX_CPU_THIS_PTR oszapc.op2_8 == 0xff)); break; case BX_INSTR_IMUL16: of = ! ((BX_CPU_THIS_PTR oszapc.op1_16 < 0x8000 && BX_CPU_THIS_PTR oszapc.op2_16 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_16 & 0x8000) && BX_CPU_THIS_PTR oszapc.op2_16 == 0xffff)); break; case BX_INSTR_IMUL32: of = ! ((BX_CPU_THIS_PTR oszapc.op1_32 < 0x80000000 && BX_CPU_THIS_PTR oszapc.op2_32 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_32 & 0x80000000) && BX_CPU_THIS_PTR oszapc.op2_32 == 0xffffffff)); break; #if BX_SUPPORT_X86_64 case BX_INSTR_IMUL64: of = ! ((BX_CPU_THIS_PTR oszapc.op1_64 < BX_CONST64(0x8000000000000000) && BX_CPU_THIS_PTR oszapc.op2_64 == 0) || ((BX_CPU_THIS_PTR oszapc.op1_64 & BX_CONST64(0x8000000000000000)) && BX_CPU_THIS_PTR oszapc.op2_64 == BX_CONST64(0xffffffffffffffff))); break; #endif case BX_INSTR_MUL8: of = (BX_CPU_THIS_PTR oszapc.op2_8 != 0); break; case BX_INSTR_MUL16: of = (BX_CPU_THIS_PTR oszapc.op2_16 != 0); break; case BX_INSTR_MUL32: of = (BX_CPU_THIS_PTR oszapc.op2_32 != 0); break; #if BX_SUPPORT_X86_64 case BX_INSTR_MUL64: of = (BX_CPU_THIS_PTR oszapc.op2_64 != 0); break; #endif default: of = 0; // Keep compiler happy. BX_PANIC(("get_OF: OSZAPC: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0x0fffff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<11); BX_CPU_THIS_PTR eflags.val32 |= (!!of)<<11; return(of); case BX_LF_INDEX_OSZAP: switch (BX_CPU_THIS_PTR oszap.instr) { case BX_INSTR_INC8: of = (BX_CPU_THIS_PTR oszap.result_8 == 0x80); break; case BX_INSTR_INC16: of = (BX_CPU_THIS_PTR oszap.result_16 == 0x8000); break; case BX_INSTR_INC32: of = (BX_CPU_THIS_PTR oszap.result_32 == 0x80000000); break; #if BX_SUPPORT_X86_64 case BX_INSTR_INC64: of = (BX_CPU_THIS_PTR oszap.result_64 == BX_CONST64(0x8000000000000000)); break; #endif case BX_INSTR_DEC8: of = (BX_CPU_THIS_PTR oszap.result_8 == 0x7F); break; case BX_INSTR_DEC16: of = (BX_CPU_THIS_PTR oszap.result_16 == 0x7FFF); break; case BX_INSTR_DEC32: of = (BX_CPU_THIS_PTR oszap.result_32 == 0x7FFFFFFF); break; #if BX_SUPPORT_X86_64 case BX_INSTR_DEC64: of = (BX_CPU_THIS_PTR oszap.result_64 == BX_CONST64(0x7FFFFFFFFFFFFFFF)); break; #endif default: of = 0; // Keep compiler happy. BX_PANIC(("get_OF: OSZAP: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0x0fffff; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<11); BX_CPU_THIS_PTR eflags.val32 |= (!!of)<<11; return(of); default: BX_PANIC(("get_OF: unknown case")); return(0); } } bx_bool BX_CPU_C::get_PFLazy(void) { unsigned pf; switch ((BX_CPU_THIS_PTR lf_flags_status>>4) & 0x00000f) { case BX_LF_INDEX_OSZAPC: switch (BX_CPU_THIS_PTR oszapc.instr) { case BX_INSTR_LOGIC8: case BX_INSTR_ADD8: case BX_INSTR_ADC8: case BX_INSTR_SUB8: case BX_INSTR_SBB8: case BX_INSTR_NEG8: case BX_INSTR_SAR8: case BX_INSTR_SHR8: case BX_INSTR_SHL8: pf = bx_parity_lookup[BX_CPU_THIS_PTR oszapc.result_8]; break; case BX_INSTR_LOGIC16: case BX_INSTR_ADD16: case BX_INSTR_ADC16: case BX_INSTR_SUB16: case BX_INSTR_SBB16: case BX_INSTR_NEG16: case BX_INSTR_SAR16: case BX_INSTR_SHR16: case BX_INSTR_SHRD16: case BX_INSTR_SHL16: case BX_INSTR_BITSCAN16: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszapc.result_16]; break; case BX_INSTR_LOGIC32: case BX_INSTR_ADD32: case BX_INSTR_ADC32: case BX_INSTR_SUB32: case BX_INSTR_SBB32: case BX_INSTR_NEG32: case BX_INSTR_SAR32: case BX_INSTR_SHR32: case BX_INSTR_SHRD32: case BX_INSTR_SHL32: case BX_INSTR_BITSCAN32: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszapc.result_32]; break; #if BX_SUPPORT_X86_64 case BX_INSTR_LOGIC64: case BX_INSTR_ADD64: case BX_INSTR_ADC64: case BX_INSTR_SUB64: case BX_INSTR_SBB64: case BX_INSTR_NEG64: case BX_INSTR_SAR64: case BX_INSTR_SHR64: case BX_INSTR_SHRD64: case BX_INSTR_SHL64: case BX_INSTR_BITSCAN64: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszapc.result_64]; break; #endif case BX_INSTR_IMUL8: case BX_INSTR_MUL8: pf = bx_parity_lookup[BX_CPU_THIS_PTR oszapc.op1_8]; break; case BX_INSTR_IMUL16: case BX_INSTR_MUL16: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszapc.op1_16]; break; case BX_INSTR_IMUL32: case BX_INSTR_MUL32: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszapc.op1_32]; break; #if BX_SUPPORT_X86_64 case BX_INSTR_IMUL64: case BX_INSTR_MUL64: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszapc.op1_64]; break; #endif default: pf = 0; // Keep compiler quiet. BX_PANIC(("get_PF: OSZAPC: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0xffff0f; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<2); BX_CPU_THIS_PTR eflags.val32 |= (pf)<<2; // pf is always 0 or 1 here return(pf); case BX_LF_INDEX_OSZAP: switch (BX_CPU_THIS_PTR oszap.instr) { case BX_INSTR_INC8: case BX_INSTR_DEC8: pf = bx_parity_lookup[BX_CPU_THIS_PTR oszap.result_8]; break; case BX_INSTR_INC16: case BX_INSTR_DEC16: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszap.result_16]; break; case BX_INSTR_INC32: case BX_INSTR_DEC32: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszap.result_32]; break; #if BX_SUPPORT_X86_64 case BX_INSTR_INC64: case BX_INSTR_DEC64: pf = bx_parity_lookup[(Bit8u) BX_CPU_THIS_PTR oszap.result_64]; break; #endif default: pf = 0; // Keep compiler quiet. BX_PANIC(("get_PF: OSZAP: unknown instr")); } BX_CPU_THIS_PTR lf_flags_status &= 0xffff0f; BX_CPU_THIS_PTR eflags.val32 &= ~(1<<2); BX_CPU_THIS_PTR eflags.val32 |= (pf)<<2; // pf is always 0 or 1 here return(pf); default: BX_PANIC(("get_PF: unknown case")); return(0); } }