From 4cef477cbdfd61a28ed6531d1e91d5a330a67704 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 18 Mar 2015 23:18:26 +0000
Subject: Computed limits for all routines according to existing symbols.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@491 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                            |  55 ++++++++++++++++
 src/analysis/disass/area.c           |  74 ++++++++++++++++++++++
 src/analysis/disass/disassembler.c   |  23 ++++++-
 src/analysis/disass/limit.c          |  25 ++++++++
 src/arch/arm/v7/opdefs/Makefile.am   |   3 +-
 src/arch/arm/v7/opdefs/b_A8818.d     |  10 +--
 src/arch/arm/v7/opdefs/bl_A8825.d    |   8 +--
 src/arch/arm/v7/opdefs/blx_A8826.d   |   4 +-
 src/arch/arm/v7/opdefs/bx_A8827.d    |   4 +-
 src/arch/arm/v7/opdefs/ldr_A8862.d   |   6 +-
 src/arch/arm/v7/opdefs/ldr_A8863.d   |   4 +-
 src/arch/arm/v7/opdefs/ldr_A8864.d   |   4 +-
 src/arch/arm/v7/opdefs/ldr_A8865.d   |   2 +-
 src/arch/arm/v7/opdefs/ldrb_A8867.d  |   6 +-
 src/arch/arm/v7/opdefs/pop_A88131.d  |   4 +-
 src/arch/arm/v7/opdefs/push_A88133.d |  10 +++
 src/arch/arm/v7/opdefs/str_A88204.d  |   4 +-
 src/arch/arm/v7/post.c               |   6 +-
 src/arch/instruction-int.h           |   1 +
 src/arch/instruction.c               |  41 +++++++++++-
 src/arch/instruction.h               |  14 +++++
 src/format/format.c                  |  19 +++++-
 src/format/symbol.c                  |  32 +++++++++-
 src/format/symbol.h                  |   4 ++
 tools/d2c/args.c                     |  29 +++++++--
 tools/d2c/args.h                     |   1 +
 tools/d2c/d2c_gram.y                 |  22 ++++---
 tools/d2c/d2c_tok.l                  |  32 ++++++----
 tools/d2c/qckcall.c                  | 119 ++++++++++++++++++++++++++++-------
 tools/d2c/qckcall.h                  |   3 +
 tools/d2c/rules.c                    |  75 +++++++++++++++++-----
 tools/d2c/rules.h                    |   8 ++-
 tools/d2c/spec.c                     |   3 +
 33 files changed, 552 insertions(+), 103 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 81df404..2dcb1d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+15-03-18  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/disass/area.c:
+	Ensure symbols exist where instructions are marked as first instructions
+	of a routine.
+
+	* src/analysis/disass/disassembler.c:
+	* src/analysis/disass/limit.c:
+	Compute limits for all routines according to existing symbols.
+
+	* src/arch/arm/v7/opdefs/b_A8818.d:
+	* src/arch/arm/v7/opdefs/bl_A8825.d:
+	* src/arch/arm/v7/opdefs/blx_A8826.d:
+	* src/arch/arm/v7/opdefs/bx_A8827.d:
+	* src/arch/arm/v7/opdefs/ldr_A8862.d:
+	* src/arch/arm/v7/opdefs/ldr_A8863.d:
+	* src/arch/arm/v7/opdefs/ldr_A8864.d:
+	* src/arch/arm/v7/opdefs/ldr_A8865.d:
+	* src/arch/arm/v7/opdefs/ldrb_A8867.d:
+	* src/arch/arm/v7/opdefs/Makefile.am:
+	* src/arch/arm/v7/opdefs/pop_A88131.d:
+	* src/arch/arm/v7/opdefs/push_A88133.d:
+	* src/arch/arm/v7/opdefs/str_A88204.d:
+	Update all rules calls and define a new one for instruction flags.
+
+	* src/arch/arm/v7/post.c:
+	Update symbol types: they are STP_CODE_LABEL, not STP_ROUTINE.
+
+	* src/arch/instruction.c:
+	* src/arch/instruction.h:
+	* src/arch/instruction-int.h:
+	Define generic instruction flags.
+
+	* src/format/format.c:
+	Collect routines when symbols are added.
+
+	* src/format/symbol.c:
+	* src/format/symbol.h:
+	Update code for the new 'STP_CODE_LABEL' type.
+
+	* tools/d2c/args.c:
+	* tools/d2c/args.h:
+	Allow constants unknown by d2c to be used: gcc will recognize them.
+
+	* tools/d2c/d2c_gram.y:
+	* tools/d2c/d2c_tok.l:
+	Handle binary as well as hex values for conditions. Update code.
+
+	* tools/d2c/qckcall.c:
+	* tools/d2c/qckcall.h:
+	* tools/d2c/rules.c:
+	* tools/d2c/rules.h:
+	* tools/d2c/spec.c:
+	Allow to call routines with or without return code.
+
 15-03-13  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/area.c:
diff --git a/src/analysis/disass/area.c b/src/analysis/disass/area.c
index 916918e..90738be 100644
--- a/src/analysis/disass/area.c
+++ b/src/analysis/disass/area.c
@@ -71,6 +71,11 @@ static bool mark_range_in_mem_area_as_processed(mem_area *, phys_t, phys_t, GArc
 
 
 
+/* S'assure de la présence d'un début de routine à un point. */
+static void update_address_as_routine(GBinFormat *, const vmpa2t *);
+
+
+
 
 /* Procède au désassemblage d'un contenu binaire non exécutable. */
 static void load_data_from_mem_area(mem_area *, mem_area *, size_t, const GLoadedBinary *, GProcContext *, const vmpa2t *, status_blob_info *);
@@ -377,6 +382,70 @@ static bool mark_range_in_mem_area_as_processed(mem_area *area, phys_t start, ph
 
 
 
+
+
+
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = format binaire en cours de traitement.              *
+*                addr   = adresse d'une instruction présentée comme première. *
+*                                                                             *
+*  Description : S'assure de la présence d'un début de routine à un point.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void update_address_as_routine(GBinFormat *format, const vmpa2t *addr)
+{
+    GBinSymbol *symbol;                     /* Symbole présent ou créé     */
+    phys_t offset;                          /* Décallage trouvé            */
+    bool found;                             /* Détection de symbole        */
+    SymbolType sym_type;                    /* Type de symbole en place    */
+    bool wrong_type;                        /* Analyse plus fine de ce type*/
+    mrange_t range;                         /* Etendue du symbole à créer  */
+    VMPA_BUFFER(loc);                       /* Traduction de l'adresse     */
+    char name[5 + VMPA_MAX_LEN];            /* Nom de symbole nouveau      */
+    GBinRoutine *routine;                   /* Nouvelle routine trouvée    */
+
+    found = g_binary_format_resolve_symbol(format, addr, &symbol, &offset);
+
+    if (found)
+    {
+        sym_type = g_binary_symbol_get_target_type(symbol);
+        wrong_type = (sym_type != STP_ROUTINE && sym_type != STP_ENTRY_POINT);
+    }
+
+    if (!found || (found && offset == 0 && wrong_type))
+    {
+        init_mrange(&range, addr, 0);
+
+        vmpa2_virt_to_string(addr, MDS_UNDEFINED, loc, NULL);
+        snprintf(name, sizeof(name), "ZZZ_%s", loc + 2);
+
+        routine = g_binary_routine_new();
+        g_binary_routine_set_name(routine, strdup(name));
+
+        g_binary_routine_set_range(routine, &range);
+
+        if (!found)
+        {
+            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            g_binary_symbol_attach_routine(symbol, routine);
+            g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
+        }
+        else _g_binary_symbol_attach_routine(symbol, routine, STP_ROUTINE);
+
+    }
+
+}
+
+
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : area   = aire représentant à contenu à parcourir.            *
@@ -489,6 +558,11 @@ bool load_code_from_mem_area(mem_area **list, size_t *count, size_t *index, cons
 
         g_arch_instruction_set_range(instr, &range);
 
+        /* Enregistrement d'un éventuel début de routine */
+
+        if (g_arch_instruction_get_flags(instr) & AIF_ROUTINE_START)
+            update_address_as_routine(format, &prev);
+
         /* Eventuel renvoi vers d'autres adresses */
 
         g_arch_instruction_call_hook(instr, IPH_LINK, ctx, format);
diff --git a/src/analysis/disass/disassembler.c b/src/analysis/disass/disassembler.c
index 37e6996..4b976c3 100644
--- a/src/analysis/disass/disassembler.c
+++ b/src/analysis/disass/disassembler.c
@@ -29,7 +29,7 @@
 #include <string.h>
 
 
-#include <i18n.h>   /////
+#include <i18n.h>
 
 
 #include "fetch.h"
@@ -299,6 +299,27 @@ G_BIN_FORMAT(g_loaded_binary_get_format(disass->binary)
 
 
 
+    /* Troisième  étape */
+
+    routines = g_binary_format_get_routines(G_BIN_FORMAT(disass->format), &routines_count);
+
+
+
+
+    //id = gtk_extended_status_bar_push(statusbar, _("Finding remaining limits..."), true);
+
+    //qsort(routines, routines_count, sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_rcompare);
+
+    limit_all_routines(disass->format, routines, routines_count, statusbar, id);
+
+    //gtk_extended_status_bar_remove(statusbar, id);
+
+    //run_plugins_on_binary(disass->binary, PGA_BINARY_BOUNDED, true);
+
+
+
+
+
     /* Septième étape */
 
     //id = gtk_extended_status_bar_push(statusbar, _("Printing disassembled code..."), true);
diff --git a/src/analysis/disass/limit.c b/src/analysis/disass/limit.c
index bb2c865..3810978 100644
--- a/src/analysis/disass/limit.c
+++ b/src/analysis/disass/limit.c
@@ -128,4 +128,29 @@ void limit_all_routines(GExeFormat *format, GBinRoutine **routines, size_t count
     if (exe_ranges != NULL)
         free(exe_ranges);
 
+
+
+
+    do
+    {
+        const mrange_t *_range;
+        vmpa2t _end;
+
+        printf("LIMIT == %zu routines\n", count);
+
+        for (i = 0; i < count; i++)
+        {
+            _range = g_binary_routine_get_range(routines[i]);
+            compute_mrange_end_addr(_range, &_end);
+
+            printf(" <LIMIT> 0x%08x <-> 0x%08x '%s'\n",
+                   (unsigned int)((get_mrange_addr(_range))->virtual),
+                   (unsigned int)_end.virtual,
+                   g_binary_routine_to_string(routines[i]));
+
+        }
+
+    } while (0);
+
+
 }
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index 45d4932..318e20b 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -21,7 +21,8 @@ D2C_MACROS =											\
     -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 SignExtend=sign_extend_armv7_imm
+    -M SignExtend=sign_extend_armv7_imm					\
+    -M SetInsFlag=g_arch_instruction_set_flag
 
 ARMV7_DEFS = 							\
 	adc_A881.d							\
diff --git a/src/arch/arm/v7/opdefs/b_A8818.d b/src/arch/arm/v7/opdefs/b_A8818.d
index 5d696a3..50bdda9 100644
--- a/src/arch/arm/v7/opdefs/b_A8818.d
+++ b/src/arch/arm/v7/opdefs/b_A8818.d
@@ -47,7 +47,7 @@
 
         //if cond == '1110' then UNDEFINED;
         //if cond == '1111' then SEE SVC;
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
@@ -75,7 +75,7 @@
     @rules {
 
         //if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
@@ -105,7 +105,7 @@
 
         //if cond<3:1> == '111' then SEE "Related encodings";
         //if InITBlock() then UNPREDICTABLE;
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
@@ -135,7 +135,7 @@
     @rules {
 
         //if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
@@ -163,7 +163,7 @@
 
     @rules {
 
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d
index c5de31e..63922dd 100644
--- a/src/arch/arm/v7/opdefs/bl_A8825.d
+++ b/src/arch/arm/v7/opdefs/bl_A8825.d
@@ -46,7 +46,7 @@
 
     @rules {
 
-        //call DefineAsReturn(1)
+        //chk_call DefineAsReturn(1)
 
     }
 
@@ -75,7 +75,7 @@
 
     @rules {
 
-        //call DefineAsReturn(1)
+        //chk_call DefineAsReturn(1)
 
     }
 
@@ -102,7 +102,7 @@
 
     @rules {
 
-        //call DefineAsReturn(1)
+        //chk_call DefineAsReturn(1)
 
     }
 
@@ -129,7 +129,7 @@
 
     @rules {
 
-        //call DefineAsReturn(1)
+        //chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/blx_A8826.d b/src/arch/arm/v7/opdefs/blx_A8826.d
index 12c55ad..c972af2 100644
--- a/src/arch/arm/v7/opdefs/blx_A8826.d
+++ b/src/arch/arm/v7/opdefs/blx_A8826.d
@@ -39,7 +39,7 @@
 
         //if m == 15 then UNPREDICTABLE;
         //if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        //call DefineAsReturn(1)
+        //chk_call DefineAsReturn(1)
 
     }
 
@@ -61,7 +61,7 @@
     @rules {
 
         //if m == 15 then UNPREDICTABLE;
-        //call DefineAsReturn(1)
+        //chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/bx_A8827.d b/src/arch/arm/v7/opdefs/bx_A8827.d
index dd06901..4856885 100644
--- a/src/arch/arm/v7/opdefs/bx_A8827.d
+++ b/src/arch/arm/v7/opdefs/bx_A8827.d
@@ -44,7 +44,7 @@
 
     @rules {
 
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
@@ -71,7 +71,7 @@
 
     @rules {
 
-        call DefineAsReturn(1)
+        chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldr_A8862.d b/src/arch/arm/v7/opdefs/ldr_A8862.d
index ecb530b..49d5c3a 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8862.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8862.d
@@ -76,7 +76,7 @@
 
         //if Rn == '1111' then SEE LDR (literal);
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -104,7 +104,7 @@
         //if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
         //if P == '0' && W == '0' then UNDEFINED;
         //if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -133,7 +133,7 @@
         //if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
         //if P == '0' && W == '0' then UNDEFINED;
         //if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldr_A8863.d b/src/arch/arm/v7/opdefs/ldr_A8863.d
index 39b9079..2360e3a 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8863.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8863.d
@@ -46,7 +46,7 @@
         //t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
         //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
         //if wback && n == t then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -76,7 +76,7 @@
         //t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
         //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
         //if wback && n == t then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldr_A8864.d b/src/arch/arm/v7/opdefs/ldr_A8864.d
index 3fbc0e3..c5b0dd0 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8864.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8864.d
@@ -70,7 +70,7 @@
     @rules {
 
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -101,7 +101,7 @@
     @rules {
 
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldr_A8865.d b/src/arch/arm/v7/opdefs/ldr_A8865.d
index 56a09fb..e8d255b 100644
--- a/src/arch/arm/v7/opdefs/ldr_A8865.d
+++ b/src/arch/arm/v7/opdefs/ldr_A8865.d
@@ -67,7 +67,7 @@
         //if Rn == '1111' then SEE LDR (literal);
         //if m IN {13,15} then UNPREDICTABLE;
         //if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/ldrb_A8867.d b/src/arch/arm/v7/opdefs/ldrb_A8867.d
index 52a50cb..2114330 100644
--- a/src/arch/arm/v7/opdefs/ldrb_A8867.d
+++ b/src/arch/arm/v7/opdefs/ldrb_A8867.d
@@ -60,7 +60,7 @@
         //if Rt == '1111' then SEE PLD;
         //if Rn == '1111' then SEE LDRB (literal);
         //if t == 13 then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -88,7 +88,7 @@
         //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;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -117,7 +117,7 @@
         //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;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/opdefs/pop_A88131.d b/src/arch/arm/v7/opdefs/pop_A88131.d
index 329b705..2663e1b 100644
--- a/src/arch/arm/v7/opdefs/pop_A88131.d
+++ b/src/arch/arm/v7/opdefs/pop_A88131.d
@@ -48,7 +48,7 @@
 
     @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>
+    @syntax "pop.W" <registers>
 
     @conv {
 
@@ -69,7 +69,7 @@
 
     @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>
+    @syntax "pop.W" <registers>
 
     @conv {
 
diff --git a/src/arch/arm/v7/opdefs/push_A88133.d b/src/arch/arm/v7/opdefs/push_A88133.d
index 0526a56..2ba7293 100644
--- a/src/arch/arm/v7/opdefs/push_A88133.d
+++ b/src/arch/arm/v7/opdefs/push_A88133.d
@@ -39,6 +39,8 @@
 
         //if BitCount(registers) < 1 then UNPREDICTABLE;
 
+        if (M == '1'); call SetInsFlag(AIF_ROUTINE_START);
+
     }
 
 }
@@ -59,6 +61,8 @@
 
         //if BitCount(registers) < 2 then UNPREDICTABLE;
 
+        if (M == '1'); call SetInsFlag(AIF_ROUTINE_START);
+
     }
 
 }
@@ -80,6 +84,8 @@
 
         //if t IN {13,15} then UNPREDICTABLE
 
+        if (Rt == '1110'); call SetInsFlag(AIF_ROUTINE_START);
+
     }
 
 }
@@ -101,6 +107,8 @@
 
         //if BitCount(register_list) < 2 then SEE STMDB / STMFD;
 
+        if (register_list & 0x4000); call SetInsFlag(AIF_ROUTINE_START);
+
     }
 
 }
@@ -123,6 +131,8 @@
 
         //if t == 13 then UNPREDICTABLE;
 
+        if (Rt == '1110'); call SetInsFlag(AIF_ROUTINE_START);
+
     }
 
 }
diff --git a/src/arch/arm/v7/opdefs/str_A88204.d b/src/arch/arm/v7/opdefs/str_A88204.d
index d4e9377..2712e1b 100644
--- a/src/arch/arm/v7/opdefs/str_A88204.d
+++ b/src/arch/arm/v7/opdefs/str_A88204.d
@@ -43,7 +43,7 @@
         //if P == '0' && W == '1' then SEE STRT;
         //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;
         //if wback && (n == 15 || n == t) then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
@@ -70,7 +70,7 @@
         //if P == '0' && W == '1' then SEE STRT;
         //if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH;
         //if wback && (n == 15 || n == t) then UNPREDICTABLE;
-        if (Rt == '1111'); call DefineAsReturn(1)
+        if (Rt == '1111'); chk_call DefineAsReturn(1)
 
     }
 
diff --git a/src/arch/arm/v7/post.c b/src/arch/arm/v7/post.c
index dfeb720..e6a6c2e 100644
--- a/src/arch/arm/v7/post.c
+++ b/src/arch/arm/v7/post.c
@@ -77,7 +77,7 @@ void post_process_branch_instructions(GArchInstruction *instr, GProcContext *con
 
             g_binary_routine_set_range(routine, &trange);
 
-            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            symbol = g_binary_symbol_new(STP_CODE_LABEL, NULL, ~0);
             g_binary_symbol_attach_routine(symbol, routine);
             g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
 
@@ -203,7 +203,7 @@ void post_process_comp_and_branch_instructions(GArchInstruction *instr, GProcCon
 
             g_binary_routine_set_range(routine, &trange);
 
-            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            symbol = g_binary_symbol_new(STP_CODE_LABEL, NULL, ~0);
             g_binary_symbol_attach_routine(symbol, routine);
             g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
 
@@ -285,7 +285,7 @@ void post_process_ldr_instructions(GArchInstruction *instr, GProcContext *contex
 
             g_binary_routine_set_range(routine, &trange);
 
-            symbol = g_binary_symbol_new(STP_ROUTINE, NULL, ~0);
+            symbol = g_binary_symbol_new(STP_CODE_LABEL, NULL, ~0);
             g_binary_symbol_attach_routine(symbol, routine);
             g_binary_format_add_symbol(G_BIN_FORMAT(format), symbol);
 
diff --git a/src/arch/instruction-int.h b/src/arch/instruction-int.h
index de9c70d..bb45f72 100644
--- a/src/arch/instruction-int.h
+++ b/src/arch/instruction-int.h
@@ -55,6 +55,7 @@ struct _GArchInstruction
     const char *suffix;                     /* Complément au nom affiché   */
     char *cached_keyword;                   /* Désignation complète        */
 
+    ArchInstrFlag flags;                    /* Informations complémentaires*/
     instr_hook_fc hooks[IPH_COUNT];         /* Traitements complémentaires */
 
     mrange_t range;                         /* Emplacement en mémoire      */
diff --git a/src/arch/instruction.c b/src/arch/instruction.c
index aced77e..0bcc739 100644
--- a/src/arch/instruction.c
+++ b/src/arch/instruction.c
@@ -151,7 +151,7 @@ static void g_arch_instruction_finalize(GArchInstruction *instr)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr  = instruction quelconque à modifier.                  *
-*                suffix =  chaîne de caractères fournie en complément.        *
+*                suffix = chaîne de caractères fournie en complément.         *
 *                                                                             *
 *  Description : Etend la désignation d'un nom d'instruction.                 *
 *                                                                             *
@@ -171,6 +171,45 @@ void g_arch_instruction_append_suffix(GArchInstruction *instr, const char *suffi
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : instr = instruction quelconque à modifier.                   *
+*                flag  = drapeau d'information complémentaire à planter.      *
+*                                                                             *
+*  Description : Ajoute une information complémentaire à une instruction.     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
+{
+    instr->flags |= flag;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction quelconque à modifier.                   *
+*                                                                             *
+*  Description : Fournit les informations complémentaires d'une instruction.  *
+*                                                                             *
+*  Retour      : Eventuels drapeaux d'information complémentaire à plantés.   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *instr)
+{
+    return instr->flags;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : instr = instruction quelconque à modifier.                   *
 *                type  = type de procédure à mémoriser.                       *
 *                hook  = fonction à appeler sur commande.                     *
 *                                                                             *
diff --git a/src/arch/instruction.h b/src/arch/instruction.h
index 12cfbb9..9251a34 100644
--- a/src/arch/instruction.h
+++ b/src/arch/instruction.h
@@ -62,6 +62,20 @@ GType g_arch_instruction_get_type(void);
 /* Etend la désignation d'un nom d'instruction. */
 void g_arch_instruction_append_suffix(GArchInstruction *, const char *);
 
+/* Drapeaux pour informations complémentaires */
+typedef enum _ArchInstrFlag
+{
+    AIF_NONE            = (0 << 0),         /* Aucune information          */
+    AIF_ROUTINE_START   = (1 << 0)          /* Début de routine            */
+
+} ArchInstrFlag;
+
+/* Ajoute une information complémentaire à une instruction. */
+void g_arch_instruction_set_flag(GArchInstruction *, ArchInstrFlag);
+
+/* Fournit les informations complémentaires d'une instruction. */
+ArchInstrFlag g_arch_instruction_get_flags(const GArchInstruction *);
+
 /**
  * La définition de "GBinFormat", utile aux traitements complémentaires, ne peut
  * se faire en incluant le fichier d'en-tête "../format/format.h", pour cause
diff --git a/src/format/format.c b/src/format/format.c
index 2808b67..2093469 100644
--- a/src/format/format.c
+++ b/src/format/format.c
@@ -192,11 +192,28 @@ void g_binary_format_add_symbol(GBinFormat *format, GBinSymbol *symbol)
 
     format->symbols[format->symbols_count - 1] = symbol;
 
-
 	qsort(format->symbols, format->symbols_count,
 		  sizeof(GBinSymbol *), (__compar_fn_t)g_binary_symbol_cmp);
 
+    switch (g_binary_symbol_get_target_type(symbol))
+    {
+        case STP_ROUTINE:
+        case STP_ENTRY_POINT:
+
+            format->routines = (GBinRoutine **)realloc(format->routines,
+                                                       ++format->routines_count * sizeof(GBinRoutine *));
+
+            format->routines[format->routines_count - 1] = g_binary_symbol_get_routine(symbol);
+            
+            qsort(format->routines, format->routines_count,
+                  sizeof(GBinRoutine *), (__compar_fn_t)g_binary_routine_compare);
 
+            break;
+
+        default:
+            break;
+
+    }
 
 }
 
diff --git a/src/format/symbol.c b/src/format/symbol.c
index d360591..c867b68 100644
--- a/src/format/symbol.c
+++ b/src/format/symbol.c
@@ -228,6 +228,7 @@ const char *g_binary_symbol_to_string(const GBinSymbol *symbol)
     {
         case STP_ROUTINE:
         case STP_ENTRY_POINT:
+        case STP_CODE_LABEL:
             result = g_binary_routine_get_name(symbol->extra.routine);
             break;
 
@@ -292,6 +293,7 @@ const char *g_binary_symbol_get_label(const GBinSymbol *symbol)
     {
         case STP_ROUTINE:
         case STP_ENTRY_POINT:
+        case STP_CODE_LABEL:
             result = g_binary_routine_get_name(symbol->extra.routine);
             break;
 
@@ -344,6 +346,7 @@ void g_binary_symbol_fix_range(GBinSymbol *symbol, const vmpa2t *full)
 
         case STP_ROUTINE:
         case STP_ENTRY_POINT:
+        case STP_CODE_LABEL:
 
             routine = g_binary_symbol_get_routine(symbol);
 
@@ -392,6 +395,7 @@ const mrange_t *g_binary_symbol_get_range(const GBinSymbol *symbol)
 
         case STP_ROUTINE:
         case STP_ENTRY_POINT:
+        case STP_CODE_LABEL:
             result = g_binary_routine_get_range(symbol->extra.routine);
             break;
 
@@ -431,6 +435,7 @@ void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt)
 *                                                                             *
 *  Paramètres  : symbol  = symbole à venir consulter.                         *
 *                routine = prototype de la fonction représentée.              *
+*                type    = (nouveau) type du symbole attaché.                 *
 *                                                                             *
 *  Description : Attache la routine associée au symbole.                      *
 *                                                                             *
@@ -440,8 +445,13 @@ void g_binary_symbol_set_alt_name(GBinSymbol *symbol, char *alt)
 *                                                                             *
 ******************************************************************************/
 
-void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine)
+void _g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine, SymbolType type)
 {
+    if (symbol->extra.routine != NULL)
+        g_object_unref(G_OBJECT(symbol->extra.routine));
+
+    symbol->type = type;
+
     symbol->extra.routine = routine;
 
 }
@@ -449,6 +459,26 @@ void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : symbol  = symbole à venir consulter.                         *
+*                routine = prototype de la fonction représentée.              *
+*                                                                             *
+*  Description : Attache la routine associée au symbole.                      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_binary_symbol_attach_routine(GBinSymbol *symbol, GBinRoutine *routine)
+{
+    _g_binary_symbol_attach_routine(symbol, routine, symbol->type);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : symbol = symbole à venir manipuler.                          *
 *                instr  = représentation du symbole associé.                  *
 *                                                                             *
diff --git a/src/format/symbol.h b/src/format/symbol.h
index fafc55f..49cde56 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -39,6 +39,7 @@ typedef enum _SymbolType
 {
     STP_DATA,                               /* Données brutes              */
     STP_ROUTINE,                            /* Simple morceau de code      */
+    STP_CODE_LABEL,                         /* Renvoi au sein de code      */
     STP_OBJECT,                             /* Objet quelconque            */
     STP_FUNCTION,                           /* Simple morceau de code      */
     STP_ENTRY_POINT,                        /* Morceau de code en entrée   */
@@ -99,6 +100,9 @@ const mrange_t *g_binary_symbol_get_range(const GBinSymbol *);
 void g_binary_symbol_set_alt_name(GBinSymbol *, char *);
 
 /* Attache la routine associée au symbole. */
+void _g_binary_symbol_attach_routine(GBinSymbol *, GBinRoutine *, SymbolType);
+
+/* Attache la routine associée au symbole. */
 void g_binary_symbol_attach_routine(GBinSymbol *, GBinRoutine *);
 
 /* Attache l'instruction associée au symbole. */
diff --git a/tools/d2c/args.c b/tools/d2c/args.c
index 616873b..1a2c287 100644
--- a/tools/d2c/args.c
+++ b/tools/d2c/args.c
@@ -73,7 +73,12 @@ struct _arg_expr_t
     union
     {
         /* CET_NAME */
-        char *name;                         /* Désignation de variable     */
+        struct
+        {
+            char *original;                 /* Désignation non transformée */
+            char *name;                     /* Désignation de variable     */
+
+        };
 
         /* CET_NUMBER */
         unsigned long number;               /* Valeur durablement définie  */
@@ -83,6 +88,7 @@ struct _arg_expr_t
         {
             char **comp_items;              /* Elements à agréger          */
             size_t comp_count;              /* Quantité de ces éléments    */
+
         };
 
         /* CET_UNARY */
@@ -156,6 +162,7 @@ arg_expr_t *build_arg_expr_from_name(char *name)
 
     result->type = CET_NAME;
 
+    result->original = strdup(name);
     result->name = make_string_lower(name);
 
     return result;
@@ -327,6 +334,7 @@ void delete_arg_expr(arg_expr_t *expr)
     switch (expr->type)
     {
         case CET_NAME:
+            free(expr->original);
             free(expr->name);
             break;
 
@@ -392,6 +400,11 @@ bool compute_arg_expr_size(const arg_expr_t *expr, const coding_bits *bits, cons
                     result = compute_conv_func_size(func, bits, list, size);
             }
 
+            /**
+             * On autorise le passage de constante inconnue par d2c mais valable pour gcc.
+             */
+            else result = true;
+
             break;
 
         case CET_COMPOSED:
@@ -590,7 +603,8 @@ bool ensure_arg_expr_content_fully_marked(arg_expr_t *expr, const coding_bits *b
         switch (sub->type)
         {
             case CET_NAME:
-                result = mark_by_name(bits, lst, sub->name);
+                /* result = */mark_by_name(bits, lst, sub->name);
+                result = true;
                 break;
 
             case CET_COMPOSED:
@@ -678,7 +692,8 @@ bool ensure_arg_expr_content_fully_declared(arg_expr_t *expr, int fd, const codi
         switch (sub->type)
         {
             case CET_NAME:
-                result = declare_by_name(f, bits, lst, *wide, sub->name);
+                /* result = */declare_by_name(f, bits, lst, *wide, sub->name);
+                result = true;
                 break;
 
             case CET_COMPOSED:
@@ -762,7 +777,8 @@ bool ensure_arg_expr_content_fully_defined(arg_expr_t *expr, int fd, const char
         switch (sub->type)
         {
             case CET_NAME:
-                result = define_by_name(f, bits, lst, info, sub->name);
+                /* result = */define_by_name(f, bits, lst, info, sub->name);
+                result = true;
                 break;
 
             case CET_COMPOSED:
@@ -824,7 +840,7 @@ bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, co
         case CET_NAME:
 
             if (!find_var_by_name(bits, list, expr->name, &field, &func))
-                result = false;
+                dprintf(fd, "%s", expr->original);
 
             else
             {
@@ -926,6 +942,9 @@ bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, co
 
             switch (expr->bin_op)
             {
+                case CBO_AND:
+                    dprintf(fd, " & ");
+                    break;
                 case CBO_EOR:
                     dprintf(fd, " ^ ");
                     break;
diff --git a/tools/d2c/args.h b/tools/d2c/args.h
index 0ad022e..d5855f4 100644
--- a/tools/d2c/args.h
+++ b/tools/d2c/args.h
@@ -49,6 +49,7 @@ typedef enum _ConvUnaryOperation
 /* Types d'opérations binaires */
 typedef enum _ConvBinaryOperation
 {
+    CBO_AND,                                /* Et logique                  */
     CBO_EOR,                                /* Ou exclusif (booléen)       */
 
     CBO_COUNT
diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y
index 9e1e034..5d83930 100644
--- a/tools/d2c/d2c_gram.y
+++ b/tools/d2c/d2c_gram.y
@@ -143,11 +143,11 @@ struct action_tmp
 
 %token SYNTAX OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
 
-%token CONV EQ OP COMMA CP NOT EOR COLON
+%token CONV EQ OP COMMA CP NOT AND_LOG EOR COLON
 
 %token HOOKS
 
-%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE CALL UNPREDICTABLE
+%token RULES IF EXPR_START EQUAL BINVAL HEXVAL EXPR_END AND THEN SEE CALL CHK_CALL UNPREDICTABLE
 
 
 %type <string> COPYRIGHT INS_NAME
@@ -170,7 +170,7 @@ struct action_tmp
 %type <string> arg_field
 
 %type <expr> rule_cond
-%type <string> BINVAL IMMVAL
+%type <string> BINVAL HEXVAL
 %type <raction> action
 
 
@@ -248,7 +248,8 @@ arg_expr : NAME                                     { $$ = build_arg_expr_from_n
 
 arg_expr_un_op : NOT { $$ = CUO_NOT; }
 
-arg_expr_bin_op : EOR { $$ = CBO_EOR; }
+arg_expr_bin_op : AND_LOG { $$ = CBO_AND; }
+                | EOR { $$ = CBO_EOR; }
 
 arg_composed : arg_field COLON arg_field    { $$ = build_composed_arg_expr($1, $3); }
              | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); }
@@ -273,14 +274,17 @@ rules_list : /* empty */
 rule : IF EXPR_START rule_cond EXPR_END THEN action { add_conditional_rule_to_coder(coder, $3, &$6); }
      | action                                       { add_conditional_rule_to_coder(coder, NULL, &$1); }
 
-rule_cond : NAME EQUAL BINVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); }
-          | NAME EQUAL IMMVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); }
+rule_cond : NAME EQUAL BINVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, true); }
+          | NAME EQUAL HEXVAL   { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, false); }
+          | NAME AND_LOG BINVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, true); }
+          | NAME AND_LOG HEXVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, false); }
           | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END
                                 { $$ = build_composed_cond_expression($2, COT_AND, $6); }
 
-action : SEE INS_DETAILS          { $$.type = CAT_SEE; $$.details = make_callable($2, false); }
-       | UNPREDICTABLE            { $$.type = CAT_UNPREDICTABLE; }
-       | CALL NAME OP arg_list CP { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; }
+action : SEE INS_DETAILS              { $$.type = CAT_SEE; $$.details = make_callable($2, false); }
+       | UNPREDICTABLE                { $$.type = CAT_UNPREDICTABLE; }
+       | CALL NAME OP arg_list CP     { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; }
+       | CHK_CALL NAME OP arg_list CP { $$.type = CAT_CHECKED_CALL; $$.callee = $2; $$.args = $4; }
 
 
 %%
diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l
index 9689b59..08562ce 100644
--- a/tools/d2c/d2c_tok.l
+++ b/tools/d2c/d2c_tok.l
@@ -39,7 +39,7 @@ void free_flex_memory(void) ;
 
 %x hooks_begin hooks_content
 
-%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see rules_action_call
+%x rules_begin rules_content rules_cond rules_cond_binval rules_cond_hexval rules_action rules_action_see rules_action_call
 
 
 %%
@@ -84,9 +84,9 @@ void free_flex_memory(void) ;
 <encoding_content>"@half"           { BEGIN(encoding_bits); return HALF; }
 <encoding_content>"@word"           { BEGIN(encoding_bits); return WORD; }
 
-<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>" "                     { }
+<encoding_bits>"\n"                    { BEGIN(encoding_content); }
+<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; }
@@ -135,8 +135,9 @@ void free_flex_memory(void) ;
 
 
 
-<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, "AND") == 0) return AND_LOG;
                                       else if (strcmp(yytext, "EOR") == 0) return EOR;
                                       else
                                       {
@@ -161,8 +162,9 @@ void free_flex_memory(void) ;
 
 
 
-<arg>[A-Za-z][A-Za-z0-9_]*     {
+<arg>[A-Za-z_][A-Za-z0-9_]*     {
                                    if (strcmp(yytext, "NOT") == 0) return NOT;
+                                   else if (strcmp(yytext, "AND") == 0) return AND_LOG;
                                    else if (strcmp(yytext, "EOR") == 0) return EOR;
                                    else
                                    {
@@ -203,18 +205,21 @@ void free_flex_memory(void) ;
 <rules_content>"see "               { BEGIN(rules_action_see); return SEE; }
 <rules_content>"unpredictable"      { return UNPREDICTABLE; }
 <rules_content>"call"               { BEGIN(rules_action_call); return CALL; }
+<rules_content>"chk_call"           { BEGIN(rules_action_call); return CHK_CALL; }
 
 <rules_content>"if"                 { BEGIN(rules_cond); return IF; }
 <rules_cond>[ ]+                    { }
 <rules_cond>"("                     { return EXPR_START; }
-<rules_cond>[A-Za-z][A-Za-z0-9]*    { d2c_lval.string = strdup(yytext); return NAME; }
+<rules_cond>[A-Za-z_][A-Za-z0-9_]*  { d2c_lval.string = strdup(yytext); return NAME; }
 <rules_cond>"=="                    { return EQUAL; }
 <rules_cond>"'"                     { BEGIN(rules_cond_binval); }
 <rules_cond_binval>[01][01]*        { d2c_lval.string = strdup(yytext); return BINVAL; }
 <rules_cond_binval>"'"              { BEGIN(rules_cond); }
-<rules_cond>[0-9][0-9]*             { d2c_lval.string = strdup(yytext); return IMMVAL; }
+<rules_cond>"0x"                     { BEGIN(rules_cond_hexval); }
+<rules_cond_hexval>[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(rules_cond); return HEXVAL; }
 <rules_cond>")"                     { return EXPR_END; }
 <rules_cond>"&&"                    { return AND; }
+<rules_cond>"&"                    { return AND_LOG; }
 
 <rules_cond>";"                     { BEGIN(rules_action); return THEN; }
 <rules_action>[ ]+                  { }
@@ -224,11 +229,12 @@ void free_flex_memory(void) ;
 
 <rules_action>"unpredictable"       { BEGIN(rules_content); return UNPREDICTABLE; }
 
-<rules_action>"call"                    { BEGIN(rules_action_call); return CALL; }
-<rules_action_call>[\t ]+               { }
-<rules_action_call>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; }
-<rules_action_call>"("                  { yy_push_state(arg); return OP; }
-<rules_action_call>[\n]                 { BEGIN(rules_content); }
+<rules_action>"call"                      { BEGIN(rules_action_call); return CALL; }
+<rules_action>"chk_call"                  { BEGIN(rules_action_call); return CHK_CALL; }
+<rules_action_call>[\t ]+                 { }
+<rules_action_call>[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; }
+<rules_action_call>"("                    { yy_push_state(arg); return OP; }
+<rules_action_call>[\n]                   { BEGIN(rules_content); }
 
 
 %%
diff --git a/tools/d2c/qckcall.c b/tools/d2c/qckcall.c
index ce9a0b2..e2e87d2 100644
--- a/tools/d2c/qckcall.c
+++ b/tools/d2c/qckcall.c
@@ -34,44 +34,44 @@
 
 
 
+/* Prépare au besoin la définition d'une macro de transtypage. */
+static char *build_cast_if_needed(const char *);
+
+
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : callee = fonction appelée à nomer.                           *
-*                args   = précise si la conversion est la dernière.           *
-*                fd     = descripteur d'un flux ouvert en écriture.           *
-*                bits   = gestionnaire des bits d'encodage.                   *
-*                list   = liste de l'ensemble des fonctions de conversion.    *
-*                pp     = pré-processeur pour les échanges de chaînes.        *
+*  Paramètres  : callee = fonction appelée à nommer.                          *
 *                                                                             *
-*  Description : Réalise un appel à une fonction liée à une instruction.      *
+*  Description : Prépare au besoin la définition d'une macro de transtypage.  *
 *                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
+*  Retour      : Macro de transtypage à libérer après usage ou NULL.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+static char *build_cast_if_needed(const char *callee)
 {
-    bool result;                            /* Bilan à remonter            */
+    char *result;                           /* Macro à retourner           */
     regex_t preg;                           /* Expression régulière        */
     int ret;                                /* Bilan d'une manipulation    */
     regmatch_t pmatch[3];                   /* Correspondances de chaînes  */
     size_t cmplen;                          /* Taille de comparaison       */
-    char *cast;                             /* Macro de transtypage        */
+
+    result = NULL;
 
     ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
     if (ret != 0)
     {
         fprintf(stderr, "Internal error: bad regular expression.\n");
-        return false;
+        return NULL;
     }
 
     ret = regexec(&preg, callee, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);
     if (ret == REG_NOMATCH)
     {
         fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callee);
-        result = false;
         goto cif_exit;
     }
 
@@ -82,29 +82,102 @@ bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const c
 
     cmplen = MAX(strlen("arch"), pmatch[2].rm_eo - pmatch[2].rm_so);
 
-    if (strncmp("arch", &callee[pmatch[2].rm_so], cmplen) == 0)
-        dprintf(fd, "\t\tif (!%s(instr, ", callee);
+    if (strncmp("arch", &callee[pmatch[2].rm_so], cmplen) != 0)
+    {
+        result = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+
+        result = make_string_upper(result);
+
+    }
+
+ cif_exit:
+
+    regfree(&preg);
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : callee = fonction appelée à nommer.                          *
+*                args   = précise si la conversion est la dernière.           *
+*                fd     = descripteur d'un flux ouvert en écriture.           *
+*                bits   = gestionnaire des bits d'encodage.                   *
+*                list   = liste de l'ensemble des fonctions de conversion.    *
+*                pp     = pré-processeur pour les échanges de chaînes.        *
+*                                                                             *
+*  Description : Réalise un appel à une fonction liée à une instruction.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+    bool result;                            /* Bilan à remonter            */
+    char *cast;                             /* Macro de transtypage        */
+
+    cast = build_cast_if_needed(callee);
+
+    if (cast == NULL)
+        dprintf(fd, "\t\t%s(instr, ", callee);
 
     else
     {
-        cast = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+        dprintf(fd, "\t\t%s(%s(instr), ", callee, cast);
+        free(cast);
+    }
 
-        cast = make_string_upper(cast);
+    result = define_arg_list(args, fd, bits, list);
 
-        dprintf(fd, "\t\tif (!%s(%s(instr), ", callee, cast);
+    dprintf(fd, ");\n");
 
-        free(cast);
+    return result;
 
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : callee = fonction appelée à nommer.                          *
+*                args   = précise si la conversion est la dernière.           *
+*                fd     = descripteur d'un flux ouvert en écriture.           *
+*                bits   = gestionnaire des bits d'encodage.                   *
+*                list   = liste de l'ensemble des fonctions de conversion.    *
+*                pp     = pré-processeur pour les échanges de chaînes.        *
+*                                                                             *
+*  Description : Réalise un appel à une fonction liée à une instruction.      *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool checked_call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+    bool result;                            /* Bilan à remonter            */
+    char *cast;                             /* Macro de transtypage        */
+
+    cast = build_cast_if_needed(callee);
+
+    if (cast == NULL)
+        dprintf(fd, "\t\tif (!%s(instr, ", callee);
+
+    else
+    {
+        dprintf(fd, "\t\tif (!%s(%s(instr), ", callee, cast);
+        free(cast);
     }
 
     result = define_arg_list(args, fd, bits, list);
 
     dprintf(fd, "))\n");
 
- cif_exit:
-
-    regfree(&preg);
-
     return result;
 
 }
diff --git a/tools/d2c/qckcall.h b/tools/d2c/qckcall.h
index 59d4adc..42aa3db 100644
--- a/tools/d2c/qckcall.h
+++ b/tools/d2c/qckcall.h
@@ -39,6 +39,9 @@
 /* Réalise un appel à une fonction liée à une instruction. */
 bool call_instr_func(const char *, const arg_list_t *, int, const coding_bits *, const conv_list *, const pre_processor *);
 
+/* Réalise un appel à une fonction liée à une instruction. */
+bool checked_call_instr_func(const char *, const arg_list_t *, int, const coding_bits *, const conv_list *, const pre_processor *);
+
 
 
 #endif  /* _TOOLS_QCKCALL_H */
diff --git a/tools/d2c/rules.c b/tools/d2c/rules.c
index 6f2e075..3101727 100644
--- a/tools/d2c/rules.c
+++ b/tools/d2c/rules.c
@@ -48,7 +48,9 @@ struct _cond_expr
         {
             char *variable;                 /* Variable manipulée          */
             CondCompType comp;              /* Type de comparaison         */
-            char *bvalue;                   /* Valeur binaire comparée     */
+            char *value;                    /* Valeur binaire comparée     */
+
+            bool is_binary;                 /* Binaire ou hexadécimal      */
 
         } simple;
 
@@ -101,9 +103,10 @@ struct _decoding_rules
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : variable = désignation de la variable à manipuler.           *
-*                comp     = type de comparaison à utiliser.                   *
-*                bvalue   = valeur binaire à comparer.                        *
+*  Paramètres  : variable  = désignation de la variable à manipuler.          *
+*                comp      = type de comparaison à utiliser.                  *
+*                value     = valeur binaire à comparer.                       *
+*                is_binary = indique la nature de la valeur transmise.        *
 *                                                                             *
 *  Description : Crée une expression conditionnelle simple.                   *
 *                                                                             *
@@ -113,7 +116,7 @@ struct _decoding_rules
 *                                                                             *
 ******************************************************************************/
 
-cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *bvalue)
+cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *value, bool is_binary)
 {
     cond_expr *result;                      /* Structure à retourner       */
 
@@ -123,7 +126,9 @@ cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char
 
     result->simple.variable = make_string_lower(variable);
     result->simple.comp = comp;
-    result->simple.bvalue = bvalue;
+    result->simple.value = value;
+
+    result->simple.is_binary = is_binary;
 
     return result;
 
@@ -178,7 +183,7 @@ static void delete_cond_expr(cond_expr *expr)
     if (expr->is_simple)
     {
         free(expr->simple.variable);
-        free(expr->simple.bvalue);
+        free(expr->simple.value);
     }
     else
     {
@@ -209,6 +214,7 @@ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bi
 {
     bool result;                            /* Bilan à renvoyer            */
     const raw_bitfield *bf;                 /* Champ de bits de définition */
+    unsigned int provided;                  /* Nombre de bits fournis      */
 
     result = true;
 
@@ -224,10 +230,15 @@ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bi
             goto wce_exit;
         }
 
-        if (get_raw_bitfield_length(bf) != strlen(expr->simple.bvalue))
+        if (expr->simple.is_binary)
+            provided = strlen(expr->simple.value);
+        else
+            provided = 4 * strlen(expr->simple.value);
+
+        if (get_raw_bitfield_length(bf) != provided)
         {
-            fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %zu).\n",
-                    expr->simple.variable, get_raw_bitfield_length(bf), strlen(expr->simple.bvalue));
+            fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %u).\n",
+                    expr->simple.variable, get_raw_bitfield_length(bf), provided);
             result = false;
             goto wce_exit;
         }
@@ -242,9 +253,15 @@ static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bi
             case CCT_DIFF:
                 dprintf(fd, " != ");
                 break;
+            case CCT_AND:
+                dprintf(fd, " & ");
+                break;
         }
 
-        dprintf(fd, "b%s", expr->simple.bvalue);
+        if (expr->simple.is_binary)
+            dprintf(fd, "b%s", expr->simple.value);
+        else
+            dprintf(fd, "0x%s", expr->simple.value);
 
     }
     else
@@ -339,6 +356,7 @@ void delete_decoding_rules(decoding_rules *rules)
                 break;
 
             case CAT_CALL:
+            case CAT_CHECKED_CALL:
                 free(rule->action.callee);
                 delete_arg_list(rule->action.args);
                 break;
@@ -406,8 +424,9 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, const rul
 bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd, const char *arch, const char *subarch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit)
 {
     bool result;                            /* Bilan à remonter            */
-    const extra_rule *rule;                 /* Règle en cours d'écriture   */
     size_t i;                               /* Boucle de parcours          */
+    const extra_rule *rule;                 /* Règle en cours d'écriture   */
+    bool multi_lines;                       /* Nécessite des accolades     */
     const char *callable;                   /* Fonction à appeler          */
 
     result = true;
@@ -419,6 +438,18 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,
         if (rule->action.type != filter)
             continue;
 
+        switch (rule->action.type)
+        {
+            case CAT_CALL:
+                multi_lines = false;
+                break;
+
+            default:
+                multi_lines = true;
+                break;
+
+        }
+
         if (rule->expr != NULL)
         {
             dprintf(fd, "\t\tif ");
@@ -427,7 +458,9 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,
             if (!result) break;
 
             dprintf(fd, "\n");
-            dprintf(fd, "\t\t{\n");
+
+            if (multi_lines)
+                dprintf(fd, "\t\t{\n");
 
         }
 
@@ -460,6 +493,20 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,
 
                 result = call_instr_func(callable, rule->action.args, fd, bits, list, pp);
 
+                break;
+
+            case CAT_CHECKED_CALL:
+
+                callable = find_macro(pp, rule->action.callee);
+
+                if (callable == NULL)
+                    callable = rule->action.callee;
+
+                if (rule->expr != NULL)
+                    dprintf(fd, "\t");
+
+                result = checked_call_instr_func(callable, rule->action.args, fd, bits, list, pp);
+
                 if (rule->expr != NULL)
                     dprintf(fd, "\t");
 
@@ -470,7 +517,7 @@ bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd,
 
         }
 
-        if (rule->expr != NULL)
+        if (rule->expr != NULL && multi_lines)
             dprintf(fd, "\t\t}\n");
 
         dprintf(fd, "\n");
diff --git a/tools/d2c/rules.h b/tools/d2c/rules.h
index 6344828..cac6a55 100644
--- a/tools/d2c/rules.h
+++ b/tools/d2c/rules.h
@@ -39,7 +39,8 @@
 typedef enum _CondCompType
 {
     CCT_EQUAL,                              /* Egalité '=='                */
-    CCT_DIFF                                /* Différence '!='             */
+    CCT_DIFF,                               /* Différence '!='             */
+    CCT_AND                                 /* Et logique '&'              */
 
 } CondCompType;
 
@@ -56,7 +57,7 @@ typedef struct _cond_expr cond_expr;
 
 
 /* Crée une expression conditionnelle simple. */
-cond_expr *build_simple_cond_expression(char *, CondCompType, char *);
+cond_expr *build_simple_cond_expression(char *, CondCompType, char *, bool);
 
 /* Crée une expression conditionnelle composée. */
 cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *);
@@ -71,7 +72,8 @@ typedef enum _CondActionType
 {
     CAT_SEE,                                /* Renvoi vers une instruction */
     CAT_UNPREDICTABLE,                      /* Cas de figure improbable    */
-    CAT_CALL                                /* Appel à une fonction C      */
+    CAT_CALL,                               /* Appel à une fonction C      */
+    CAT_CHECKED_CALL                        /* Appel à une fonction C      */
 
 } CondActionType;
 
diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c
index 9d4447d..7d65cab 100644
--- a/tools/d2c/spec.c
+++ b/tools/d2c/spec.c
@@ -324,6 +324,9 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
 
     result &= write_hook_functions(spec->hooks, fd);
 
+    result &= write_decoding_rules(spec->rules, CAT_CHECKED_CALL,
+                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
+
     result &= write_decoding_rules(spec->rules, CAT_CALL,
                                    fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
 
-- 
cgit v0.11.2-87-g4458