From patchwork Wed Oct 24 11:25:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rusty Russell X-Patchwork-Id: 1637721 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id F0CE5DF2AB for ; Wed, 24 Oct 2012 11:31:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758441Ab2JXLbe (ORCPT ); Wed, 24 Oct 2012 07:31:34 -0400 Received: from ozlabs.org ([203.10.76.45]:50350 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758263Ab2JXL34 (ORCPT ); Wed, 24 Oct 2012 07:29:56 -0400 Received: by ozlabs.org (Postfix, from userid 1011) id ABD552C0199; Wed, 24 Oct 2012 22:29:54 +1100 (EST) From: Rusty Russell To: Will Deacon Cc: Christoffer Dall , "kvm@vger.kernel.org" , dave.martin@linaro.org, Rusty Russell Subject: [PATCH 01/10] kvm: split out instruction structure from decoding method. Date: Wed, 24 Oct 2012 21:55:14 +1030 Message-Id: <1351077923-17977-2-git-send-email-rusty@rustcorp.com.au> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1351077923-17977-1-git-send-email-rusty@rustcorp.com.au> References: <20121022174555.GD26619@mudshark.cambridge.arm.com> <1351077923-17977-1-git-send-email-rusty@rustcorp.com.au> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org From: Rusty Russell 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 --- 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;