summaryrefslogtreecommitdiff
path: root/src/arch/arm
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2014-12-09 23:07:29 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2014-12-09 23:07:29 (GMT)
commit224a2ef04e37cd180a58ede3469fddc59e39bc13 (patch)
tree9b61b706f525304e919e9fa8b1fcb78392746acd /src/arch/arm
parent096f123b87437cf25cd008a6dea710286fbefcf0 (diff)
Supported new ARMv7 instructions.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@438 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/arm')
-rw-r--r--src/arch/arm/v7/helpers.h23
-rw-r--r--src/arch/arm/v7/opcodes/Makefile.am15
-rw-r--r--src/arch/arm/v7/opcodes/opcodes_tmp_arm.h1
-rw-r--r--src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h5
-rw-r--r--src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h4
-rw-r--r--src/arch/arm/v7/opdefs/Makefile.am5
-rw-r--r--src/arch/arm/v7/opdefs/ldrb_A8867.d121
-rw-r--r--src/arch/arm/v7/opdefs/nop_A88119.d50
-rw-r--r--src/arch/arm/v7/opdefs/pop_A88131.d87
-rw-r--r--src/arch/arm/v7/opdefs/push_A88133.d128
-rw-r--r--src/arch/arm/v7/opdefs/strb_A88206.d116
-rw-r--r--src/arch/arm/v7/operands/Makefile.am1
-rw-r--r--src/arch/arm/v7/operands/reglist.c325
-rw-r--r--src/arch/arm/v7/operands/reglist.h72
14 files changed, 943 insertions, 10 deletions
diff --git a/src/arch/arm/v7/helpers.h b/src/arch/arm/v7/helpers.h
index fee5aea..919611e 100644
--- a/src/arch/arm/v7/helpers.h
+++ b/src/arch/arm/v7/helpers.h
@@ -31,6 +31,7 @@
#include "pseudo.h"
#include "operands/maccess.h"
#include "operands/offset.h"
+#include "operands/reglist.h"
#include "operands/shift.h"
#include "../../operand.h"
@@ -188,8 +189,30 @@ return shift_t;
+/**
+ * Glue purement interne pour les listes de registres.
+ */
+
+#define RegistersList(mask) \
+ ({ \
+ GArchOperand *__result; \
+ __result = g_armv7_reglist_operand_new(); \
+ if (!g_armv7_reglist_load_registers(G_ARMV7_REGLIST_OPERAND(__result), mask)) \
+ { \
+ g_object_unref(G_OBJECT(__result)); \
+ __result = NULL; \
+ } \
+ __result; \
+ })
+#define ListFromRegister(reg) \
+ ({ \
+ GArchOperand *__result; \
+ __result = g_armv7_reglist_operand_new(); \
+ g_armv7_reglist_add_register(G_ARMV7_REGLIST_OPERAND(__result), reg); \
+ __result; \
+ })
diff --git a/src/arch/arm/v7/opcodes/Makefile.am b/src/arch/arm/v7/opcodes/Makefile.am
index be437b9..0bff196 100644
--- a/src/arch/arm/v7/opcodes/Makefile.am
+++ b/src/arch/arm/v7/opcodes/Makefile.am
@@ -15,19 +15,24 @@ libarcharmv7opcodes_la_SOURCES = \
arm_cmp.c \
arm_eor.c \
arm_ldr.c \
+ arm_ldrb.c \
arm_lsl.c \
arm_mla.c \
arm_mls.c \
arm_mov.c \
arm_mul.c \
arm_mvn.c \
+ arm_nop.c \
arm_orr.c \
+ arm_pop.c \
+ arm_push.c \
arm_rsb.c \
arm_rsc.c \
arm_sbc.c \
arm_smlal.c \
arm_smull.c \
arm_str.c \
+ arm_strb.c \
arm_sub.c \
arm_subs.c \
arm_teq.c \
@@ -48,19 +53,24 @@ libarcharmv7opcodes_la_SOURCES = \
thumb_16_cmp.c \
thumb_16_eor.c \
thumb_16_ldr.c \
+ thumb_16_ldrb.c \
thumb_16_lsl.c \
thumb_16_mla.c \
thumb_16_mls.c \
thumb_16_mov.c \
thumb_16_mul.c \
thumb_16_mvn.c \
+ thumb_16_nop.c \
thumb_16_orr.c \
+ thumb_16_pop.c \
+ thumb_16_push.c \
thumb_16_rsb.c \
thumb_16_rsc.c \
thumb_16_sbc.c \
thumb_16_smlal.c \
thumb_16_smull.c \
thumb_16_str.c \
+ thumb_16_strb.c \
thumb_16_sub.c \
thumb_16_subs.c \
thumb_16_teq.c \
@@ -81,19 +91,24 @@ libarcharmv7opcodes_la_SOURCES = \
thumb_32_cmp.c \
thumb_32_eor.c \
thumb_32_ldr.c \
+ thumb_32_ldrb.c \
thumb_32_lsl.c \
thumb_32_mla.c \
thumb_32_mls.c \
thumb_32_mov.c \
thumb_32_mul.c \
thumb_32_mvn.c \
+ thumb_32_nop.c \
thumb_32_orr.c \
+ thumb_32_pop.c \
+ thumb_32_push.c \
thumb_32_rsb.c \
thumb_32_rsc.c \
thumb_32_sbc.c \
thumb_32_smlal.c \
thumb_32_smull.c \
thumb_32_str.c \
+ thumb_32_strb.c \
thumb_32_sub.c \
thumb_32_subs.c \
thumb_32_teq.c \
diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
index 1cd3e24..612b45e 100644
--- a/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
+++ b/src/arch/arm/v7/opcodes/opcodes_tmp_arm.h
@@ -11,7 +11,6 @@
#define armv7_read_arm_instr_lsr_immediate(r) NULL
#define armv7_read_arm_instr_movt(r) NULL
#define armv7_read_arm_instr_pop_arm(r) NULL
-#define armv7_read_arm_instr_push(r) NULL
#define armv7_read_arm_instr_ror_immediate(r) NULL
#define armv7_read_arm_instr_rrx(r) NULL
#define armv7_read_arm_instr_stmda_stmed(r) NULL
diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h
index f9ef7d9..fe67305 100644
--- a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h
+++ b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h
@@ -17,7 +17,6 @@
#define armv7_read_thumb_16_instr_eor_register(r) NULL
#define armv7_read_thumb_16_instr_it(r) NULL
#define armv7_read_thumb_16_instr_ldm_ldmia_ldmfd_thumb(r) NULL
-#define armv7_read_thumb_16_instr_ldrb_immediate_thumb(r) NULL
#define armv7_read_thumb_16_instr_ldrb_register(r) NULL
#define armv7_read_thumb_16_instr_ldrh_immediate_thumb(r) NULL
#define armv7_read_thumb_16_instr_ldrh_register(r) NULL
@@ -28,10 +27,7 @@
#define armv7_read_thumb_16_instr_lsr_register(r) NULL
#define armv7_read_thumb_16_instr_mul(r) NULL
#define armv7_read_thumb_16_instr_mvn_register(r) NULL
-#define armv7_read_thumb_16_instr_nop(r) NULL
#define armv7_read_thumb_16_instr_orr_register(r) NULL
-#define armv7_read_thumb_16_instr_pop_thumb(r) NULL
-#define armv7_read_thumb_16_instr_push(r) NULL
#define armv7_read_thumb_16_instr_rev(r) NULL
#define armv7_read_thumb_16_instr_rev16(r) NULL
#define armv7_read_thumb_16_instr_revsh(r) NULL
@@ -41,7 +37,6 @@
#define armv7_read_thumb_16_instr_setend(r) NULL
#define armv7_read_thumb_16_instr_sev(r) NULL
#define armv7_read_thumb_16_instr_stm_stmia_stmea(r) NULL
-#define armv7_read_thumb_16_instr_strb_immediate_thumb(r) NULL
#define armv7_read_thumb_16_instr_strb_register(r) NULL
#define armv7_read_thumb_16_instr_strh_immediate_thumb(r) NULL
#define armv7_read_thumb_16_instr_strh_register(r) NULL
diff --git a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h
index 966d6a2..1f0abb9 100644
--- a/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h
+++ b/src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h
@@ -28,12 +28,9 @@
#define armv7_read_thumb_32_instr_mrs_banked_register(r) NULL
#define armv7_read_thumb_32_instr_msr_banked_register(r) NULL
#define armv7_read_thumb_32_instr_msr_register(r) NULL
-#define armv7_read_thumb_32_instr_nop(r) NULL
#define armv7_read_thumb_32_instr_orn_immediate(r) NULL
#define armv7_read_thumb_32_instr_orn_register(r) NULL
#define armv7_read_thumb_32_instr_pkh(r) NULL
-#define armv7_read_thumb_32_instr_pop_thumb(r) NULL
-#define armv7_read_thumb_32_instr_push(r) NULL
#define armv7_read_thumb_32_instr_qadd(r) NULL
#define armv7_read_thumb_32_instr_qdadd(r) NULL
#define armv7_read_thumb_32_instr_qdsub(r) NULL
@@ -86,7 +83,6 @@
#define armv7_read_thumb_32_instr_ssub8(r) NULL
#define armv7_read_thumb_32_instr_stmdb_stmfd(r) NULL
#define armv7_read_thumb_32_instr_stm_stmia_stmea(r) NULL
-#define armv7_read_thumb_32_instr_strb_immediate_thumb(r) NULL
#define armv7_read_thumb_32_instr_strb_register(r) NULL
#define armv7_read_thumb_32_instr_strbt(r) NULL
#define armv7_read_thumb_32_instr_strh_immediate_thumb(r) NULL
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index 948c9da..a24e706 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -44,6 +44,7 @@ ARMV7_DEFS = \
ldr_A8862.d \
ldr_A8864.d \
ldr_A8865.d \
+ ldrb_A8867.d \
lsl_A8894.d \
mla_A88100.d \
mls_A88101.d \
@@ -53,8 +54,11 @@ ARMV7_DEFS = \
mul_A88114.d \
mvn_A88115.d \
mvn_A88116.d \
+ nop_A88119.d \
orr_A88122.d \
orr_A88123.d \
+ pop_A88131.d \
+ push_A88133.d \
rsb_A88152.d \
rsb_A88153.d \
rsc_A88155.d \
@@ -64,6 +68,7 @@ ARMV7_DEFS = \
smlal_A88178.d \
smull_A88189.d \
str_A88203.d \
+ strb_A88206.d \
sub_A88222.d \
sub_A88223.d \
teq_A88237.d \
diff --git a/src/arch/arm/v7/opdefs/ldrb_A8867.d b/src/arch/arm/v7/opdefs/ldrb_A8867.d
new file mode 100644
index 0000000..8097fd0
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/ldrb_A8867.d
@@ -0,0 +1,121 @@
+
+/* 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 LDRB (immediate, Thumb)
+
+@encoding(t1) {
+
+ @half 0 1 1 1 1 imm5(5) Rn(3) Rt(3)
+
+ @syntax <Rgt>, <access>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm5, 5, 32)
+ access = MakeMemoryAccess(Rgn, imm32, 1, 0)
+
+ }
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 1 1 0 0 0 1 0 0 1 Rn(4) Rt(4) imm12(12)
+
+ @syntax "ldrb.W" <Rgt>, <access>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm12, 12, 32)
+ access = MakeMemoryAccess(Rgn, imm32, 1, 0)
+
+ }
+
+ @rules {
+
+ //if Rt == '1111' then SEE PLD;
+ //if Rn == '1111' then SEE LDRB (literal);
+ //if t == 13 then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T31) {
+
+ @word 1 1 1 1 1 0 0 0 0 0 0 1 Rn(4) Rt(4) 1 1 U(1) W(1) imm8(8)
+
+ @syntax <Rgt> <access>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm8, 8, 32);
+ access = MakeMemoryAccess(Rgn, imm32, U, W)
+
+ }
+
+ @rules {
+
+ //if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD, PLDW (immediate);
+ //if Rn == '1111' then SEE LDRB (literal);
+ //if P == '1' && U == '1' && W == '0' then SEE LDRBT;
+ //if P == '0' && W == '0' then UNDEFINED;
+ //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T32) {
+
+ @word 1 1 1 1 1 0 0 0 0 0 0 1 Rn(4) Rt(4) 1 0 U(1) W(1) imm8(8)
+
+ @syntax <Rgt> <base> <offset>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm8, 8, 32);
+ base = MakeMemoryNotIndexed(Rgn, W)
+ offset = MakeAccessOffset(U, imm32)
+
+ }
+
+ @rules {
+
+ //if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD, PLDW (immediate);
+ //if Rn == '1111' then SEE LDRB (literal);
+ //if P == '1' && U == '1' && W == '0' then SEE LDRBT;
+ //if P == '0' && W == '0' then UNDEFINED;
+ //if t == 13 || (t == 15 && W == '1') || (wback && n == t) then UNPREDICTABLE;
+
+ }
+
+}
diff --git a/src/arch/arm/v7/opdefs/nop_A88119.d b/src/arch/arm/v7/opdefs/nop_A88119.d
new file mode 100644
index 0000000..d47c346
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/nop_A88119.d
@@ -0,0 +1,50 @@
+
+/* 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 NOP
+
+@encoding(t1) {
+
+ @half 1 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 1 0 0 1 1 1 0 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+
+}
+
+@encoding(A1) {
+
+ @word cond(4) 0 0 1 1 0 0 1 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
+
+ @syntax {c}
+
+ @conv {
+
+ c = Condition(cond)
+
+ }
+
+}
diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d
new file mode 100644
index 0000000..329b705
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/pop_A88131.d
@@ -0,0 +1,87 @@
+
+/* 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 POP (Thumb)
+
+@encoding(t1) {
+
+ @half 1 0 1 1 1 1 0 P(1) register_list(8)
+
+ @syntax <registers>
+
+ @conv {
+
+ registers = RegistersList(P:'0000000':register_list)
+
+ }
+
+ @rules {
+
+ //if BitCount(registers) < 1 then UNPREDICTABLE;
+ //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 0 1 0 0 0 1 0 1 1 1 1 0 1 P(1) M(1) 0 register_list(13)
+
+ @syntax "push.W" <registers>
+
+ @conv {
+
+ registers = RegistersList(P:M:'0':register_list)
+
+ }
+
+ @rules {
+
+ //if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
+ //if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T3) {
+
+ @word 1 1 1 1 1 0 0 0 0 1 0 1 1 1 0 1 Rt(4) 1 0 1 1 0 0 0 0 0 1 0 0
+
+ @syntax "push.W" <registers>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ registers = ListFromRegister(Rgt)
+
+ }
+
+ @rules {
+
+ //if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
+
+ }
+
+}
diff --git a/src/arch/arm/v7/opdefs/push_A88133.d b/src/arch/arm/v7/opdefs/push_A88133.d
new file mode 100644
index 0000000..0526a56
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/push_A88133.d
@@ -0,0 +1,128 @@
+
+/* 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 PUSH
+
+@encoding(t1) {
+
+ @half 1 0 1 1 0 1 0 M(1) register_list(8)
+
+ @syntax <registers>
+
+ @conv {
+
+ registers = RegistersList('0':M:'000000':register_list)
+
+ }
+
+ @rules {
+
+ //if BitCount(registers) < 1 then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 0 1 0 0 1 0 0 1 0 1 1 0 1 0 M(1) 0 register_list(13)
+
+ @syntax "push.W" <registers>
+
+ @conv {
+
+ registers = RegistersList('0':M:'0':register_list)
+
+ }
+
+ @rules {
+
+ //if BitCount(registers) < 2 then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T3) {
+
+ @word 1 1 1 1 1 0 0 0 0 1 0 0 1 1 0 1 Rt(4) 1 1 0 1 0 0 0 0 0 1 0 0
+
+ @syntax "push.W" <registers>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ registers = ListFromRegister(Rgt)
+
+ }
+
+ @rules {
+
+ //if t IN {13,15} then UNPREDICTABLE
+
+ }
+
+}
+
+@encoding(A1) {
+
+ @word cond(4) 1 0 0 1 0 0 1 0 1 1 0 1 register_list(16)
+
+ @syntax {c} <registers>
+
+ @conv {
+
+ c = Condition(cond)
+ registers = RegistersList(register_list)
+
+ }
+
+ @rules {
+
+ //if BitCount(register_list) < 2 then SEE STMDB / STMFD;
+
+ }
+
+}
+
+@encoding(A2) {
+
+ @word cond(4) 0 1 0 1 0 0 1 0 1 1 0 1 Rt(4) 0 0 0 0 0 0 0 0 0 1 0 0
+
+ @syntax {c} <registers>
+
+ @conv {
+
+ c = Condition(cond)
+ Rgt = Register(Rt)
+ registers = ListFromRegister(Rgt)
+
+ }
+
+ @rules {
+
+ //if t == 13 then UNPREDICTABLE;
+
+ }
+
+}
diff --git a/src/arch/arm/v7/opdefs/strb_A88206.d b/src/arch/arm/v7/opdefs/strb_A88206.d
new file mode 100644
index 0000000..4799f61
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/strb_A88206.d
@@ -0,0 +1,116 @@
+
+/* 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 STRB (immediate, Thumb)
+
+@encoding(t1) {
+
+ @half 0 1 1 1 0 imm5(5) Rn(3) Rt(3)
+
+ @syntax <Rgt>, <access>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm5, 5, 32)
+ access = MakeMemoryAccess(Rgn, imm32, 1, 0)
+
+ }
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 1 1 0 0 0 1 0 0 0 Rn(4) Rt(4) imm12(12)
+
+ @syntax "strb.W" <Rgt>, <access>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm12, 12, 32)
+ access = MakeMemoryAccess(Rgn, imm32, 1, 0)
+
+ }
+
+ @rules {
+
+ //if Rn == '1111' then UNDEFINED;
+ //if t IN {13,15} then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T31) {
+
+ @word 1 1 1 1 1 0 0 0 0 0 0 0 Rn(4) Rt(4) 1 1 U(1) W(1) imm8(8)
+
+ @syntax <Rgt> <access>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm8, 8, 32);
+ access = MakeMemoryAccess(Rgn, imm32, U, W)
+
+ }
+
+ @rules {
+
+ //if P == '1' && U == '1' && W == '0' then SEE STRBT;
+ //if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
+ //if t IN {13,15} || (wback && n == t) then UNPREDICTABLE;
+
+ }
+
+}
+
+@encoding(T32) {
+
+ @word 1 1 1 1 1 0 0 0 0 0 0 0 Rn(4) Rt(4) 1 0 U(1) W(1) imm8(8)
+
+ @syntax <Rgt> <base> <offset>
+
+ @conv {
+
+ Rgt = Register(Rt)
+ Rgn = Register(Rn)
+ imm32 = ZeroExtend(imm8, 8, 32);
+ base = MakeMemoryNotIndexed(Rgn, W)
+ offset = MakeAccessOffset(U, imm32)
+
+ }
+
+ @rules {
+
+ //if P == '1' && U == '1' && W == '0' then SEE STRBT;
+ //if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
+ //if t IN {13,15} || (wback && n == t) then UNPREDICTABLE;
+
+ }
+
+}
diff --git a/src/arch/arm/v7/operands/Makefile.am b/src/arch/arm/v7/operands/Makefile.am
index 8733bfe..32648c9 100644
--- a/src/arch/arm/v7/operands/Makefile.am
+++ b/src/arch/arm/v7/operands/Makefile.am
@@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libarcharmv7operands.la
libarcharmv7operands_la_SOURCES = \
maccess.h maccess.c \
offset.h offset.c \
+ reglist.h reglist.c \
shift.h shift.c
libarcharmv7operands_la_LIBADD =
diff --git a/src/arch/arm/v7/operands/reglist.c b/src/arch/arm/v7/operands/reglist.c
new file mode 100644
index 0000000..a54d148
--- /dev/null
+++ b/src/arch/arm/v7/operands/reglist.c
@@ -0,0 +1,325 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * reglist.c - accès à la mémorie à partir d'un registre et d'un décallage
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "reglist.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+
+
+#include "../../../operand-int.h"
+#include "../../../register.h"
+
+
+
+/* Définition d'un opérande listant une série de registres ARM (instance) */
+struct _GArmV7RegListOperand
+{
+ GArchOperand parent; /* Instance parente */
+
+ GArmV7Register **registers; /* Liste de registres intégrés */
+ size_t count; /* Taille de cette liste */
+
+};
+
+
+/* Définition d'un opérande listant une série de registres ARM (classe) */
+struct _GArmV7RegListOperandClass
+{
+ GArchOperandClass parent; /* Classe parente */
+
+};
+
+
+/* Initialise la classe des listes de registres ARM. */
+static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *);
+
+/* Initialise une instance de liste de registres ARM. */
+static void g_armv7_reglist_operand_init(GArmV7RegListOperand *);
+
+/* Supprime toutes les références externes. */
+static void g_armv7_reglist_operand_dispose(GArmV7RegListOperand *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_armv7_reglist_operand_finalize(GArmV7RegListOperand *);
+
+/* Traduit un opérande en version humainement lisible. */
+static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *, GBufferLine *, AsmSyntax);
+
+
+
+/* Indique le type défini par la GLib pour une liste de registres ARM. */
+G_DEFINE_TYPE(GArmV7RegListOperand, g_armv7_reglist_operand, G_TYPE_ARCH_OPERAND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des listes de registres ARM. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_reglist_operand_class_init(GArmV7RegListOperandClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GArchOperandClass *operand; /* Version de classe parente */
+
+ object = G_OBJECT_CLASS(klass);
+ operand = G_ARCH_OPERAND_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_armv7_reglist_operand_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_armv7_reglist_operand_finalize;
+
+ operand->print = (operand_print_fc)g_armv7_reglist_operand_print;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance de liste de registres ARM. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_reglist_operand_init(GArmV7RegListOperand *operand)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_reglist_operand_dispose(GArmV7RegListOperand *operand)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < operand->count; i++)
+ g_object_unref(G_OBJECT(operand->registers[i]));
+
+ G_OBJECT_CLASS(g_armv7_reglist_operand_parent_class)->dispose(G_OBJECT(operand));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_reglist_operand_finalize(GArmV7RegListOperand *operand)
+{
+ if (operand->registers != NULL)
+ free(operand->registers);
+
+ G_OBJECT_CLASS(g_armv7_reglist_operand_parent_class)->finalize(G_OBJECT(operand));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une liste vierge de registres ARM. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_reglist_operand_new(void)
+{
+ GArmV7RegListOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ARMV7_REGLIST_OPERAND, NULL);
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* line = ligne tampon où imprimer l'opérande donné. *
+* syntax = type de représentation demandée. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_armv7_reglist_operand_print(const GArmV7RegListOperand *operand, GBufferLine *line, AsmSyntax syntax)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY, "{", 1, RTT_HOOK);
+
+ for (i = 0; i < operand->count; i++)
+ {
+ if (i > 0)
+ {
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT);
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW);
+ }
+
+ g_arch_register_print(G_ARCH_REGISTER(operand->registers[i]), line, syntax);
+
+ }
+
+ g_buffer_line_insert_text(line, BLC_ASSEMBLY, "}", 1, RTT_HOOK);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = liste de registres à compléter. *
+* selected = masque de bits pour les registres à intégrer. *
+* *
+* Description : Remplit une liste de registres de registres ARM. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_armv7_reglist_load_registers(GArmV7RegListOperand *operand, uint32_t selected)
+{
+ uint8_t i; /* Boucle de parcours */
+ GArmV7Register *reg; /* Nouveau registre à intégrer */
+
+ for (i = 18; i < 32; i++)
+ if (selected & (1 << i)) return false;
+
+ for (i = 0; i < 18; i++)
+ {
+ if ((selected & (1 << i)) == 0) continue;
+
+ reg = g_armv7_register_new(i);
+ g_armv7_reglist_add_register(operand, reg);
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = liste de registres à compléter. *
+* reg = nouveau registre à intégrer. *
+* *
+* Description : Ajoute un registre à une liste de registres ARM. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_armv7_reglist_add_register(GArmV7RegListOperand *operand, GArmV7Register *reg)
+{
+ operand->registers = (GArmV7Register **)realloc(operand->registers,
+ ++operand->count * sizeof(GArmV7Register *));
+
+ operand->registers[operand->count - 1] = reg;
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Compte le nombre de registres ARM composant la liste. *
+* *
+* Retour : Nombre positif ou nul. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_armv7_reglist_count_registers(const GArmV7RegListOperand *operand)
+{
+ return operand->count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* index = indice de l'élément à fournier. *
+* *
+* Description : Founit un élément donné d'une liste de registres ARM. *
+* *
+* Retour : Registre intégré à la liste manipulée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArmV7Register *g_armv7_reglist_operand_get_register(const GArmV7RegListOperand *operand, size_t index)
+{
+ assert(index < operand->count);
+
+ return operand->registers[index];
+
+}
diff --git a/src/arch/arm/v7/operands/reglist.h b/src/arch/arm/v7/operands/reglist.h
new file mode 100644
index 0000000..cf0b9c0
--- /dev/null
+++ b/src/arch/arm/v7/operands/reglist.h
@@ -0,0 +1,72 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * reglist.h - prototypes pour les accès à la mémorie à partir d'un registre et d'un décallage
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _ARCH_ARM_V7_OPERANDS_REGLIST_H
+#define _ARCH_ARM_V7_OPERANDS_REGLIST_H
+
+
+#include <glib-object.h>
+#include <stdbool.h>
+
+
+#include "../register.h"
+#include "../../../operand.h"
+
+
+
+#define G_TYPE_ARMV7_REGLIST_OPERAND g_armv7_reglist_operand_get_type()
+#define G_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_armv7_reglist_operand_get_type(), GArmV7RegListOperand))
+#define G_IS_ARMV7_REGLIST_OPERAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_armv7_reglist_operand_get_type()))
+#define G_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass))
+#define G_IS_ARMV7_REGLIST_OPERAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_ARMV7_REGLIST_OPERAND))
+#define G_ARMV7_REGLIST_OPERAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_ARMV7_REGLIST_OPERAND, GArmV7RegListOperandClass))
+
+
+/* Définition d'un opérande listant une série de registres ARM (instance) */
+typedef struct _GArmV7RegListOperand GArmV7RegListOperand;
+
+/* Définition d'un opérande listant une série de registres ARM (classe) */
+typedef struct _GArmV7RegListOperandClass GArmV7RegListOperandClass;
+
+
+/* Indique le type défini par la GLib pour une liste de registres ARM. */
+GType g_armv7_reglist_operand_get_type(void);
+
+/* Crée une liste vierge de registres ARM. */
+GArchOperand *g_armv7_reglist_operand_new(void);
+
+/* Remplit une liste de registres de registres ARM. */
+bool g_armv7_reglist_load_registers(GArmV7RegListOperand *, uint32_t);
+
+/* Ajoute un registre à une liste de registres ARM. */
+void g_armv7_reglist_add_register(GArmV7RegListOperand *, GArmV7Register *);
+
+/* Compte le nombre de registres ARM composant la liste. */
+size_t g_armv7_reglist_count_registers(const GArmV7RegListOperand *);
+
+/* Founit un élément donné d'une liste de registres ARM. */
+GArmV7Register *g_armv7_reglist_operand_get_register(const GArmV7RegListOperand *, size_t );
+
+
+
+#endif /* _ARCH_ARM_V7_OPERANDS_REGLIST_H */