summaryrefslogtreecommitdiff
path: root/src/arch/arm/v7
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm/v7')
-rw-r--r--src/arch/arm/v7/arm.c121
-rw-r--r--src/arch/arm/v7/helpers.c56
-rw-r--r--src/arch/arm/v7/helpers.h4
-rw-r--r--src/arch/arm/v7/opcodes/Makefile.am1
-rw-r--r--src/arch/arm/v7/opdefs/Makefile.am4
-rw-r--r--src/arch/arm/v7/opdefs/bl_A8825.d84
6 files changed, 267 insertions, 3 deletions
diff --git a/src/arch/arm/v7/arm.c b/src/arch/arm/v7/arm.c
index 5295ef8..b7d4ff1 100644
--- a/src/arch/arm/v7/arm.c
+++ b/src/arch/arm/v7/arm.c
@@ -39,6 +39,8 @@ static GArchInstruction *process_armv7_data_processing_and_miscellaneous_instruc
/* Désassemble une instruction ARMv7 de données de registre. */
static GArchInstruction *process_armv7_data_processing_register(uint32_t);
+/* Désassemble une instruction ARMv7 de données ou autre. */
+static GArchInstruction *process_armv7_branch_branch_with_link_and_block_data_transfer(uint32_t);
@@ -47,7 +49,7 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t);
#define process_armv7_load_store_word_and_unsigned_byte(raw) NULL
#define process_armv7_load_store_word_and_unsigned_byte(raw) NULL
#define process_armv7_media_instructions(raw) NULL
-#define process_armv7_branch_branch_with_link_and_block_data_transfer(raw) NULL
+//#define process_armv7_branch_branch_with_link_and_block_data_transfer(raw) NULL
#define process_armv7_coprocessor_instructions_and_Supervisor_call(raw) NULL
#define process_armv7_unconditional_instructions(raw) NULL
@@ -93,6 +95,26 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t);
#define armv7_read_instr_mvn_register(raw) NULL
+// process_armv7_branch_branch_with_link_and_block_data_transfer
+
+#define armv7_read_instr_stmda_stmed(raw) NULL
+#define armv7_read_instr_ldmda_ldmfa(raw) NULL
+#define armv7_read_instr_stm_stmia_stmea(raw) NULL
+#define armv7_read_instr_ldm_ldmia_ldmfd_arm(raw) NULL
+#define armv7_read_instr_ldm_ldmia_ldmfd_arm(raw) NULL
+#define armv7_read_instr_pop_arm(raw) NULL
+#define armv7_read_instr_stmdb_stmfd(raw) NULL
+#define armv7_read_instr_stmdb_stmfd(raw) NULL
+#define armv7_read_instr_push(raw) NULL
+#define armv7_read_instr_ldmdb_ldmea(raw) NULL
+#define armv7_read_instr_stmib_stmfa(raw) NULL
+#define armv7_read_instr_ldmib_ldmed(raw) NULL
+#define armv7_read_instr_stm_user_registers(raw) NULL
+#define armv7_read_instr_ldm_user_registers(raw) NULL
+#define armv7_read_instr_ldm_exception_return(raw) NULL
+#define armv7_read_instr_b(raw) NULL
+//#define armv7_read_instr_bl_blx_immediate(raw) NULL
+
@@ -127,7 +149,6 @@ GArchInstruction *process_armv7_instruction_set_encoding(uint32_t raw)
op1 = (raw >> 25) & 0x7;
op = (raw >> 4) & 0x1;
-
if (cond != b1111)
{
if ((op1 & b110) == b000)
@@ -403,3 +424,99 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t raw)
+
+
+
+
+
+
+/******************************************************************************
+* *
+* 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_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_instr_stmda_stmed(raw);
+
+ else if ((op & b111101) == b000001)
+ result = armv7_read_instr_ldmda_ldmfa(raw);
+
+ else if ((op & b111101) == b001000)
+ result = armv7_read_instr_stm_stmia_stmea(raw);
+
+ else if (op == b001001)
+ result = armv7_read_instr_ldm_ldmia_ldmfd_arm(raw);
+
+ else if (op == b001011)
+ {
+ if (rn != b1101)
+ result = armv7_read_instr_ldm_ldmia_ldmfd_arm(raw);
+ else /* if (rn == b1101) */
+ result = armv7_read_instr_pop_arm(raw);
+ }
+
+ else if (op == b010000)
+ result = armv7_read_instr_stmdb_stmfd(raw);
+
+ else if (op == b010010)
+ {
+ if (rn != b1101)
+ result = armv7_read_instr_stmdb_stmfd(raw);
+ else /* if (rn == b1101) */
+ result = armv7_read_instr_push(raw);
+ }
+
+ else if ((op & b111101) == b010001)
+ result = armv7_read_instr_ldmdb_ldmea(raw);
+
+ else if ((op & b111101) == b011000)
+ result = armv7_read_instr_stmib_stmfa(raw);
+
+ else if ((op & b111101) == b011001)
+ result = armv7_read_instr_ldmib_ldmed(raw);
+
+ else if ((op & b100101) == b000100)
+ result = armv7_read_instr_stm_user_registers(raw);
+
+ else if ((op & b100101) == b000101)
+ {
+ if (r == b0)
+ result = armv7_read_instr_ldm_user_registers(raw);
+ else /* if (r == b1) */
+ result = armv7_read_instr_ldm_exception_return(raw);
+ }
+
+ else if ((op & b110000) == b100000)
+ result = armv7_read_instr_b(raw);
+
+ else if ((op & b110000) == b110000)
+ result = armv7_read_instr_bl_blx_immediate(raw);
+
+ return result;
+
+}
diff --git a/src/arch/arm/v7/helpers.c b/src/arch/arm/v7/helpers.c
index 632c1b7..e7c9ad8 100644
--- a/src/arch/arm/v7/helpers.c
+++ b/src/arch/arm/v7/helpers.c
@@ -26,11 +26,67 @@
#include "register.h"
#include "../../register.h"
+#include "../../immediate.h"
+#include "../../../common/asm.h"
/******************************************************************************
* *
+* Paramètres : value = valeur sur 32 bits maximum à traiter. *
+* topbit = valeur du bit de poids fort manipulé. *
+* size = taille de la valeur finale à constituer. *
+* *
+* Description : Crée un opérande de valeur immédiate avec extension de signe.*
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *sign_extend_armv7_imm(uint32_t value, bool topbit, unsigned int size)
+{
+ GArchOperand *result; /* Opérande à faire remonter */
+ unsigned int msb; /* Position du premier bit à 1 */
+ MemoryDataSize mds; /* Conversion de la taille */
+ uint32_t val4; /* Valeur sur 4 bits */
+ uint32_t val8; /* Valeur sur 8 bits */
+ uint32_t val16; /* Valeur sur 16 bits */
+ uint32_t val32; /* Valeur sur 32 bits */
+ unsigned int i; /* Boucle de parcours */
+
+ result = NULL;
+
+ topbit &= msb_32(value, &msb);
+
+ switch (size)
+ {
+
+#define SIGN_EXTEND_CASE(sz) \
+ case sz: \
+ mds = MDS_ ## sz ## _BITS_SIGNED; \
+ val ## sz = value; \
+ if (topbit) \
+ for (i = msb + 1; i < sz; i++) \
+ val ## sz |= (1 << i); \
+ result = g_imm_operand_new_from_value(mds, val ## sz); \
+ break;
+
+ SIGN_EXTEND_CASE(4);
+ SIGN_EXTEND_CASE(8);
+ SIGN_EXTEND_CASE(16);
+ SIGN_EXTEND_CASE(32);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : index = indice du registre correspondant. *
* *
* Description : Crée un opérande représentant un registre ARMv7. *
diff --git a/src/arch/arm/v7/helpers.h b/src/arch/arm/v7/helpers.h
index 9ea0d74..087b2e7 100644
--- a/src/arch/arm/v7/helpers.h
+++ b/src/arch/arm/v7/helpers.h
@@ -25,6 +25,7 @@
#define _ARCH_ARM_V7_HELPERS_H
+#include <stdbool.h>
#include <stdint.h>
@@ -32,6 +33,9 @@
+/* Crée un opérande de valeur immédiate avec extension de signe. */
+GArchOperand *sign_extend_armv7_imm(uint32_t, bool, unsigned int);
+
/* Crée un opérande représentant un registre ARMv7. */
GArchOperand *translate_armv7_register(uint8_t);
diff --git a/src/arch/arm/v7/opcodes/Makefile.am b/src/arch/arm/v7/opcodes/Makefile.am
index e77b7e8..dc5c8d9 100644
--- a/src/arch/arm/v7/opcodes/Makefile.am
+++ b/src/arch/arm/v7/opcodes/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libarcharmv7opcodes.la
libarcharmv7opcodes_la_SOURCES = \
+ bl.c \
mov.c \
subs.c
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index f2c5a35..9aa6a82 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -17,9 +17,11 @@ D2C_MACROS = \
-M SetFlags=g_armv7_instruction_define_setflags \
-M Condition=g_arm_instruction_set_cond \
-M Register=translate_armv7_register \
- -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, "
+ -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, " \
+ -M SignExtend=sign_extend_armv7_imm
ARMV7_DEFS = \
+ bl_A8825.d \
mov_A88104.d \
subs_B9320.d
diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d
new file mode 100644
index 0000000..c9ef5d0
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/bl_A8825.d
@@ -0,0 +1,84 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ##FILE## - traduction d'instructions ARMv7
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+@title BL, BLX (immediate)
+
+@encoding(T1) {
+
+ @word 1 1 1 1 0 S(1) imm10H(10) 1 1 J1(1) 1 J2(1) imm10L(10) H(1)
+
+ @syntax <imm32>
+
+ @conv {
+
+ I1 = NOT(J1 EOR S)
+ I2 = NOT(J2 EOR S)
+ imm32 = SignExtend(S:I1:I2:imm10H:imm10L:'00', s, 32)
+
+ }
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 1 0 S(1) imm10(10) 1 1 J1(1) 0 J2(1) imm11(11)
+
+ @syntax <imm32>
+
+ @conv {
+
+ I1 = NOT(J1 EOR S)
+ I2 = NOT(J2 EOR S)
+ imm32 = SignExtend(S:I1:I2:imm10:imm11:'0', S, 32)
+
+ }
+
+}
+
+@encoding(A1) {
+
+ @word cond(4) 1 0 1 1 imm24(24)
+
+ @syntax <imm32>
+
+ @conv {
+
+ imm32 = SignExtend(imm24:'00', 0, 32)
+
+ }
+
+}
+
+@encoding(A2) {
+
+ @word cond(4) 1 0 1 H(1) imm24(24)
+
+ @syntax <imm32>
+
+ @conv {
+
+ imm32 = SignExtend(imm24:H:'0', 0, 32)
+
+ }
+
+}