From: Rusty Russell <rusty.russ...@linaro.org>

Add a new 'struct arm_insn' to represent the decoded instruction; the
decoding logic belong in a separate structure (arm_decode).

Signed-off-by: Rusty Russell <rusty.russ...@linaro.org>
---
 arch/arm/kvm/emulate.c |  120 +++++++++++++++++++++++++++---------------------
 1 file changed, 68 insertions(+), 52 deletions(-)

diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index 30124cb..e4fc12b 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -288,34 +288,37 @@ out:
 /******************************************************************************
  * Load-Store instruction emulation
  *****************************************************************************/
+enum SRType {
+       SRType_LSL,
+       SRType_LSR,
+       SRType_ASR,
+       SRType_ROR,
+       SRType_RRX
+};
 
-struct arm_instr {
-       /* Instruction decoding */
-       u32 opc;
-       u32 opc_mask;
-
+struct arm_insn {
        /* Decoding for the register write back */
        bool register_form;
        u32 imm;
-       u8 Rm;
        u8 type;
+       u8 Rt, Rn, Rm;
        u8 shift_n;
 
        /* Common decoding */
        u8 len;
        bool sign_extend;
        bool w;
+};
+
+struct arm_decode {
+       /* Instruction decoding */
+       u32 opc;
+       u32 opc_mask;
 
        bool (*decode)(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
-                      unsigned long instr, struct arm_instr *ai);
-};
+                      unsigned long instr, struct arm_insn *ai);
 
-enum SRType {
-       SRType_LSL,
-       SRType_LSR,
-       SRType_ASR,
-       SRType_ROR,
-       SRType_RRX
+       struct arm_insn template;
 };
 
 /* Modelled after DecodeImmShift() in the ARM ARM */
@@ -383,7 +386,7 @@ u32 shift(u32 value, u8 N, enum SRType type, u8 amount, 
bool carry_in)
 }
 
 static bool decode_arm_wb(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
-                         unsigned long instr, const struct arm_instr *ai)
+                         unsigned long instr, const struct arm_insn *ai)
 {
        u8 Rt = (instr >> 12) & 0xf;
        u8 Rn = (instr >> 16) & 0xf;
@@ -431,7 +434,7 @@ static bool decode_arm_wb(struct kvm_vcpu *vcpu, struct 
kvm_exit_mmio *mmio,
 }
 
 static bool decode_arm_ls(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
-                         unsigned long instr, struct arm_instr *ai)
+                         unsigned long instr, struct arm_insn *ai)
 {
        u8 A = (instr >> 25) & 1;
 
@@ -449,7 +452,7 @@ static bool decode_arm_ls(struct kvm_vcpu *vcpu, struct 
kvm_exit_mmio *mmio,
 }
 
 static bool decode_arm_extra(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio,
-                            unsigned long instr, struct arm_instr *ai)
+                            unsigned long instr, struct arm_insn *ai)
 {
        mmio->is_write = ai->w;
        mmio->len = ai->len;
@@ -476,56 +479,69 @@ static bool decode_arm_extra(struct kvm_vcpu *vcpu, 
struct kvm_exit_mmio *mmio,
  * loads and stores as their encodings mandate the W bit set and the P bit
  * clear.
  */
-static const struct arm_instr arm_instr[] = {
+static const struct arm_decode arm_decode[] = {
        /**************** Load/Store Word and Byte **********************/
        /* Store word with writeback */
-       { .opc = 0x04000000, .opc_mask = 0x0c500000, .len = 4, .w = true,
-               .sign_extend = false, .decode = decode_arm_ls },
+       { .opc = 0x04000000, .opc_mask = 0x0c500000,
+         .decode = decode_arm_ls,
+         .template =  { .len = 4, .w = true, .sign_extend = false, }, },
        /* Store byte with writeback */
-       { .opc = 0x04400000, .opc_mask = 0x0c500000, .len = 1, .w = true,
-               .sign_extend = false, .decode = decode_arm_ls },
+       { .opc = 0x04400000, .opc_mask = 0x0c500000,
+         .decode = decode_arm_ls,
+         .template = {  .len = 1, .w = true, .sign_extend = false, }, },
        /* Load word with writeback */
-       { .opc = 0x04100000, .opc_mask = 0x0c500000, .len = 4, .w = false,
-               .sign_extend = false, .decode = decode_arm_ls },
+       { .opc = 0x04100000, .opc_mask = 0x0c500000,
+         .decode = decode_arm_ls,
+         .template = {  .len = 4, .w = false, .sign_extend = false, }, },
        /* Load byte with writeback */
-       { .opc = 0x04500000, .opc_mask = 0x0c500000, .len = 1, .w = false,
-               .sign_extend = false, .decode = decode_arm_ls },
+       { .opc = 0x04500000, .opc_mask = 0x0c500000,
+         .decode = decode_arm_ls,
+         .template = { .len = 1, .w = false, .sign_extend = false, }, },
 
        /*************** Extra load/store instructions ******************/
 
        /* Store halfword with writeback */
-       { .opc = 0x000000b0, .opc_mask = 0x0c1000f0, .len = 2, .w = true,
-               .sign_extend = false, .decode = decode_arm_extra },
+       { .opc = 0x000000b0, .opc_mask = 0x0c1000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 2, .w = true, .sign_extend = false, }, },
        /* Load halfword with writeback */
-       { .opc = 0x001000b0, .opc_mask = 0x0c1000f0, .len = 2, .w = false,
-               .sign_extend = false, .decode = decode_arm_extra },
-
+       { .opc = 0x001000b0, .opc_mask = 0x0c1000f0, 
+         .decode = decode_arm_extra,
+         .template = { .len = 2, .w = false, .sign_extend = false, }, },
        /* Load dual with writeback */
-       { .opc = 0x000000d0, .opc_mask = 0x0c1000f0, .len = 8, .w = false,
-               .sign_extend = false, .decode = decode_arm_extra },
+       { .opc = 0x000000d0, .opc_mask = 0x0c1000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 8, .w = false, .sign_extend = false, }, },
        /* Load signed byte with writeback */
-       { .opc = 0x001000d0, .opc_mask = 0x0c1000f0, .len = 1, .w = false,
-               .sign_extend = true,  .decode = decode_arm_extra },
+       { .opc = 0x001000d0, .opc_mask = 0x0c1000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 1, .w = false, .sign_extend = true, }, },
 
        /* Store dual with writeback */
-       { .opc = 0x000000f0, .opc_mask = 0x0c1000f0, .len = 8, .w = true,
-               .sign_extend = false, .decode = decode_arm_extra },
+       { .opc = 0x000000f0, .opc_mask = 0x0c1000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 8, .w = true, .sign_extend = false, }, },
        /* Load signed halfword with writeback */
-       { .opc = 0x001000f0, .opc_mask = 0x0c1000f0, .len = 2, .w = false,
-               .sign_extend = true,  .decode = decode_arm_extra },
+       { .opc = 0x001000f0, .opc_mask = 0x0c1000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 2, .w = false, .sign_extend = true, }, },
 
        /* Store halfword unprivileged */
-       { .opc = 0x002000b0, .opc_mask = 0x0f3000f0, .len = 2, .w = true,
-               .sign_extend = false, .decode = decode_arm_extra },
+       { .opc = 0x002000b0, .opc_mask = 0x0f3000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 2, .w = true, .sign_extend = false, }, },
        /* Load halfword unprivileged */
-       { .opc = 0x003000b0, .opc_mask = 0x0f3000f0, .len = 2, .w = false,
-               .sign_extend = false, .decode = decode_arm_extra },
+       { .opc = 0x003000b0, .opc_mask = 0x0f3000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 2, .w = false, .sign_extend = false, }, },
        /* Load signed byte unprivileged */
-       { .opc = 0x003000d0, .opc_mask = 0x0f3000f0, .len = 1, .w = false,
-               .sign_extend = true , .decode = decode_arm_extra },
+       { .opc = 0x003000d0, .opc_mask = 0x0f3000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 1, .w = false, .sign_extend = true, }, },
        /* Load signed halfword unprivileged */
-       { .opc = 0x003000d0, .opc_mask = 0x0f3000f0, .len = 2, .w = false,
-               .sign_extend = true , .decode = decode_arm_extra },
+       { .opc = 0x003000d0, .opc_mask = 0x0f3000f0,
+         .decode = decode_arm_extra,
+         .template = { .len = 2, .w = false, .sign_extend = true, }, },
 };
 
 static bool kvm_decode_arm_ls(struct kvm_vcpu *vcpu, unsigned long instr,
@@ -533,11 +549,11 @@ static bool kvm_decode_arm_ls(struct kvm_vcpu *vcpu, 
unsigned long instr,
 {
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(arm_instr); i++) {
-               const struct arm_instr *ai = &arm_instr[i];
-               if ((instr & ai->opc_mask) == ai->opc) {
-                       struct arm_instr ai_copy = *ai;
-                       return ai->decode(vcpu, mmio, instr, &ai_copy);
+       for (i = 0; i < ARRAY_SIZE(arm_decode); i++) {
+               const struct arm_decode *d = &arm_decode[i];
+               if ((instr & d->opc_mask) == d->opc) {
+                       struct arm_insn ai = d->template;
+                       return d->decode(vcpu, mmio, instr, &ai);
                }
        }
        return false;
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to