[HVM][MMIO] Emulate more instructions: or/and/xor with byte width,
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 7 Jun 2006 13:20:29 +0000 (14:20 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 7 Jun 2006 13:20:29 +0000 (14:20 +0100)
and load string (LODS) instructions.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Signed-off-by: Yunfeng zhao <yunfeng.zhao@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
xen/arch/x86/hvm/io.c
xen/arch/x86/hvm/platform.c
xen/include/asm-x86/hvm/io.h

index 18bd59ebfd037d179c74ab6259e4a96faf2081e7..95253fa97637452629c4494826efe9e1de238903 100644 (file)
@@ -507,6 +507,13 @@ static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs,
             regs->ecx -= p->count;
         break;
 
+    case INSTR_LODS:
+        sign = p->df ? -1 : 1;
+        regs->esi += sign * p->count * p->size;
+        if (mmio_opp->flags & REPZ)
+            regs->ecx -= p->count;
+        break;
+
     case INSTR_AND:
         if (src & REGISTER) {
             index = operand_index(src);
index 20779414fac3f5e69d1f4ff755e972a8d3b34f87..15d5a44e73bca621629e7c769d520ef987489eec 100644 (file)
@@ -364,6 +364,12 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
     }
 
     switch (*opcode) {
+    case 0x0A: /* or r8, m8 */
+        instr->instr = INSTR_OR;
+        instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return mem_reg(size_reg, opcode, instr, rex);
+
     case 0x0B: /* or m32/16, r32/16 */
         instr->instr = INSTR_OR;
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
@@ -380,6 +386,12 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
         return reg_mem(instr->op_size, opcode, instr, rex);
 
+    case 0x22: /* and m8, r8 */
+        instr->instr = INSTR_AND;
+        instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return mem_reg(size_reg, opcode, instr, rex);
+
     case 0x23: /* and m32/16, r32/16 */
         instr->instr = INSTR_AND;
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
@@ -396,6 +408,12 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
         return reg_mem(instr->op_size, opcode, instr, rex);
 
+    case 0x32: /* xor m8, r8*/
+        instr->instr = INSTR_XOR;
+        instr->op_size = BYTE;
+        GET_OP_SIZE_FOR_BYTE(size_reg);
+        return mem_reg(size_reg, opcode, instr, rex);
+
     case 0x39: /* cmp r32/16, m32/16 */
         instr->instr = INSTR_CMP;
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
@@ -516,6 +534,16 @@ static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *i
         GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
         return DECODE_success;
 
+    case 0xAC: /* lodsb */
+        instr->instr = INSTR_LODS;
+        instr->op_size = BYTE;
+        return DECODE_success;
+
+    case 0xAD: /* lodsw/lodsl */
+        instr->instr = INSTR_LODS;
+        GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
+        return DECODE_success;
+
     case 0xC6:
         if (((opcode[1] >> 3) & 7) == 0) { /* mov $imm8, m8 */
             instr->instr = INSTR_MOV;
@@ -906,6 +934,17 @@ void handle_mmio(unsigned long va, unsigned long gpa)
                       GET_REPEAT_COUNT(), mmio_inst.op_size, regs->eax, IOREQ_WRITE, 0);
         break;
 
+    case INSTR_LODS:
+        /*
+         * Since the source is always in (contiguous) mmio space we don't
+         * need to break it up into pages.
+         */
+        mmio_opp->flags = mmio_inst.flags;
+        mmio_opp->instr = mmio_inst.instr;
+        send_mmio_req(IOREQ_TYPE_COPY, gpa,
+                      GET_REPEAT_COUNT(), mmio_inst.op_size, 0, IOREQ_READ, 0);
+        break;
+
     case INSTR_OR:
         mmio_operands(IOREQ_TYPE_OR, gpa, &mmio_inst, mmio_opp, regs);
         break;
@@ -954,26 +993,26 @@ void handle_mmio(unsigned long va, unsigned long gpa)
         mmio_opp->instr = mmio_inst.instr;
         mmio_opp->operand[0] = mmio_inst.operand[0]; /* source */
         mmio_opp->operand[1] = mmio_inst.operand[1]; /* destination */
-       if (mmio_inst.operand[0] & REGISTER) {
-               long value;
-               unsigned long operand = mmio_inst.operand[0];
-               value = get_reg_value(operand_size(operand), 
-                                     operand_index(operand), 0,
-                                     mmio_opp->inst_decoder_regs);
-               /* send the request and wait for the value */
-               send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
-                      mmio_inst.op_size, value, IOREQ_WRITE, 0);
-       } else {
-               /* the destination is a register */
-               long value;
-               unsigned long operand = mmio_inst.operand[1];
-               value = get_reg_value(operand_size(operand), 
-                                     operand_index(operand), 0,
-                                     mmio_opp->inst_decoder_regs);
-               /* send the request and wait for the value */
-               send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
-                      mmio_inst.op_size, value, IOREQ_WRITE, 0);
-       }
+        if ( mmio_inst.operand[0] & REGISTER ) {
+            long value;
+            unsigned long operand = mmio_inst.operand[0];
+            value = get_reg_value(operand_size(operand),
+                                  operand_index(operand), 0,
+                                  mmio_opp->inst_decoder_regs);
+            /* send the request and wait for the value */
+            send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
+                          mmio_inst.op_size, value, IOREQ_WRITE, 0);
+        } else {
+            /* the destination is a register */
+            long value;
+            unsigned long operand = mmio_inst.operand[1];
+            value = get_reg_value(operand_size(operand),
+                                  operand_index(operand), 0,
+                                  mmio_opp->inst_decoder_regs);
+            /* send the request and wait for the value */
+            send_mmio_req(IOREQ_TYPE_XCHG, gpa, 1,
+                          mmio_inst.op_size, value, IOREQ_WRITE, 0);
+        }
         break;
 
     default:
index 0d4b36b0ad25b99c5f6d3f1d791b2b668364acb9..c07470394ff18679d0d4ee95dfbcaaf1d63b2a60 100644 (file)
 #define INSTR_MOVZX 8
 #define INSTR_MOVSX 9
 #define INSTR_STOS  10
-#define INSTR_TEST  11
-#define INSTR_BT    12
-#define INSTR_XCHG  13
+#define INSTR_LODS  11
+#define INSTR_TEST  12
+#define INSTR_BT    13
+#define INSTR_XCHG  14
 
 struct instruction {
     __s8    instr;        /* instruction type */