// Copyright Notice
// ================
// BOCHS is Copyright 1994-1999 by Kevin P. Lawton.
//
// BOCHS is commercial software.
//
// For more information, read the file 'LICENSE' included in the bochs
// distribution.  If you don't have access to this file, or have questions
// regarding the licensing policy, the author may be contacted via:
//
//     US Mail:  Kevin Lawton
//               439 Marrett Rd.
//               Lexington, MA 02421-7714
//
//     EMail:    bochs@world.std.com






#include "bochs.h"





  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_printf("CLI: CPL > IOPL\n"); /* ??? */
      exception(BX_GP_EXCEPTION, 0, 0);
      return;
      }
    }
#if BX_CPU_LEVEL >= 3
  else if (v8086_mode()) {
    if (IOPL != 3) {
      //bx_printf("CLI: IOPL != 3\n"); /* ??? */
      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_printf("STI: CPL > IOPL\n"); /* ??? */
      exception(BX_GP_EXCEPTION, 0, 0);
      return;
      }
    }
#if BX_CPU_LEVEL >= 3
  else if (v8086_mode()) {
    if (IOPL != 3) {
      //bx_printf("STI: IOPL != 3\n"); /* ??? */
      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_printf("popf_fv: IOPL < 3\n");
      exception(BX_GP_EXCEPTION, 0, 0);
      return;
      }
    if (i->os_32) {
      bx_panic("POPFD(): not supported in virtual mode\n");
      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;
    }
}
