// 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::BOUND_GvMa(BxInstruction_t *i)
{
#if BX_CPU_LEVEL < 2
  bx_panic("BOUND_GvMa: not supported on 8086!\n");
#else

  if (i->mod == 0xc0) {
    /* undefined opcode exception */
    bx_panic("bound: op2 must be mem ref\n");
    UndefinedOpcode(i);
    }

  if (i->os_32) {
    Bit32s bound_min, bound_max;
    Bit32s op1_32;

    op1_32 = BX_READ_32BIT_REG(i->nnn);

    read_virtual_dword(i->seg, i->rm_addr, (Bit32u *) &bound_min);
    read_virtual_dword(i->seg, i->rm_addr+4, (Bit32u *) &bound_max);

    /* ??? */
    if ( (op1_32 < bound_min) || (op1_32 > bound_max) ) {
      bx_printf("BOUND: fails bounds test\n");
      exception(5, 0, 0);
      }
    }
  else {
    Bit16s bound_min, bound_max;
    Bit16s op1_16;

    op1_16 = BX_READ_16BIT_REG(i->nnn);

    read_virtual_word(i->seg, i->rm_addr, (Bit16u *) &bound_min);
    read_virtual_word(i->seg, i->rm_addr+2, (Bit16u *) &bound_max);

    /* ??? */
    if ( (op1_16 < bound_min) || (op1_16 > bound_max) ) {
      bx_printf("BOUND: fails bounds test\n");
      exception(5, 0, 0);
      }
    }

#endif
}

  void
BX_CPU_C::INT1(BxInstruction_t *i)
{
  // This is an undocumented instrucion (opcode 0xf1)
  // which is useful for an ICE system.

#if BX_DEBUGGER
  BX_CPU_THIS_PTR show_flag |= Flag_int;
#endif

  interrupt(1, 1, 0, 0);
  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
                      BX_CPU_THIS_PTR eip);
}

  void
BX_CPU_C::INT3(BxInstruction_t *i)
{
  // INT 3 is not IOPL sensitive

#if BX_DEBUGGER
  BX_CPU_THIS_PTR show_flag |= Flag_int;
#endif

//bx_panic("INT3: bailing\n");
  interrupt(3, 1, 0, 0);
  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
                      BX_CPU_THIS_PTR eip);
}


  void
BX_CPU_C::INT_Ib(BxInstruction_t *i)
{
  Bit8u imm8;

#if BX_DEBUGGER
  BX_CPU_THIS_PTR show_flag |= Flag_int;
#endif

  imm8 = i->Ib;

  if (v8086_mode() && (IOPL<3)) {
    //bx_printf("int_ib: v8086: IOPL<3\n");
    exception(BX_GP_EXCEPTION, 0, 0);
    }

#ifdef SHOW_EXIT_STATUS
if ( (imm8 == 0x21) && (AH == 0x4c) ) {
  fprintf(stderr, "#(%u) INT 21/4C called AL=0x%02x, BX=0x%04x\n", BX_SIM_ID,
          (unsigned) AL, (unsigned) BX);
  bx_printf("INT 21/4C called AL=0x%02x, BX=0x%04x\n", (unsigned) AL, (unsigned) BX);
  }
#endif

  interrupt(imm8, 1, 0, 0);
  BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
                      BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
                      BX_CPU_THIS_PTR eip);
}


  void
BX_CPU_C::INTO(BxInstruction_t *i)
{

#if BX_DEBUGGER
  BX_CPU_THIS_PTR show_flag |= Flag_int;
#endif

  /* ??? is this IOPL sensitive ? */
  if (v8086_mode()) bx_panic("soft_int: v8086 mode unsupported\n");

  if (get_OF()) {
    interrupt(4, 1, 0, 0);
    BX_INSTR_FAR_BRANCH(BX_INSTR_IS_INT,
                        BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value,
                        BX_CPU_THIS_PTR eip);
    }
}
