///////////////////////////////////////////////////////////////////////// // $Id: flag_ctrl.cc,v 1.6 2001-10-03 13:10:37 bdenney 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" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPU_C::SAHF(BxInstruction_t *i) { set_SF((AH & 0x80) >> 7); set_ZF((AH & 0x40) >> 6); set_AF((AH & 0x10) >> 4); set_CF(AH & 0x01); set_PF((AH & 0x04) >> 2); } void BX_CPU_C::LAHF(BxInstruction_t *i) { AH = (get_SF() ? 0x80 : 0) | (get_ZF() ? 0x40 : 0) | (get_AF() ? 0x10 : 0) | (get_PF() ? 0x04 : 0) | (0x02) | (get_CF() ? 0x01 : 0); } void BX_CPU_C::CLC(BxInstruction_t *i) { set_CF(0); } void BX_CPU_C::STC(BxInstruction_t *i) { set_CF(1); } void BX_CPU_C::CLI(BxInstruction_t *i) { #if BX_CPU_LEVEL >= 2 if (protected_mode()) { if (CPL > IOPL) { //BX_INFO(("CLI: CPL > IOPL")); /* ??? */ exception(BX_GP_EXCEPTION, 0, 0); return; } } #if BX_CPU_LEVEL >= 3 else if (v8086_mode()) { if (IOPL != 3) { //BX_INFO(("CLI: IOPL != 3")); /* ??? */ exception(BX_GP_EXCEPTION, 0, 0); return; } } #endif #endif BX_CPU_THIS_PTR eflags.if_ = 0; } void BX_CPU_C::STI(BxInstruction_t *i) { #if BX_CPU_LEVEL >= 2 if (protected_mode()) { if (CPL > IOPL) { //BX_INFO(("STI: CPL > IOPL")); /* ??? */ exception(BX_GP_EXCEPTION, 0, 0); return; } } #if BX_CPU_LEVEL >= 3 else if (v8086_mode()) { if (IOPL != 3) { //BX_INFO(("STI: IOPL != 3")); /* ??? */ exception(BX_GP_EXCEPTION, 0, 0); return; } } #endif #endif if (!BX_CPU_THIS_PTR eflags.if_) { BX_CPU_THIS_PTR eflags.if_ = 1; BX_CPU_THIS_PTR inhibit_mask |= BX_INHIBIT_INTERRUPTS; BX_CPU_THIS_PTR async_event = 1; } } void BX_CPU_C::CLD(BxInstruction_t *i) { BX_CPU_THIS_PTR eflags.df = 0; } void BX_CPU_C::STD(BxInstruction_t *i) { BX_CPU_THIS_PTR eflags.df = 1; } void BX_CPU_C::CMC(BxInstruction_t *i) { set_CF( !get_CF() ); } void BX_CPU_C::PUSHF_Fv(BxInstruction_t *i) { if (v8086_mode() && (IOPL<3)) { exception(BX_GP_EXCEPTION, 0, 0); return; } #if BX_CPU_LEVEL >= 3 if (i->os_32) { push_32(read_eflags() & 0x00fcffff); } else #endif { push_16(read_flags()); } } void BX_CPU_C::POPF_Fv(BxInstruction_t *i) { #if BX_CPU_LEVEL >= 3 if (v8086_mode()) { if (IOPL < 3) { //BX_INFO(("popf_fv: IOPL < 3")); exception(BX_GP_EXCEPTION, 0, 0); return; } if (i->os_32) { BX_PANIC(("POPFD(): not supported in virtual mode")); exception(BX_GP_EXCEPTION, 0, 0); return; } } if (i->os_32) { Bit32u eflags; pop_32(&eflags); eflags &= 0x00277fd7; if (!real_mode()) { write_eflags(eflags, /* change IOPL? */ CPL==0, /* change IF? */ CPL<=IOPL, 0, 0); } else { /* real mode */ write_eflags(eflags, /* change IOPL? */ 1, /* change IF? */ 1, 0, 0); } } else #endif /* BX_CPU_LEVEL >= 3 */ { /* 16 bit opsize */ Bit16u flags; pop_16(&flags); if (!real_mode()) { write_flags(flags, /* change IOPL? */ CPL==0, /* change IF? */ CPL<=IOPL); } else { /* real mode */ write_flags(flags, /* change IOPL? */ 1, /* change IF? */ 1); } } } void BX_CPU_C::SALC(BxInstruction_t *i) { if ( get_CF() ) { AL = 0xff; } else { AL = 0x00; } }