Add support for emulation of the "or r/m, imm8" instruction.
Submitted by: Zhixiang Yu (zxyu.core@gmail.com) Obtained from: GSoC 2013 (AHCI device emulation for bhyve)
This commit is contained in:
parent
f5ce18bd6e
commit
8a3e57621d
@ -60,6 +60,7 @@ enum {
|
||||
VIE_OP_TYPE_NONE = 0,
|
||||
VIE_OP_TYPE_MOV,
|
||||
VIE_OP_TYPE_AND,
|
||||
VIE_OP_TYPE_OR,
|
||||
VIE_OP_TYPE_LAST
|
||||
};
|
||||
|
||||
@ -94,7 +95,13 @@ static const struct vie_op one_byte_opcodes[256] = {
|
||||
.op_byte = 0x81,
|
||||
.op_type = VIE_OP_TYPE_AND,
|
||||
.op_flags = VIE_OP_F_IMM,
|
||||
}
|
||||
},
|
||||
[0x83] = {
|
||||
/* XXX Group 1 extended opcode - not just OR */
|
||||
.op_byte = 0x83,
|
||||
.op_type = VIE_OP_TYPE_OR,
|
||||
.op_flags = VIE_OP_F_IMM8,
|
||||
},
|
||||
};
|
||||
|
||||
/* struct vie.mod */
|
||||
@ -338,8 +345,8 @@ emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
|
||||
break;
|
||||
case 0x81:
|
||||
/*
|
||||
* AND reg (ModRM:reg) with immediate and store the
|
||||
* result in reg
|
||||
* AND mem (ModRM:r/m) with immediate and store the
|
||||
* result in mem.
|
||||
*
|
||||
* 81/ and r/m32, imm32
|
||||
* REX.W + 81/ and r/m64, imm32 sign-extended to 64
|
||||
@ -371,6 +378,52 @@ emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
emulate_or(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
|
||||
mem_region_read_t memread, mem_region_write_t memwrite, void *arg)
|
||||
{
|
||||
int error, size;
|
||||
uint64_t val1;
|
||||
|
||||
size = 4;
|
||||
error = EINVAL;
|
||||
|
||||
switch (vie->op.op_byte) {
|
||||
case 0x83:
|
||||
/*
|
||||
* OR mem (ModRM:r/m) with immediate and store the
|
||||
* result in mem.
|
||||
*
|
||||
* 83/ OR r/m32, imm8 sign-extended to 32
|
||||
* REX.W + 83/ OR r/m64, imm8 sign-extended to 64
|
||||
*
|
||||
* Currently, only the OR operation of the 0x83 opcode
|
||||
* is implemented (ModRM:reg = b001).
|
||||
*/
|
||||
if ((vie->reg & 7) != 1)
|
||||
break;
|
||||
|
||||
if (vie->rex_w)
|
||||
size = 8;
|
||||
|
||||
/* get the first operand */
|
||||
error = memread(vm, vcpuid, gpa, &val1, size, arg);
|
||||
if (error)
|
||||
break;
|
||||
|
||||
/*
|
||||
* perform the operation with the pre-fetched immediate
|
||||
* operand and write the result
|
||||
*/
|
||||
val1 |= vie->immediate;
|
||||
error = memwrite(vm, vcpuid, gpa, val1, size, arg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
|
||||
mem_region_read_t memread, mem_region_write_t memwrite,
|
||||
@ -390,6 +443,10 @@ vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie,
|
||||
error = emulate_and(vm, vcpuid, gpa, vie,
|
||||
memread, memwrite, memarg);
|
||||
break;
|
||||
case VIE_OP_TYPE_OR:
|
||||
error = emulate_or(vm, vcpuid, gpa, vie,
|
||||
memread, memwrite, memarg);
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user