From 224a2ef04e37cd180a58ede3469fddc59e39bc13 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Tue, 9 Dec 2014 23:07:29 +0000
Subject: Supported new ARMv7 instructions.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@438 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                                      |  35 +++
 src/arch/arm/v7/helpers.h                      |  23 ++
 src/arch/arm/v7/opcodes/Makefile.am            |  15 ++
 src/arch/arm/v7/opcodes/opcodes_tmp_arm.h      |   1 -
 src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h |   5 -
 src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h |   4 -
 src/arch/arm/v7/opdefs/Makefile.am             |   5 +
 src/arch/arm/v7/opdefs/ldrb_A8867.d            | 121 +++++++++
 src/arch/arm/v7/opdefs/nop_A88119.d            |  50 ++++
 src/arch/arm/v7/opdefs/pop_A88131.d            |  87 +++++++
 src/arch/arm/v7/opdefs/push_A88133.d           | 128 ++++++++++
 src/arch/arm/v7/opdefs/strb_A88206.d           | 116 +++++++++
 src/arch/arm/v7/operands/Makefile.am           |   1 +
 src/arch/arm/v7/operands/reglist.c             | 325 +++++++++++++++++++++++++
 src/arch/arm/v7/operands/reglist.h             |  72 ++++++
 tools/d2c/d2c_tok.l                            |   4 +-
 16 files changed, 980 insertions(+), 12 deletions(-)
 create mode 100644 src/arch/arm/v7/opdefs/ldrb_A8867.d
 create mode 100644 src/arch/arm/v7/opdefs/nop_A88119.d
 create mode 100644 src/arch/arm/v7/opdefs/pop_A88131.d
 create mode 100644 src/arch/arm/v7/opdefs/push_A88133.d
 create mode 100644 src/arch/arm/v7/opdefs/strb_A88206.d
 create mode 100644 src/arch/arm/v7/operands/reglist.c
 create mode 100644 src/arch/arm/v7/operands/reglist.h

diff --git a/ChangeLog b/ChangeLog
index 9157004..ca48b3b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+14-12-09  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/arch/arm/v7/helpers.h:
+	Add some sugar for the lists of registers.
+
+	* src/arch/arm/v7/opcodes/Makefile.am:
+	Update libarcharmv7opcodes_la_SOURCES.
+
+	* src/arch/arm/v7/opcodes/opcodes_tmp_arm.h:
+	* src/arch/arm/v7/opcodes/opcodes_tmp_thumb_16.h:
+	* src/arch/arm/v7/opcodes/opcodes_tmp_thumb_32.h:
+	Update missing prototypes.
+
+	* src/arch/arm/v7/opdefs/ldrb_A8867.d:
+	New entries: support new ARMv7 instructions.
+
+	* src/arch/arm/v7/opdefs/Makefile.am:
+	Add new definitions to ARMV7_DEFS.
+
+	* src/arch/arm/v7/opdefs/nop_A88119.d:
+	* src/arch/arm/v7/opdefs/pop_A88131.d:
+	* src/arch/arm/v7/opdefs/push_A88133.d:
+	* src/arch/arm/v7/opdefs/strb_A88206.d:
+	New entries: support new ARMv7 instructions.
+
+	* src/arch/arm/v7/operands/Makefile.am:
+	Add the 'reglist.[ch]' files to libarcharmv7operands_la_SOURCES.
+
+	* src/arch/arm/v7/operands/reglist.c:
+	* src/arch/arm/v7/operands/reglist.h:
+	New entries: handle list of ARM regisers.
+
+	* tools/d2c/d2c_tok.l:
+	Allow underscores in more names.
+
 14-12-08  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/arm/v7/helpers.h:
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 */
diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l
index b7e50fd..71f1a15 100644
--- a/tools/d2c/d2c_tok.l
+++ b/tools/d2c/d2c_tok.l
@@ -80,7 +80,7 @@ void free_flex_memory(void) ;
 
 <encoding_bits>" "                  { }
 <encoding_bits>"\n"                 { BEGIN(encoding_content); }
-<encoding_bits>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; }
+<encoding_bits>[A-Za-z][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; }
 
 <encoding_bits>"("                  { BEGIN(encoding_bits_size); }
 <encoding_bits_size>[0-9]+          { d2c_lval.integer = atoi(yytext); return SIZE; }
@@ -125,7 +125,7 @@ void free_flex_memory(void) ;
                                     }
 <conv_content>"="                   { return EQ; }
 <conv_content>"("                   { BEGIN(conv_arg); return OP; }
-<conv_arg>[A-Za-z][A-Za-z0-9]*      {
+<conv_arg>[A-Za-z][A-Za-z0-9_]*      {
                                       if (strcmp(yytext, "NOT") == 0) return NOT;
                                       else if (strcmp(yytext, "EOR") == 0) return EOR;
                                       else
-- 
cgit v0.11.2-87-g4458