/* Chrysalide - Outil d'analyse de fichiers binaires * arm.c - désassemblage des instructions ARMv7 * * Copyright (C) 2014 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * OpenIDA is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "arm.h" #include #include "opcodes/arm_opcodes.h" #include "opcodes/opcodes_tmp_arm.h" #include "../../../common/bconst.h" /* Désassemble une instruction ARMv7 de données ou autre. */ static GArchInstruction *process_armv7_arm_data_processing_and_miscellaneous_instructions(uint32_t); /* Désassemble une instruction ARMv7 de données de registre. */ static GArchInstruction *process_armv7_arm_data_processing_register(uint32_t); /* Désassemble une instruction ARMv7 de données de immédiate. */ static GArchInstruction *process_armv7_arm_data_processing_immediate(uint32_t); /* Désassemble une instruction ARMv7 liées aux multiplications. */ static GArchInstruction *process_armv7_arm_multiply_and_multiply_accumulate(uint32_t); /* Désassemble une instruction ARMv7 de données ou autre. */ static GArchInstruction *process_armv7_arm_load_store_word_and_unsigned_byte(uint32_t); /* Désassemble une instruction ARMv7 de données ou autre. */ static GArchInstruction *process_armv7_arm_media_instructions(uint32_t); #define process_armv7_arm_parallel_addition_and_subtraction_signed(raw) NULL #define process_armv7_arm_parallel_addition_and_subtraction_unsigned(raw) NULL #define process_armv7_arm_signed_multiply_signed_and_unsigned_divide(raw) NULL /* Désassemble une instruction ARMv7 de données ou autre. */ static GArchInstruction *process_armv7_arm_packing_unpacking_saturation_and_reversal(uint32_t); /* Désassemble une instruction ARMv7 de données ou autre. */ static GArchInstruction *process_armv7_arm_branch_branch_with_link_and_block_data_transfer(uint32_t); // process_armv7_arm_instruction_set_encoding //#define process_armv7_arm_load_store_word_and_unsigned_byte(raw) NULL //#define process_armv7_arm_load_store_word_and_unsigned_byte(raw) NULL //#define process_armv7_arm_media_instructions(raw) NULL //#define process_armv7_arm_branch_branch_with_link_and_block_data_transfer(raw) NULL #define process_armv7_arm_coprocessor_instructions_and_Supervisor_call(raw) NULL #define process_armv7_arm_unconditional_instructions(raw) NULL // process_armv7_arm_data_processing_and_miscellaneous_instructions #define process_armv7_arm_data_processing_register_shifted_register(raw) NULL #define process_armv7_arm_extra_load_store_instructions(raw) NULL #define process_armv7_arm_miscellaneous_instructions(raw) NULL #define process_armv7_arm_halfword_multiply_and_multiply_accumulate(raw) NULL //#define process_armv7_arm_multiply_and_multiply_accumulate(raw) NULL #define process_armv7_arm_synchronization_primitives(raw) NULL #define process_armv7_arm_extra_load_store_instructions_unprivileged(raw) NULL #define process_armv7_arm_extra_load_store_instructions(raw) NULL //#define process_armv7_arm_data_processing_immediate(raw) NULL #define process_armv7_arm_msr_immediate_and_hints(raw) NULL // process_armv7_arm_data_processing_register /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 classique. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ GArchInstruction *process_armv7_arm_instruction_set_encoding(uint32_t raw) { GArchInstruction *result; /* Instruction à renvoyer */ uint32_t cond; /* Champ 'cond' à retrouver */ uint32_t op1; /* Champ 'op1' à retrouver */ uint32_t op; /* Champ 'op' à retrouver */ /** * Suit les directives de : * § A5.1 ARM instruction set encoding */ result = NULL; cond = (raw >> 28) & 0xf; op1 = (raw >> 25) & 0x7; op = (raw >> 4) & 0x1; if (cond != b1111) { if ((op1 & b110) == b000) result = process_armv7_arm_data_processing_and_miscellaneous_instructions(raw); else if (op1 == b010) result = process_armv7_arm_load_store_word_and_unsigned_byte(raw); else if (op1 == b011) { if (op == b0) result = process_armv7_arm_load_store_word_and_unsigned_byte(raw); else result = process_armv7_arm_media_instructions(raw); } else if ((op1 & b110) == b100) result = process_armv7_arm_branch_branch_with_link_and_block_data_transfer(raw); else if ((op1 & b110) == b110) result = process_armv7_arm_coprocessor_instructions_and_Supervisor_call(raw); } else /* if (cond == b1111) */ result = process_armv7_arm_unconditional_instructions(raw); return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données ou autre. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_data_processing_and_miscellaneous_instructions(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t op; /* Champ 'op' à retrouver */ uint32_t op1; /* Champ 'op1' à retrouver */ uint32_t op2; /* Champ 'op2' à retrouver */ /** * Suit les directives de : * § A5.2 Data-processing and miscellaneous instructions */ result = NULL; op = (raw >> 25) & 0x1; op1 = (raw >> 20) & 0x1f; op2 = (raw >> 4) & 0xf; if (op == b0) { if ((op1 & b11001) != b10000) { if ((op2 & b0001) == b0000) result = process_armv7_arm_data_processing_register(raw); else if ((op2 & b1001) == b0001) result = process_armv7_arm_data_processing_register_shifted_register(raw); if (result != NULL) goto padpami_found; } else /* if ((op1 & b11001) == b10000) */ { if ((op2 & b1000) == b0000) result = process_armv7_arm_miscellaneous_instructions(raw); else if ((op2 & b1001) == b1000) result = process_armv7_arm_halfword_multiply_and_multiply_accumulate(raw); if (result != NULL) goto padpami_found; } if ((op1 & b10000) == b00000) { if (op2 == b1001) result = process_armv7_arm_multiply_and_multiply_accumulate(raw); if (result != NULL) goto padpami_found; } if ((op1 & b10000) == b10000) { if (op2 == b1001) result = process_armv7_arm_synchronization_primitives(raw); if (result != NULL) goto padpami_found; } if ((op1 & b10010) != b00010) { if (op2 == b1011) result = process_armv7_arm_extra_load_store_instructions(raw); else if ((op2 & b1101) == b1101) result = process_armv7_arm_extra_load_store_instructions(raw); if (result != NULL) goto padpami_found; } else /* if ((op1 & b10010) != b00010) */ { if (op2 == b1011) result = process_armv7_arm_extra_load_store_instructions_unprivileged(raw); else if ((op2 & b1101) == b1101) result = process_armv7_arm_extra_load_store_instructions(raw); if (result != NULL) goto padpami_found; } } else { if ((op1 & b11001) != b10000) result = process_armv7_arm_data_processing_immediate(raw); else if (op1 == b10000) result = armv7_read_arm_instr_mov_immediate(raw); else if (op1 == b10100) result = armv7_read_arm_instr_movt(raw); else if ((op1 & b11011) == b10010) result = process_armv7_arm_msr_immediate_and_hints(raw); } padpami_found: return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données de registre. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_data_processing_register(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t op; /* Champ 'op' à retrouver */ uint32_t imm5; /* Champ 'imm5' à retrouver */ uint32_t op2; /* Champ 'op2' à retrouver */ /** * Suit les directives de : * § A5.2.1 Data-processing (register) */ result = NULL; op = (raw >> 20) & 0x1f; imm5 = (raw >> 7) & 0x1f; op2 = (raw >> 5) & 0x3; if ((op & b11110) == b00000) result = armv7_read_arm_instr_and_register(raw); else if ((op & b11110) == b00010) result = armv7_read_arm_instr_eor_register(raw); else if ((op & b11110) == b00100) result = armv7_read_arm_instr_sub_register(raw); else if ((op & b11110) == b00110) result = armv7_read_arm_instr_rsb_register(raw); else if ((op & b11110) == b01000) result = armv7_read_arm_instr_add_register_arm(raw); else if ((op & b11110) == b01010) result = armv7_read_arm_instr_adc_register(raw); else if ((op & b11110) == b01100) result = armv7_read_arm_instr_sbc_register(raw); else if ((op & b11110) == b01110) result = armv7_read_arm_instr_rsc_register(raw); /* else if ((op & b11001) == b10000) result = process_armv7_arm_data_processing_and_miscellaneous_instructions(raw); */ else if (op == b10001) result = armv7_read_arm_instr_tst_register(raw); else if (op == b10011) result = armv7_read_arm_instr_teq_register(raw); else if (op == b10101) result = armv7_read_arm_instr_cmp_register(raw); else if (op == b10111) result = armv7_read_arm_instr_cmn_register(raw); else if ((op & b11110) == b11000) result = armv7_read_arm_instr_orr_register(raw); else if ((op & b11110) == b11010) { if (op2 == b00) { if (imm5 == b00000) result = armv7_read_arm_instr_mov_register_arm(raw); else result = armv7_read_arm_instr_lsl_immediate(raw); } else if (op2 == b01) result = armv7_read_arm_instr_lsr_immediate(raw); else if (op2 == b10) result = armv7_read_arm_instr_asr_immediate(raw); else if (op2 == b11) { if (imm5 == b00000) result = armv7_read_arm_instr_rrx(raw); else result = armv7_read_arm_instr_ror_immediate(raw); } } else if ((op & b11110) == b11100) result = armv7_read_arm_instr_bic_register(raw); else if ((op & b11110) == b11110) result = armv7_read_arm_instr_mvn_register(raw); return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données de immédiate. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_data_processing_immediate(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t op; /* Champ 'op' à retrouver */ uint32_t rn; /* Champ 'rn' à retrouver */ /** * Suit les directives de : * § A5.2.3 Data-processing (immediate) */ result = NULL; op = (raw >> 20) & 0x1f; rn = (raw >> 16) & 0xf; if ((op & b11110) == b00000) result = armv7_read_arm_instr_and_immediate(raw); else if ((op & b11110) == b00010) result = armv7_read_arm_instr_eor_immediate(raw); else if ((op & b11110) == b00100) { if (rn == b1111) result = armv7_read_arm_instr_adr(raw); else result = armv7_read_arm_instr_sub_immediate_arm(raw); } else if ((op & b11110) == b00110) result = armv7_read_arm_instr_rsb_immediate(raw); else if ((op & b11110) == b01000) { if (rn == b1111) result = armv7_read_arm_instr_adr(raw); else result = armv7_read_arm_instr_add_immediate_arm(raw); } else if ((op & b11110) == b01010) result = armv7_read_arm_instr_adc_immediate(raw); else if ((op & b11110) == b01100) result = armv7_read_arm_instr_sbc_immediate(raw); else if ((op & b11110) == b01110) result = armv7_read_arm_instr_rsc_immediate(raw); /* else if ((op & b11110) == b10000) result = process_armv7_arm_data_processing_and_miscellaneous_instructions(raw); */ else if (op == b10001) result = armv7_read_arm_instr_tst_immediate(raw); else if (op == b10011) result = armv7_read_arm_instr_teq_immediate(raw); else if (op == b10101) result = armv7_read_arm_instr_cmp_immediate(raw); else if (op == b10111) result = armv7_read_arm_instr_cmn_immediate(raw); else if ((op & b11110) == b11000) result = armv7_read_arm_instr_orr_immediate(raw); else if ((op & b11110) == b11010) result = armv7_read_arm_instr_mov_immediate(raw); else if ((op & b11110) == b11100) result = armv7_read_arm_instr_bic_immediate(raw); else if ((op & b11110) == b11110) result = armv7_read_arm_instr_mvn_immediate(raw); return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 liées aux multiplications. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_multiply_and_multiply_accumulate(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t op; /* Champ 'op' à retrouver */ /** * Suit les directives de : * § A5.2.5 Multiply and multiply accumulate */ result = NULL; if ((raw & 0x0f0000f0) != 0x00000090) return NULL; op = (raw >> 20) & 0xf; if ((op & b1110) == b0000) result = armv7_read_arm_instr_mul(raw); else if ((op & b1110) == b0010) result = armv7_read_arm_instr_mla(raw); else if (op == b0100) result = armv7_read_arm_instr_umaal(raw); else if (op == b0101) result = NULL; /* Non défini */ else if (op == b0110) result = armv7_read_arm_instr_mls(raw); else if (op == b0111) result = NULL; /* Non défini */ else if ((op & b1110) == b1000) result = armv7_read_arm_instr_umull(raw); else if ((op & b1110) == b1010) result = armv7_read_arm_instr_umlal(raw); else if ((op & b1110) == b1100) result = armv7_read_arm_instr_smull(raw); else if ((op & b1110) == b1110) result = armv7_read_arm_instr_smlal(raw); return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données ou autre. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_load_store_word_and_unsigned_byte(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t a; /* Champ 'a' à retrouver */ uint32_t op1; /* Champ 'op1' à retrouver */ uint32_t rn; /* Champ 'rn' à retrouver */ uint32_t b; /* Champ 'b' à retrouver */ /** * Suit les directives de : * § A5.3 Load/store word and unsigned byte */ result = NULL; a = (raw >> 25) & 0x1; op1 = (raw >> 20) & 0x1f; rn = (raw >> 16) & 0xf; b = (raw >> 4) & 0x1; if ((op1 & b10111) == b00010) { if (a == b0) { result = armv7_read_arm_instr_strt(raw); goto a53_done; } else if (/*a == b1 && */b == b0) goto a53_done; } else if ((op1 & b00101) == b00000) { if (a == b0) { result = armv7_read_arm_instr_str_immediate_arm(raw); goto a53_done; } else if (/*a == b1 && */b == b0) { result = armv7_read_arm_instr_str_register(raw); goto a53_done; } } if ((op1 & b10111) == b00011) { if (a == b0) { result = armv7_read_arm_instr_ldrt(raw); goto a53_done; } else if (/*a == b1 && */b == b0) goto a53_done; } else if ((op1 & b00101) == b00001) { if (a == b0) { if (rn == b1111) result = armv7_read_arm_instr_ldr_literal(raw); else result = armv7_read_arm_instr_ldr_immediate_arm(raw); goto a53_done; } else if (/*a == b1 && */b == b0) { result = armv7_read_arm_instr_ldr_register(raw); goto a53_done; } } if ((op1 & b10111) == b00110) { if (a == b0) { result = armv7_read_arm_instr_strbt(raw); goto a53_done; } else if (/*a == b1 && */b == b0) goto a53_done; } else if ((op1 & b00101) == b00100) { if (a == b0) { result = armv7_read_arm_instr_strb_immediate_arm(raw); goto a53_done; } else if (/*a == b1 && */b == b0) { result = armv7_read_arm_instr_strb_register(raw); goto a53_done; } } if ((op1 & b10111) == b00111) { if (a == b0) { result = armv7_read_arm_instr_ldrbt(raw); goto a53_done; } else if (/*a == b1 && */b == b0) goto a53_done; } else if ((op1 & b00101) == b00101) { if (a == b0) { if (rn == b1111) result = armv7_read_arm_instr_ldrb_literal(raw); else result = armv7_read_arm_instr_ldrb_immediate_arm(raw); goto a53_done; } else if (/*a == b1 && */b == b0) { result = armv7_read_arm_instr_ldrb_register(raw); goto a53_done; } } a53_done: return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données ou autre. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_media_instructions(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t cond; /* Champ 'cond' à retrouver */ uint32_t op1; /* Champ 'op1' à retrouver */ uint32_t rd; /* Champ 'rd' à retrouver */ uint32_t op2; /* Champ 'op2' à retrouver */ uint32_t rn; /* Champ 'rn' à retrouver */ /** * Suit les directives de : * § A5.4 Media instructions */ result = NULL; if ((raw & 0x0e000010) != 0x06000010) return NULL; cond = (raw >> 28) & 0xf; op1 = (raw >> 20) & 0x1f; rd = (raw >> 12) & 0xf; op2 = (raw >> 5) & 0x7; rn = (raw >> 0) & 0xf; if ((op1 & b11100) == b00000) result = process_armv7_arm_parallel_addition_and_subtraction_signed(raw); else if ((op1 & b11100) == b00100) result = process_armv7_arm_parallel_addition_and_subtraction_unsigned(raw); else if ((op1 & b11000) == b01000) result = process_armv7_arm_packing_unpacking_saturation_and_reversal(raw); else if ((op1 & b11000) == b10000) result = process_armv7_arm_signed_multiply_signed_and_unsigned_divide(raw); else if (op1 == b11000) { if (op2 == b000) { if (rd == b1111) result = armv7_read_arm_instr_usad8(raw); else result = armv7_read_arm_instr_usada8(raw); } goto a54_done; } else if ((op1 & b11110) == b11010) { if ((op2 & b011) == b010) result = armv7_read_arm_instr_sbfx(raw); goto a54_done; } else if ((op1 & b11110) == b11100) { if ((op2 & b011) == b000) { if (rn == b1111) result = armv7_read_arm_instr_bfc(raw); else result = armv7_read_arm_instr_bfi(raw); } goto a54_done; } else if ((op1 & b11110) == b11110) { if ((op2 & b011) == b010) result = armv7_read_arm_instr_ubfx(raw); goto a54_done; } else if (op1 == b11111 && op2 == b111 && cond == b1110) result = armv7_read_arm_instr_ubfx(raw); a54_done: return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données ou autre. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_packing_unpacking_saturation_and_reversal(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t op1; /* Champ 'op1' à retrouver */ uint32_t a; /* Champ 'a' à retrouver */ uint32_t op2; /* Champ 'op2' à retrouver */ /** * Suit les directives de : * § A5.4.3 Packing, unpacking, saturation, and reversal */ result = NULL; if ((raw & 0x0f800010) != 0x06800010) return NULL; op1 = (raw >> 20) & 0x7; a = (raw >> 16) & 0xf; op2 = (raw >> 5) & 0x7; if ((op1 & b111) == b000) { if ((op2 & b001) == b000) { result = armv7_read_arm_instr_pkh(raw); goto a543_done; } else if (op2 == b011) { if (a == b1111) { result = armv7_read_arm_instr_sxtb16(raw); goto a543_done; } else { result = armv7_read_arm_instr_sxtab16(raw); goto a543_done; } } else if (op2 == b101) { result = armv7_read_arm_instr_sel(raw); goto a543_done; } } else if ((op1 & b110) == b010 && (op2 & b001) == b000) { result = armv7_read_arm_instr_ssat(raw); goto a543_done; } else if (op1 == b010) { if (op2 == b001) { result = armv7_read_arm_instr_ssat16(raw); goto a543_done; } else if (op2 == b011) { if (a == b1111) { result = armv7_read_arm_instr_sxtb(raw); goto a543_done; } else { result = armv7_read_arm_instr_sxtab(raw); goto a543_done; } } } else if (op1 == b011) { if (op2 == b001) { result = armv7_read_arm_instr_rev(raw); goto a543_done; } else if (op2 == b011) { if (a == b1111) { result = armv7_read_arm_instr_sxth(raw); goto a543_done; } else { result = armv7_read_arm_instr_sxtah(raw); goto a543_done; } } else if (op2 == b101) { result = armv7_read_arm_instr_rev16(raw); goto a543_done; } } else if (op1 == b100 && op2 == b011) { if (a == b1111) { result = armv7_read_arm_instr_uxtb16(raw); goto a543_done; } else { result = armv7_read_arm_instr_uxtab16(raw); goto a543_done; } } else if ((op1 & b110) == b110 && (op2 & b001) == b000) { result = armv7_read_arm_instr_usat(raw); goto a543_done; } else if (op1 == b110) { if (op2 == b001) { result = armv7_read_arm_instr_usat16(raw); goto a543_done; } else if (op2 == b011) { if (a == b1111) { result = armv7_read_arm_instr_uxtb(raw); goto a543_done; } else { result = armv7_read_arm_instr_uxtab(raw); goto a543_done; } } } else if (op1 == b111) { if (op2 == b001) { result = armv7_read_arm_instr_rbit(raw); goto a543_done; } else if (op2 == b011) { if (a == b1111) { result = armv7_read_arm_instr_uxth(raw); goto a543_done; } else { result = armv7_read_arm_instr_uxtah(raw); goto a543_done; } } else if (op2 == b101) { result = armv7_read_arm_instr_revsh(raw); goto a543_done; } } a543_done: return result; } /****************************************************************************** * * * Paramètres : raw = donnée brute de 32 bits à désassembler. * * * * Description : Désassemble une instruction ARMv7 de données ou autre. * * * * Retour : Instruction mise en place ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ static GArchInstruction *process_armv7_arm_branch_branch_with_link_and_block_data_transfer(uint32_t raw) { GArchInstruction *result; /* Instruction à retourner */ uint32_t op; /* Champ 'op' à retrouver */ uint32_t rn; /* Champ 'rn' à retrouver */ uint32_t r; /* Champ 'r' à retrouver */ /** * Suit les directives de : * § A5.5 Branch, branch with link, and block data transferr */ result = NULL; op = (raw >> 20) & 0x3f; rn = (raw >> 16) & 0xf; r = (raw >> 15) & 0x1; if ((op & b111101) == b000000) result = armv7_read_arm_instr_stmda_stmed(raw); else if ((op & b111101) == b000001) result = armv7_read_arm_instr_ldmda_ldmfa(raw); else if ((op & b111101) == b001000) result = armv7_read_arm_instr_stm_stmia_stmea(raw); else if (op == b001001) result = armv7_read_arm_instr_ldm_ldmia_ldmfd_arm(raw); else if (op == b001011) { if (rn != b1101) result = armv7_read_arm_instr_ldm_ldmia_ldmfd_arm(raw); else /* if (rn == b1101) */ result = armv7_read_arm_instr_pop_arm(raw); } else if (op == b010000) result = armv7_read_arm_instr_stmdb_stmfd(raw); else if (op == b010010) { if (rn != b1101) result = armv7_read_arm_instr_stmdb_stmfd(raw); else /* if (rn == b1101) */ result = armv7_read_arm_instr_push(raw); } else if ((op & b111101) == b010001) result = armv7_read_arm_instr_ldmdb_ldmea(raw); else if ((op & b111101) == b011000) result = armv7_read_arm_instr_stmib_stmfa(raw); else if ((op & b111101) == b011001) result = armv7_read_arm_instr_ldmib_ldmed(raw); else if ((op & b100101) == b000100) result = armv7_read_arm_instr_stm_user_registers(raw); else if ((op & b100101) == b000101) { if (r == b0) result = armv7_read_arm_instr_ldm_user_registers(raw); else /* if (r == b1) */ result = armv7_read_arm_instr_ldm_exception_return(raw); } else if ((op & b110000) == b100000) result = armv7_read_arm_instr_b(raw); else if ((op & b110000) == b110000) result = armv7_read_arm_instr_bl_blx_immediate(raw); return result; }