From 7a8628a53e55641e31737fe10b6ed7b5498e84a7 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 27 Nov 2015 22:23:05 +0000
Subject: Fixed binary string format in immediate operands.

git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@612 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
---
 ChangeLog                   | 16 +++++++++
 src/arch/arm/v7/processor.c |  5 ---
 src/arch/immediate.c        | 87 ++++++++++++++++++++++++++++++++++++---------
 src/arch/raw.c              | 57 -----------------------------
 src/arch/raw.h              |  3 --
 src/common/asm.c            | 38 ++++++++++++++++++++
 src/common/asm.h            |  3 ++
 7 files changed, 127 insertions(+), 82 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index fc012e7..ed92b9f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 15-11-27  Cyrille Bagard <nocbos@gmail.com>
 
+	* src/arch/arm/v7/processor.c:
+	Typo.
+
+	* src/arch/immediate.c:
+	Fix binary string format in immediate operands.
+
+	* src/arch/raw.c:
+	* src/arch/raw.h:
+	Remove old code.
+
+	* src/common/asm.c:
+	* src/common/asm.h:
+	Compute the first set bit in 64bit words.
+
+15-11-27  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/analysis/disass/fetch.c:
 	Disable old code.
 
diff --git a/src/arch/arm/v7/processor.c b/src/arch/arm/v7/processor.c
index 7a1dd5a..195b87c 100644
--- a/src/arch/arm/v7/processor.c
+++ b/src/arch/arm/v7/processor.c
@@ -289,11 +289,6 @@ static GArchInstruction *g_armv7_processor_disassemble(const GArmV7Processor *pr
 
     }
 
-    /*
-    else
-        result = g_raw_instruction_new_array_old(data, MDS_32_BITS, 1, pos, end,
-                                             G_ARCH_PROCESSOR(proc)->endianness);
-    */
     return result;
 
 }
diff --git a/src/arch/immediate.c b/src/arch/immediate.c
index 3720bff..4c9ea84 100644
--- a/src/arch/immediate.c
+++ b/src/arch/immediate.c
@@ -32,6 +32,7 @@
 
 
 #include "operand-int.h"
+#include "../common/asm.h"
 #include "../common/extstr.h"
 #include "../format/format.h"
 
@@ -739,12 +740,15 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt
     const char *zpad;                       /* Remplissage par des zéros   */
     const char *lmod;                       /* Modification de longueur    */
     const char *conv;                       /* Opérateur de conversion     */
-    char format[16];                        /* Format d'impression final   */
+    char binval[65];                        /* Conversion intégrée         */
+    unsigned int max;                       /* Indice du plus fort bit     */
+    unsigned int i;                         /* Boucle de parcours #1       */
+    char format[16 + 65];                   /* Format d'impression final   */
 
     static const char *zpad_defs[] = { "", "02", "04", "08", "016" };
     static const char *lmod_defs[] = { "hh", "hh", "h", "", __PRI64_PREFIX };
-    static const char *conv_si_defs[] = { "c", "d", "x", "o" };
-    static const char *conv_us_defs[] = { "c", "u", "x", "o" };
+    static const char *conv_si_defs[] = { "", "o", "d", "x", "c" };
+    static const char *conv_us_defs[] = { "", "o", "u", "x", "c" };
 
     result = 0; /* Gcc... */
 
@@ -762,28 +766,77 @@ static size_t g_imm_operand_to_string(const GImmOperand *operand, AsmSyntax synt
         suffix = "";
     }
 
-    /* Préfix de forme '0x' ou '0' */
-    if (operand->display == IOD_HEX)
-        alternate = "0x";
-    else if (operand->display == IOD_OCT)
-        alternate = "0";
-    else
-        alternate = "";
+    /* Préfix de forme '0x', 'b' ou '0' */
+    switch (operand->display)
+    {
+        case IOD_BIN:
+            alternate = "b";
+            break;
+        case IOD_OCT:
+            alternate = "0";
+            break;
+        case IOD_HEX:
+            alternate = "0x";
+            break;
+        default:
+            alternate = "";
+            break;
+    }
 
     /* Drapeau de remplissage ? */
-    if (operand->display == IOD_HEX)
-        zpad = (operand->zpad ? zpad_defs[range] : "");
-    else
-        zpad = "";
+    switch (operand->display)
+    {
+        case IOD_BIN:
+        case IOD_CHAR:
+            zpad = "";
+            break;
+        default:
+            zpad = (operand->zpad ? zpad_defs[range] : "");
+            break;
+    }
 
     /* Modification de la longueur fournie */
     lmod = lmod_defs[range];
 
     /* Spécification de la conversion */
-    if (MDS_IS_SIGNED(operand->size))
-        conv = conv_si_defs[operand->display];
+
+    if (operand->display != IOD_BIN)
+    {
+        if (MDS_IS_SIGNED(operand->size))
+            conv = conv_si_defs[operand->display];
+        else
+            conv = conv_us_defs[operand->display];
+
+    }
     else
-        conv = conv_us_defs[operand->display];
+    {
+        if (operand->zpad)
+            max = range * 8 + 1;
+        else
+        {
+            if (!msb_64(operand->raw, &max))
+            {
+                conv = "0";
+                max = 0;
+            }
+            else
+                max++;
+        }
+
+        if (max > 0)
+        {
+            conv = binval;
+
+            for (i = max; i > 0; i--)
+                binval[max - i] = (operand->raw & (1 << (i - 1)) ? '1' : '0');
+
+            binval[max] = '\0';
+
+        }
+
+    }
+
+    /* Impression finale */
 
     snprintf(format, sizeof(format), "%s%s%%%s%s%s%s", prefix, alternate, zpad, lmod, conv, suffix);
 
diff --git a/src/arch/raw.c b/src/arch/raw.c
index 41f46c1..a9fc3df 100644
--- a/src/arch/raw.c
+++ b/src/arch/raw.c
@@ -243,63 +243,6 @@ GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *addr, MemoryDat
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : data   = flux de données à analyser.                         *
-*                size   = taille de chacun des éléments à représenter.        *
-*                count  = nombre de ces éléments.                             *
-*                addr   = position courante dans ce flux. [OUT]               *
-*                end    = limite des données à analyser.                      *
-*                endian = ordre des bits dans la source.                      *
-*                                                                             *
-*  Description : Crée une instruction de type 'db/dw/etc' étendue.            *
-*                                                                             *
-*  Retour      : Instruction mise en place.                                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-GArchInstruction *g_raw_instruction_new_array_old(const bin_t *data, MemoryDataSize size, size_t count, vmpa2t *addr, off_t end, SourceEndian endian)
-{
-    GArchInstruction *result;               /* Instruction à retourner     */
-    vmpa2t old;                             /* Sauvegarde de la position   */
-    size_t i;                               /* Boucle de parcours          */
-    GArchOperand *operand;                  /* Octet non décodé à afficher */
-    mrange_t range;                         /* Couverture de l'instruction */
-
-    /* Par soucis de cohérence */
-    if (count == 0) return NULL;
-
-    result = g_object_new(G_TYPE_RAW_INSTRUCTION, NULL);
-
-    copy_vmpa(&old, addr);
-
-    for (i = 0; i < count; i++)
-    {
-        operand = g_imm_operand_new_from_data_old(size, data, addr, end, endian);
-        if (operand == NULL) goto grina_error;
-
-        g_imm_operand_pad(G_IMM_OPERAND(operand), true);
-
-        g_arch_instruction_attach_extra_operand(result, operand);
-    }
-
-    init_mrange(&range, &old, compute_vmpa_diff(addr, &old));
-
-    g_arch_instruction_set_range(result, &range);
-
-    return result;
-
- grina_error:
-
-    g_object_unref(G_OBJECT(result));
-
-    return NULL;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : content = flux de données à analyser.                        *
 *                size    = taille de chacun des éléments à représenter.       *
 *                count   = nombre de ces éléments.                            *
diff --git a/src/arch/raw.h b/src/arch/raw.h
index 6712b81..459ade2 100644
--- a/src/arch/raw.h
+++ b/src/arch/raw.h
@@ -56,9 +56,6 @@ GType g_raw_instruction_get_type(void);
 GArchInstruction *g_raw_instruction_new_from_value(const vmpa2t *, MemoryDataSize, uint64_t);
 
 /* Crée une instruction de type 'db/dw/etc' étendue. */
-GArchInstruction *g_raw_instruction_new_array_old(const bin_t *, MemoryDataSize, size_t, vmpa2t *, off_t, SourceEndian);
-
-/* Crée une instruction de type 'db/dw/etc' étendue. */
 GArchInstruction *g_raw_instruction_new_array(const GBinContent *, MemoryDataSize, size_t, vmpa2t *, SourceEndian);
 
 /* Marque l'instruction comme ne contenant que du bourrage. */
diff --git a/src/common/asm.c b/src/common/asm.c
index 597013a..0e92938 100644
--- a/src/common/asm.c
+++ b/src/common/asm.c
@@ -65,3 +65,41 @@ bool msb_32(uint32_t v, unsigned int *p)
     return true;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : v = valeur quelconque sur 64 bits.                           *
+*                p = position du premier bit à 1 (poids fort). [OUT]          *
+*                                                                             *
+*  Description : Détermine l'indice du premier bit à 1, côté gauche.          *
+*                                                                             *
+*  Retour      : true si le nombre est différent de zéro, false sinon.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool msb_64(uint64_t v, unsigned int *p)
+{
+    static const unsigned int bval[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
+
+    /* S'il n'y a aucun bit à 1... */
+    if (v == 0) return false;
+
+    /**
+     * Cf. msb_32().
+     */
+
+    *p = 0;
+
+    if (v & 0xffffffff00000000ull) { *p += 32 / 1; v >>= 32 / 1; }
+    if (v & 0x00000000ffff0000ull) { *p += 32 / 2; v >>= 32 / 2; }
+    if (v & 0x000000000000ff00ull) { *p += 32 / 4; v >>= 32 / 4; }
+    if (v & 0x00000000000000f0ull) { *p += 32 / 8; v >>= 32 / 8; }
+
+    *p += bval[v];
+
+    return true;
+
+}
diff --git a/src/common/asm.h b/src/common/asm.h
index 047d8db..5207bf7 100644
--- a/src/common/asm.h
+++ b/src/common/asm.h
@@ -33,6 +33,9 @@
 /* Détermine l'indice du premier bit à 1, côté gauche. */
 bool msb_32(uint32_t, unsigned int *);
 
+/* Détermine l'indice du premier bit à 1, côté gauche. */
+bool msb_64(uint64_t, unsigned int *);
+
 
 
 #endif  /* _COMMON_ASM_H */
-- 
cgit v0.11.2-87-g4458