direct-io.hg

changeset 13375:a6f10ffa07a0

[XEN] Emulate PUSHA/POPA/ARPL/BOUND.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@localhost.localdomain
date Sun Jan 14 16:00:19 2007 +0000 (2007-01-14)
parents 328deec3febf
children 179453a85929
files xen/arch/x86/x86_emulate.c
line diff
     1.1 --- a/xen/arch/x86/x86_emulate.c	Sun Jan 14 13:15:13 2007 +0000
     1.2 +++ b/xen/arch/x86/x86_emulate.c	Sun Jan 14 16:00:19 2007 +0000
     1.3 @@ -47,9 +47,8 @@
     1.4  #define SrcReg      (1<<3) /* Register operand. */
     1.5  #define SrcMem      (2<<3) /* Memory operand. */
     1.6  #define SrcMem16    (3<<3) /* Memory operand (16-bit). */
     1.7 -#define SrcMem32    (4<<3) /* Memory operand (32-bit). */
     1.8 -#define SrcImm      (5<<3) /* Immediate operand. */
     1.9 -#define SrcImmByte  (6<<3) /* 8-bit sign-extended immediate operand. */
    1.10 +#define SrcImm      (4<<3) /* Immediate operand. */
    1.11 +#define SrcImmByte  (5<<3) /* 8-bit sign-extended immediate operand. */
    1.12  #define SrcMask     (7<<3)
    1.13  /* Generic ModRM decode. */
    1.14  #define ModRM       (1<<6)
    1.15 @@ -100,7 +99,7 @@ static uint8_t opcode_table[256] = {
    1.16      ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
    1.17      ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps|Mov,
    1.18      /* 0x60 - 0x67 */
    1.19 -    0, 0, 0, DstReg|SrcMem32|ModRM|Mov /* movsxd (x86/64) */,
    1.20 +    ImplicitOps, ImplicitOps, DstReg|SrcMem|ModRM, DstReg|SrcMem16|ModRM|Mov,
    1.21      0, 0, 0, 0,
    1.22      /* 0x68 - 0x6F */
    1.23      ImplicitOps|Mov, DstMem|SrcImm|ModRM|Mov,
    1.24 @@ -259,6 +258,8 @@ struct operand {
    1.25  
    1.26  /* Exception definitions. */
    1.27  #define EXC_DE  0
    1.28 +#define EXC_BR  5
    1.29 +#define EXC_UD  6
    1.30  #define EXC_GP 13
    1.31  
    1.32  /*
    1.33 @@ -884,9 +885,6 @@ x86_emulate(
    1.34      case SrcMem16:
    1.35          ea.bytes = 2;
    1.36          goto srcmem_common;
    1.37 -    case SrcMem32:
    1.38 -        ea.bytes = 4;
    1.39 -        goto srcmem_common;
    1.40      case SrcMem:
    1.41          ea.bytes = (d & ByteOp) ? 1 : op_bytes;
    1.42      srcmem_common:
    1.43 @@ -1065,10 +1063,42 @@ x86_emulate(
    1.44          emulate_2op_SrcV("cmp", src, dst, _regs.eflags);
    1.45          break;
    1.46  
    1.47 -    case 0x63: /* movsxd */
    1.48 -        if ( !mode_64bit() )
    1.49 -            goto cannot_emulate;
    1.50 -        dst.val = (int32_t)src.val;
    1.51 +    case 0x62: /* bound */ {
    1.52 +        unsigned long src_val2;
    1.53 +        int lb, ub, idx;
    1.54 +        generate_exception_if(mode_64bit() || (src.type != OP_MEM), EXC_UD);
    1.55 +        if ( (rc = ops->read(src.mem.seg, src.mem.off + op_bytes,
    1.56 +                             &src_val2, op_bytes, ctxt)) )
    1.57 +            goto done;
    1.58 +        ub  = (op_bytes == 2) ? (int16_t)src_val2 : (int32_t)src_val2;
    1.59 +        lb  = (op_bytes == 2) ? (int16_t)src.val  : (int32_t)src.val;
    1.60 +        idx = (op_bytes == 2) ? (int16_t)dst.val  : (int32_t)dst.val;
    1.61 +        generate_exception_if((idx < lb) || (idx > ub), EXC_BR);
    1.62 +        dst.type = OP_NONE;
    1.63 +        break;
    1.64 +    }
    1.65 +
    1.66 +    case 0x63: /* movsxd (x86/64) / arpl (x86/32) */
    1.67 +        if ( mode_64bit() )
    1.68 +        {
    1.69 +            /* movsxd */
    1.70 +            if ( src.type == OP_REG )
    1.71 +                src.val = *(int32_t *)src.reg;
    1.72 +            else if ( (rc = ops->read(src.mem.seg, src.mem.off,
    1.73 +                                      &src.val, 4, ctxt)) )
    1.74 +                goto done;
    1.75 +            dst.val = (int32_t)src.val;
    1.76 +        }
    1.77 +        else
    1.78 +        {
    1.79 +            /* arpl */
    1.80 +            uint16_t src_val = dst.val;
    1.81 +            dst = src;
    1.82 +            if ( (src_val & 3) > (dst.val & 3) )
    1.83 +                dst.val  = (dst.val & ~3) | (src_val & 3);
    1.84 +            else
    1.85 +                dst.type = OP_NONE;
    1.86 +        }
    1.87          break;
    1.88  
    1.89      case 0x69: /* imul imm16/32 */
    1.90 @@ -1140,7 +1170,7 @@ x86_emulate(
    1.91          break;
    1.92  
    1.93      case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
    1.94 -        fail_if((modrm_reg & 7) != 0);
    1.95 +        generate_exception_if((modrm_reg & 7) != 0, EXC_UD);
    1.96      case 0x88 ... 0x8b: /* mov */
    1.97          dst.val = src.val;
    1.98          break;
    1.99 @@ -1150,7 +1180,7 @@ x86_emulate(
   1.100          break;
   1.101  
   1.102      case 0x8f: /* pop (sole member of Grp1a) */
   1.103 -        fail_if((modrm_reg & 7) != 0);
   1.104 +        generate_exception_if((modrm_reg & 7) != 0, EXC_UD);
   1.105          /* 64-bit mode: POP defaults to a 64-bit operand. */
   1.106          if ( mode_64bit() && (dst.bytes == 4) )
   1.107              dst.bytes = 8;
   1.108 @@ -1415,7 +1445,7 @@ x86_emulate(
   1.109          break;
   1.110  
   1.111      case 0xfe: /* Grp4 */
   1.112 -        fail_if((modrm_reg & 7) >= 2);
   1.113 +        generate_exception_if((modrm_reg & 7) >= 2, EXC_UD);
   1.114      case 0xff: /* Grp5 */
   1.115          switch ( modrm_reg & 7 )
   1.116          {
   1.117 @@ -1455,7 +1485,7 @@ x86_emulate(
   1.118              dst.type = OP_NONE;
   1.119              break;
   1.120          case 7:
   1.121 -            fail_if(1);
   1.122 +            generate_exception_if(1, EXC_UD);
   1.123          default:
   1.124              goto cannot_emulate;
   1.125          }
   1.126 @@ -1525,7 +1555,7 @@ x86_emulate(
   1.127      case 0x27: /* daa */ {
   1.128          uint8_t al = _regs.eax;
   1.129          unsigned long eflags = _regs.eflags;
   1.130 -        fail_if(mode_64bit());
   1.131 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.132          _regs.eflags &= ~(EFLG_CF|EFLG_AF);
   1.133          if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
   1.134          {
   1.135 @@ -1547,7 +1577,7 @@ x86_emulate(
   1.136      case 0x2f: /* das */ {
   1.137          uint8_t al = _regs.eax;
   1.138          unsigned long eflags = _regs.eflags;
   1.139 -        fail_if(mode_64bit());
   1.140 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.141          _regs.eflags &= ~(EFLG_CF|EFLG_AF);
   1.142          if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
   1.143          {
   1.144 @@ -1570,7 +1600,7 @@ x86_emulate(
   1.145  
   1.146      case 0x37: /* aaa */
   1.147      case 0x3f: /* aas */
   1.148 -        fail_if(mode_64bit());
   1.149 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.150          _regs.eflags &= ~EFLG_CF;
   1.151          if ( ((uint8_t)_regs.eax > 9) || (_regs.eflags & EFLG_AF) )
   1.152          {
   1.153 @@ -1610,6 +1640,36 @@ x86_emulate(
   1.154          register_address_increment(_regs.esp, dst.bytes);
   1.155          break;
   1.156  
   1.157 +    case 0x60: /* pusha */ {
   1.158 +        int i;
   1.159 +        unsigned long regs[] = {
   1.160 +            _regs.eax, _regs.ecx, _regs.edx, _regs.ebx,
   1.161 +            _regs.esp, _regs.ebp, _regs.esi, _regs.edi };
   1.162 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.163 +        for ( i = 0; i < 8; i++ )
   1.164 +            if ( (rc = ops->write(x86_seg_ss,
   1.165 +                                  truncate_ea(_regs.esp-(i+1)*op_bytes),
   1.166 +                                  regs[i], op_bytes, ctxt)) != 0 )
   1.167 +            goto done;
   1.168 +        register_address_increment(_regs.esp, -8*op_bytes);
   1.169 +        break;
   1.170 +    }
   1.171 +
   1.172 +    case 0x61: /* popa */ {
   1.173 +        int i;
   1.174 +        unsigned long dummy_esp, *regs[] = {
   1.175 +            &_regs.edi, &_regs.esi, &_regs.ebp, &dummy_esp,
   1.176 +            &_regs.ebx, &_regs.edx, &_regs.ecx, &_regs.eax };
   1.177 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.178 +        for ( i = 0; i < 8; i++ )
   1.179 +            if ( (rc = ops->read(x86_seg_ss,
   1.180 +                                 truncate_ea(_regs.esp+i*op_bytes),
   1.181 +                                 regs[i], op_bytes, ctxt)) != 0 )
   1.182 +            goto done;
   1.183 +        register_address_increment(_regs.esp, 8*op_bytes);
   1.184 +        break;
   1.185 +    }
   1.186 +
   1.187      case 0x68: /* push imm{16,32,64} */
   1.188          src.val = ((op_bytes == 2)
   1.189                     ? (int32_t)insn_fetch_type(int16_t)
   1.190 @@ -1752,7 +1812,7 @@ x86_emulate(
   1.191      case 0xd4: /* aam */ {
   1.192          unsigned int base = insn_fetch_type(uint8_t);
   1.193          uint8_t al = _regs.eax;
   1.194 -        fail_if(mode_64bit());
   1.195 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.196          generate_exception_if(base == 0, EXC_DE);
   1.197          *(uint16_t *)&_regs.eax = ((al / base) << 8) | (al % base);
   1.198          _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
   1.199 @@ -1765,7 +1825,7 @@ x86_emulate(
   1.200      case 0xd5: /* aad */ {
   1.201          unsigned int base = insn_fetch_type(uint8_t);
   1.202          uint16_t ax = _regs.eax;
   1.203 -        fail_if(mode_64bit());
   1.204 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.205          *(uint16_t *)&_regs.eax = (uint8_t)(ax + ((ax >> 8) * base));
   1.206          _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF);
   1.207          _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0;
   1.208 @@ -1775,7 +1835,7 @@ x86_emulate(
   1.209      }
   1.210  
   1.211      case 0xd6: /* salc */
   1.212 -        fail_if(mode_64bit());
   1.213 +        generate_exception_if(mode_64bit(), EXC_UD);
   1.214          *(uint8_t *)&_regs.eax = (_regs.eflags & EFLG_CF) ? 0xff : 0x00;
   1.215          break;
   1.216