From patchwork Tue Jul 5 13:40:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antoine Tremblay X-Patchwork-Id: 13645 Received: (qmail 64635 invoked by alias); 5 Jul 2016 13:41:31 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 64529 invoked by uid 89); 5 Jul 2016 13:41:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 spammy= X-HELO: usplmg21.ericsson.net Received: from usplmg21.ericsson.net (HELO usplmg21.ericsson.net) (198.24.6.65) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 05 Jul 2016 13:41:19 +0000 Received: from EUSAAHC008.ericsson.se (Unknown_Domain [147.117.188.96]) by usplmg21.ericsson.net (Symantec Mail Security) with SMTP id C9.66.03614.FA8BB775; Tue, 5 Jul 2016 15:40:00 +0200 (CEST) Received: from elxa4wqvvz1.dyn.mo.ca.am.ericsson.se (147.117.188.8) by smtps-am.internal.ericsson.com (147.117.188.96) with Microsoft SMTP Server (TLS) id 14.3.294.0; Tue, 5 Jul 2016 09:40:52 -0400 From: Antoine Tremblay To: CC: Simon Marchi Subject: [PATCH v3 08/18] Move Thumb 32 bits instruction decode functions to arch/arm-insn-reloc.c Date: Tue, 5 Jul 2016 09:40:20 -0400 Message-ID: <1467726030-13020-9-git-send-email-antoine.tremblay@ericsson.com> In-Reply-To: <1467726030-13020-1-git-send-email-antoine.tremblay@ericsson.com> References: <1467726030-13020-1-git-send-email-antoine.tremblay@ericsson.com> MIME-Version: 1.0 X-IsSubscribed: yes From: Simon Marchi This patch does the same as the previous one, but for 32-bits Thumb instructions-related functions. gdb/ChangeLog: * arch/arm-insn-reloc.h (struct thumb_32bit_insn_reloc_visitor): Move from arm-tdep.c. (thumb_32bit_relocate_insn): New declaration. * arch/arm-insn-reloc.c (thumb2_decode_dp_shift_reg): Move from arm-tdep.c. (thumb2_decode_ext_reg_ld_st): Likewise. (thumb2_decode_svc_copro): Likewise. (decode_thumb_32bit_ld_mem_hints): Likewise. (thumb_32bit_relocate_insn): Likewise. * arm-tdep.c (struct thumb_32bit_insn_reloc_visitor): Move to arch/arm-insn-reloc.h. (thumb2_decode_dp_shift_reg): Move to arch/arm-insn-reloc.c. (thumb2_decode_ext_reg_ld_st): Likewise. (thumb2_decode_svc_copro): Likewise. (decode_thumb_32bit_ld_mem_hints): Likewise. (thumb_32bit_relocate_insn): Likewise. --- gdb/arch/arm-insn-reloc.c | 274 +++++++++++++++++++++++++++++++++++++++++ gdb/arch/arm-insn-reloc.h | 32 +++++ gdb/arm-tdep.c | 301 ---------------------------------------------- 3 files changed, 306 insertions(+), 301 deletions(-) diff --git a/gdb/arch/arm-insn-reloc.c b/gdb/arch/arm-insn-reloc.c index adf6243..f598c64 100644 --- a/gdb/arch/arm-insn-reloc.c +++ b/gdb/arch/arm-insn-reloc.c @@ -470,3 +470,277 @@ arm_relocate_insn (uint32_t insn, struct arm_insn_reloc_visitor *visitor, return err; } + +/* Decode shifted register instructions. */ + +static int +thumb2_decode_dp_shift_reg (uint16_t insn1, uint16_t insn2, + struct thumb_32bit_insn_reloc_visitor *visitor, + struct arm_insn_reloc_data *data) +{ + /* PC is only allowed to be used in instruction MOV. */ + + unsigned int op = bits (insn1, 5, 8); + unsigned int rn = bits (insn1, 0, 3); + + if (op == 0x2 && rn == 0xf) /* MOV */ + return visitor->alu_imm (insn1, insn2, data); + else + return visitor->others (insn1, insn2, "dp (shift reg)", data); +} + + +/* Decode extension register load/store. Exactly the same as + arm_decode_ext_reg_ld_st. */ + +static int +thumb2_decode_ext_reg_ld_st (uint16_t insn1, uint16_t insn2, + struct thumb_32bit_insn_reloc_visitor *visitor, + struct arm_insn_reloc_data *data) +{ + unsigned int opcode = bits (insn1, 4, 8); + + switch (opcode) + { + case 0x04: case 0x05: + return visitor->others (insn1, insn2, "vfp/neon vmov", data); + + case 0x08: case 0x0c: /* 01x00 */ + case 0x0a: case 0x0e: /* 01x10 */ + case 0x12: case 0x16: /* 10x10 */ + return visitor->others (insn1, insn2, "vfp/neon vstm/vpush", data); + + case 0x09: case 0x0d: /* 01x01 */ + case 0x0b: case 0x0f: /* 01x11 */ + case 0x13: case 0x17: /* 10x11 */ + return visitor->others (insn1, insn2, "vfp/neon vldm/vpop", data); + + case 0x10: case 0x14: case 0x18: case 0x1c: /* vstr. */ + return visitor->others (insn1, insn2, "vstr", data); + case 0x11: case 0x15: case 0x19: case 0x1d: /* vldr. */ + return visitor->copro_load_store (insn1, insn2, data); + } + + /* Should be unreachable. */ + return 1; +} + + +static int +decode_thumb_32bit_ld_mem_hints (uint16_t insn1, uint16_t insn2, + struct thumb_32bit_insn_reloc_visitor *visitor, + struct arm_insn_reloc_data *data) +{ + int rt = bits (insn2, 12, 15); + int rn = bits (insn1, 0, 3); + int op1 = bits (insn1, 7, 8); + + switch (bits (insn1, 5, 6)) + { + case 0: /* Load byte and memory hints */ + if (rt == 0xf) /* PLD/PLI */ + { + if (rn == 0xf) + /* PLD literal or Encoding T3 of PLI(immediate, literal). */ + return visitor->preload (insn1, insn2, data); + else + return visitor->others (insn1, insn2, "pli/pld", data); + } + else + { + if (rn == 0xf) /* LDRB/LDRSB (literal) */ + return visitor->load_literal (insn1, insn2, data, 1); + else + return visitor->others (insn1, insn2, "ldrb{reg, immediate}/ldrbt", + data); + } + + break; + case 1: /* Load halfword and memory hints. */ + if (rt == 0xf) /* PLD{W} and Unalloc memory hint. */ + return visitor->others (insn1, insn2, "pld/unalloc memhint", data); + else + { + if (rn == 0xf) + return visitor->load_literal (insn1, insn2, data, 2); + else + return visitor->others (insn1, insn2, "ldrh/ldrht", data); + } + break; + case 2: /* Load word */ + { + int insn2_bit_8_11 = bits (insn2, 8, 11); + + if (rn == 0xf) + return visitor->load_literal (insn1, insn2, data, 4); + else if (op1 == 0x1) /* Encoding T3 */ + return visitor->load_reg_imm (insn1, insn2, data, 0, 1); + else /* op1 == 0x0 */ + { + if (insn2_bit_8_11 == 0xc || (insn2_bit_8_11 & 0x9) == 0x9) + /* LDR (immediate) */ + return visitor->load_reg_imm (insn1, insn2, data, + bit (insn2, 8), 1); + else if (insn2_bit_8_11 == 0xe) /* LDRT */ + return visitor->others (insn1, insn2, "ldrt", data); + else + /* LDR (register) */ + return visitor->load_reg_imm (insn1, insn2, data, 0, 0); + } + break; + } + default: + return visitor->undef (insn1, insn2, data); + } + return 0; +} + +static int +thumb2_decode_svc_copro (uint16_t insn1, uint16_t insn2, + struct thumb_32bit_insn_reloc_visitor *visitor, + struct arm_insn_reloc_data *data) +{ + unsigned int coproc = bits (insn2, 8, 11); + unsigned int bit_5_8 = bits (insn1, 5, 8); + unsigned int bit_9 = bit (insn1, 9); + unsigned int bit_4 = bit (insn1, 4); + + if (bit_9 == 0) + { + if (bit_5_8 == 2) + return visitor->others (insn1, insn2, + "neon 64bit xfer/mrrc/mrrc2/mcrr/mcrr2", data); + else if (bit_5_8 == 0) /* UNDEFINED. */ + return visitor->undef (insn1, insn2, data); + else + { + /*coproc is 101x. SIMD/VFP, ext registers load/store. */ + if ((coproc & 0xe) == 0xa) + return thumb2_decode_ext_reg_ld_st (insn1, insn2, visitor, data); + else /* coproc is not 101x. */ + { + if (bit_4 == 0) /* STC/STC2. */ + return visitor->others (insn1, insn2, "stc/stc2", data); + else /* LDC/LDC2 {literal, immeidate}. */ + return visitor->copro_load_store (insn1, insn2, data); + } + } + } + else + return visitor->others (insn1, insn2, "coproc", data); + + return 0; +} + +int +thumb_32bit_relocate_insn (uint16_t insn1, uint16_t insn2, + struct thumb_32bit_insn_reloc_visitor *visitor, + struct arm_insn_reloc_data *data) +{ + int err = 0; + unsigned short op = bit (insn2, 15); + unsigned int op1 = bits (insn1, 11, 12); + + switch (op1) + { + case 1: + { + switch (bits (insn1, 9, 10)) + { + case 0: + if (bit (insn1, 6)) + { + /* Load/store {dual, execlusive}, table branch. */ + if (bits (insn1, 7, 8) == 1 && bits (insn1, 4, 5) == 1 + && bits (insn2, 5, 7) == 0) + err = visitor->table_branch (insn1, insn2, data); + else + /* PC is not allowed to use in load/store {dual, exclusive} + instructions. */ + err = visitor->others (insn1, insn2, "load/store dual/ex", + data); + } + else /* load/store multiple */ + { + switch (bits (insn1, 7, 8)) + { + case 0: case 3: /* SRS, RFE */ + err = visitor->others (insn1, insn2, "srs/rfe", data); + break; + case 1: case 2: /* LDM/STM/PUSH/POP */ + err = visitor->block_xfer (insn1, insn2, data); + break; + } + } + break; + + case 1: + /* Data-processing (shift register). */ + err = thumb2_decode_dp_shift_reg (insn1, insn2, visitor, data); + break; + default: /* Coprocessor instructions. */ + err = thumb2_decode_svc_copro (insn1, insn2, visitor, data); + break; + } + break; + } + case 2: /* op1 = 2 */ + if (op) /* Branch and misc control. */ + { + if (bit (insn2, 14) /* BLX/BL */ + || bit (insn2, 12) /* Unconditional branch */ + || (bits (insn1, 7, 9) != 0x7)) /* Conditional branch */ + err = visitor->b_bl_blx (insn1, insn2, data); + else + err = visitor->others (insn1, insn2, "misc ctrl", data); + } + else + { + if (bit (insn1, 9)) /* Data processing (plain binary imm). */ + { + int op = bits (insn1, 4, 8); + int rn = bits (insn1, 0, 3); + if ((op == 0 || op == 0xa) && rn == 0xf) + err = visitor->pc_relative_32bit (insn1, insn2, data); + else + err = visitor->others (insn1, insn2, "dp/pb", data); + } + else /* Data processing (modified immeidate) */ + err = visitor->others (insn1, insn2, "dp/mi", data); + } + break; + case 3: /* op1 = 3 */ + switch (bits (insn1, 9, 10)) + { + case 0: + if (bit (insn1, 4)) + err = decode_thumb_32bit_ld_mem_hints (insn1, insn2, visitor, data); + else /* NEON Load/Store and Store single data item */ + err = visitor->others (insn1, insn2, "neon elt/struct load/store", + data); + break; + case 1: /* op1 = 3, bits (9, 10) == 1 */ + switch (bits (insn1, 7, 8)) + { + case 0: case 1: /* Data processing (register) */ + err = visitor->others (insn1, insn2, "dp(reg)", data); + break; + case 2: /* Multiply and absolute difference */ + err = visitor->others (insn1, insn2, "mul/mua/diff", data); + break; + case 3: /* Long multiply and divide */ + err = visitor->others (insn1, insn2, "lmul/lmua", data); + break; + } + break; + default: /* Coprocessor instructions */ + err = thumb2_decode_svc_copro (insn1, insn2, visitor, data); + break; + } + break; + default: + err = 1; + } + + return err; +} diff --git a/gdb/arch/arm-insn-reloc.h b/gdb/arch/arm-insn-reloc.h index 18d3916..ebfc89a 100644 --- a/gdb/arch/arm-insn-reloc.h +++ b/gdb/arch/arm-insn-reloc.h @@ -42,8 +42,40 @@ struct arm_insn_reloc_visitor int (*unpred) (uint32_t insn, struct arm_insn_reloc_data *data); }; +struct thumb_32bit_insn_reloc_visitor +{ + int (*alu_imm) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*b_bl_blx) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*block_xfer) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*copro_load_store) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*load_literal) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data, int size); + int (*load_reg_imm) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data, int writeback, + int immed); + int (*others) (uint16_t insn1, uint16_t insn2, const char *iname, + struct arm_insn_reloc_data *data); + int (*pc_relative_32bit) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*preload) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*undef) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); + int (*table_branch) (uint16_t insn1, uint16_t insn2, + struct arm_insn_reloc_data *data); +}; + extern int arm_relocate_insn (uint32_t insn, struct arm_insn_reloc_visitor *visitor, struct arm_insn_reloc_data *data); +extern int thumb_32bit_relocate_insn ( + uint16_t insn1, uint16_t insn2, + struct thumb_32bit_insn_reloc_visitor *visitor, + struct arm_insn_reloc_data *data); + #endif /* ARM_INSN_RELOC_H */ diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 1af4d36..4f4b6b2 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -4481,33 +4481,6 @@ struct arm_insn_reloc_data struct regcache *regs; }; -struct thumb_32bit_insn_reloc_visitor -{ - int (*alu_imm) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*b_bl_blx) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*block_xfer) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*copro_load_store) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*load_literal) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data, int size); - int (*load_reg_imm) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data, int writeback, - int immed); - int (*others) (uint16_t insn1, uint16_t insn2, const char *iname, - struct arm_insn_reloc_data *data); - int (*pc_relative_32bit) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*preload) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*undef) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); - int (*table_branch) (uint16_t insn1, uint16_t insn2, - struct arm_insn_reloc_data *data); -}; - struct thumb_16bit_insn_reloc_visitor { int (*alu_reg) (uint16_t insn, struct arm_insn_reloc_data *data); @@ -6504,97 +6477,6 @@ arm_copy_unpred (uint32_t insn, struct arm_insn_reloc_data *data) /* The decode_* functions are instruction decoding helpers. They mostly follow the presentation in the ARM ARM. */ -/* Decode shifted register instructions. */ - -static int -thumb2_decode_dp_shift_reg (uint16_t insn1, uint16_t insn2, - struct thumb_32bit_insn_reloc_visitor *visitor, - struct arm_insn_reloc_data *data) -{ - /* PC is only allowed to be used in instruction MOV. */ - - unsigned int op = bits (insn1, 5, 8); - unsigned int rn = bits (insn1, 0, 3); - - if (op == 0x2 && rn == 0xf) /* MOV */ - return visitor->alu_imm (insn1, insn2, data); - else - return visitor->others (insn1, insn2, "dp (shift reg)", data); -} - - -/* Decode extension register load/store. Exactly the same as - arm_decode_ext_reg_ld_st. */ - -static int -thumb2_decode_ext_reg_ld_st (uint16_t insn1, uint16_t insn2, - struct thumb_32bit_insn_reloc_visitor *visitor, - struct arm_insn_reloc_data *data) -{ - unsigned int opcode = bits (insn1, 4, 8); - - switch (opcode) - { - case 0x04: case 0x05: - return visitor->others (insn1, insn2, "vfp/neon vmov", data); - - case 0x08: case 0x0c: /* 01x00 */ - case 0x0a: case 0x0e: /* 01x10 */ - case 0x12: case 0x16: /* 10x10 */ - return visitor->others (insn1, insn2, "vfp/neon vstm/vpush", data); - - case 0x09: case 0x0d: /* 01x01 */ - case 0x0b: case 0x0f: /* 01x11 */ - case 0x13: case 0x17: /* 10x11 */ - return visitor->others (insn1, insn2, "vfp/neon vldm/vpop", data); - - case 0x10: case 0x14: case 0x18: case 0x1c: /* vstr. */ - return visitor->others (insn1, insn2, "vstr", data); - case 0x11: case 0x15: case 0x19: case 0x1d: /* vldr. */ - return visitor->copro_load_store (insn1, insn2, data); - } - - /* Should be unreachable. */ - return 1; -} - -static int -thumb2_decode_svc_copro (uint16_t insn1, uint16_t insn2, - struct thumb_32bit_insn_reloc_visitor *visitor, - struct arm_insn_reloc_data *data) -{ - unsigned int coproc = bits (insn2, 8, 11); - unsigned int bit_5_8 = bits (insn1, 5, 8); - unsigned int bit_9 = bit (insn1, 9); - unsigned int bit_4 = bit (insn1, 4); - - if (bit_9 == 0) - { - if (bit_5_8 == 2) - return visitor->others (insn1, insn2, - "neon 64bit xfer/mrrc/mrrc2/mcrr/mcrr2", data); - else if (bit_5_8 == 0) /* UNDEFINED. */ - return visitor->undef (insn1, insn2, data); - else - { - /*coproc is 101x. SIMD/VFP, ext registers load/store. */ - if ((coproc & 0xe) == 0xa) - return thumb2_decode_ext_reg_ld_st (insn1, insn2, visitor, data); - else /* coproc is not 101x. */ - { - if (bit_4 == 0) /* STC/STC2. */ - return visitor->others (insn1, insn2, "stc/stc2", data); - else /* LDC/LDC2 {literal, immeidate}. */ - return visitor->copro_load_store (insn1, insn2, data); - } - } - } - else - return visitor->others (insn1, insn2, "coproc", data); - - return 0; -} - static void install_pc_relative (struct arm_insn_reloc_data *data, int rd) { @@ -6996,189 +6878,6 @@ thumb_16bit_relocate_insn (uint16_t insn1, return err; } -static int -decode_thumb_32bit_ld_mem_hints (uint16_t insn1, uint16_t insn2, - struct thumb_32bit_insn_reloc_visitor *visitor, - struct arm_insn_reloc_data *data) -{ - int rt = bits (insn2, 12, 15); - int rn = bits (insn1, 0, 3); - int op1 = bits (insn1, 7, 8); - - switch (bits (insn1, 5, 6)) - { - case 0: /* Load byte and memory hints */ - if (rt == 0xf) /* PLD/PLI */ - { - if (rn == 0xf) - /* PLD literal or Encoding T3 of PLI(immediate, literal). */ - return visitor->preload (insn1, insn2, data); - else - return visitor->others (insn1, insn2, "pli/pld", data); - } - else - { - if (rn == 0xf) /* LDRB/LDRSB (literal) */ - return visitor->load_literal (insn1, insn2, data, 1); - else - return visitor->others (insn1, insn2, "ldrb{reg, immediate}/ldrbt", - data); - } - - break; - case 1: /* Load halfword and memory hints. */ - if (rt == 0xf) /* PLD{W} and Unalloc memory hint. */ - return visitor->others (insn1, insn2, "pld/unalloc memhint", data); - else - { - if (rn == 0xf) - return visitor->load_literal (insn1, insn2, data, 2); - else - return visitor->others (insn1, insn2, "ldrh/ldrht", data); - } - break; - case 2: /* Load word */ - { - int insn2_bit_8_11 = bits (insn2, 8, 11); - - if (rn == 0xf) - return visitor->load_literal (insn1, insn2, data, 4); - else if (op1 == 0x1) /* Encoding T3 */ - return visitor->load_reg_imm (insn1, insn2, data, 0, 1); - else /* op1 == 0x0 */ - { - if (insn2_bit_8_11 == 0xc || (insn2_bit_8_11 & 0x9) == 0x9) - /* LDR (immediate) */ - return visitor->load_reg_imm (insn1, insn2, data, - bit (insn2, 8), 1); - else if (insn2_bit_8_11 == 0xe) /* LDRT */ - return visitor->others (insn1, insn2, "ldrt", data); - else - /* LDR (register) */ - return visitor->load_reg_imm (insn1, insn2, data, 0, 0); - } - break; - } - default: - return visitor->undef (insn1, insn2, data); - } - return 0; -} - -static int -thumb_32bit_relocate_insn (uint16_t insn1, uint16_t insn2, - struct thumb_32bit_insn_reloc_visitor *visitor, - struct arm_insn_reloc_data *data) -{ - int err = 0; - unsigned short op = bit (insn2, 15); - unsigned int op1 = bits (insn1, 11, 12); - - switch (op1) - { - case 1: - { - switch (bits (insn1, 9, 10)) - { - case 0: - if (bit (insn1, 6)) - { - /* Load/store {dual, execlusive}, table branch. */ - if (bits (insn1, 7, 8) == 1 && bits (insn1, 4, 5) == 1 - && bits (insn2, 5, 7) == 0) - err = visitor->table_branch (insn1, insn2, data); - else - /* PC is not allowed to use in load/store {dual, exclusive} - instructions. */ - err = visitor->others (insn1, insn2, "load/store dual/ex", - data); - } - else /* load/store multiple */ - { - switch (bits (insn1, 7, 8)) - { - case 0: case 3: /* SRS, RFE */ - err = visitor->others (insn1, insn2, "srs/rfe", data); - break; - case 1: case 2: /* LDM/STM/PUSH/POP */ - err = visitor->block_xfer (insn1, insn2, data); - break; - } - } - break; - - case 1: - /* Data-processing (shift register). */ - err = thumb2_decode_dp_shift_reg (insn1, insn2, visitor, data); - break; - default: /* Coprocessor instructions. */ - err = thumb2_decode_svc_copro (insn1, insn2, visitor, data); - break; - } - break; - } - case 2: /* op1 = 2 */ - if (op) /* Branch and misc control. */ - { - if (bit (insn2, 14) /* BLX/BL */ - || bit (insn2, 12) /* Unconditional branch */ - || (bits (insn1, 7, 9) != 0x7)) /* Conditional branch */ - err = visitor->b_bl_blx (insn1, insn2, data); - else - err = visitor->others (insn1, insn2, "misc ctrl", data); - } - else - { - if (bit (insn1, 9)) /* Data processing (plain binary imm). */ - { - int op = bits (insn1, 4, 8); - int rn = bits (insn1, 0, 3); - if ((op == 0 || op == 0xa) && rn == 0xf) - err = visitor->pc_relative_32bit (insn1, insn2, data); - else - err = visitor->others (insn1, insn2, "dp/pb", data); - } - else /* Data processing (modified immeidate) */ - err = visitor->others (insn1, insn2, "dp/mi", data); - } - break; - case 3: /* op1 = 3 */ - switch (bits (insn1, 9, 10)) - { - case 0: - if (bit (insn1, 4)) - err = decode_thumb_32bit_ld_mem_hints (insn1, insn2, visitor, data); - else /* NEON Load/Store and Store single data item */ - err = visitor->others (insn1, insn2, "neon elt/struct load/store", - data); - break; - case 1: /* op1 = 3, bits (9, 10) == 1 */ - switch (bits (insn1, 7, 8)) - { - case 0: case 1: /* Data processing (register) */ - err = visitor->others (insn1, insn2, "dp(reg)", data); - break; - case 2: /* Multiply and absolute difference */ - err = visitor->others (insn1, insn2, "mul/mua/diff", data); - break; - case 3: /* Long multiply and divide */ - err = visitor->others (insn1, insn2, "lmul/lmua", data); - break; - } - break; - default: /* Coprocessor instructions */ - err = thumb2_decode_svc_copro (insn1, insn2, visitor, data); - break; - } - break; - default: - err = 1; - } - - return err; - -} - static struct arm_insn_reloc_visitor arm_insn_reloc_visitor = { arm_copy_alu_imm,