summaryrefslogtreecommitdiff
path: root/plugins/arm/v7/operands/maccess.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/arm/v7/operands/maccess.c')
-rw-r--r--plugins/arm/v7/operands/maccess.c530
1 files changed, 254 insertions, 276 deletions
diff --git a/plugins/arm/v7/operands/maccess.c b/plugins/arm/v7/operands/maccess.c
index 07f38a6..77d031f 100644
--- a/plugins/arm/v7/operands/maccess.c
+++ b/plugins/arm/v7/operands/maccess.c
@@ -29,24 +29,26 @@
#include <stdlib.h>
-#include <arch/operand-int.h>
#include <common/cpp.h>
-#include <common/sort.h>
+#include <core/columns.h>
#include <core/logs.h>
-#include <gtkext/gtkblockdisplay.h>
+#include "../operand-int.h"
+
+
+
+/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */
+
/* Définition d'un opérande offrant un accès à la mémoire depuis une base (instance) */
struct _GArmV7MAccessOperand
{
- GArchOperand parent; /* Instance parente */
+ GArmV7Operand parent; /* Instance parente */
GArchOperand *base; /* Base de l'accès en mémoire */
GArchOperand *offset; /* Décalage pour l'adresse */
GArchOperand *shift; /* Décalage supplémentaire ? */
- bool post_indexed; /* Position du décalage */
- bool write_back; /* Mise à jour de la base */
};
@@ -54,7 +56,7 @@ struct _GArmV7MAccessOperand
/* Définition d'un opérande offrant un accès à la mémoire depuis une base (classe) */
struct _GArmV7MAccessOperandClass
{
- GArchOperandClass parent; /* Classe parente */
+ GArmV7OperandClass parent; /* Classe parente */
};
@@ -71,8 +73,13 @@ static void g_armv7_maccess_operand_dispose(GArmV7MAccessOperand *);
/* Procède à la libération totale de la mémoire. */
static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *);
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
/* Compare un opérande avec un autre. */
-static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *, const GArmV7MAccessOperand *);
+static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *, const GArmV7MAccessOperand *, bool);
/* Détermine le chemin conduisant à un opérande interne. */
static char *g_armv7_maccess_operand_find_inner_operand_path(const GArmV7MAccessOperand *, const GArchOperand *);
@@ -83,21 +90,24 @@ static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const G
/* Traduit un opérande en version humainement lisible. */
static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *, GBufferLine *);
+/* Fournit une liste de candidats embarqués par un candidat. */
+static GArchOperand **g_armv7_maccess_operand_list_inner_instances(const GArmV7MAccessOperand *, size_t *);
+/* Met à jour une liste de candidats embarqués par un candidat. */
+static void g_armv7_maccess_operand_update_inner_instances(GArmV7MAccessOperand *, GArchOperand **, size_t);
-/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */
+/* Fournit l'empreinte d'un candidat à une centralisation. */
+static guint g_armv7_maccess_operand_hash(const GArmV7MAccessOperand *, bool);
-/* Charge un opérande depuis une mémoire tampon. */
-static bool g_armv7_maccess_operand_unserialize(GArmV7MAccessOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *);
-
-/* Sauvegarde un opérande dans une mémoire tampon. */
-static bool g_armv7_maccess_operand_serialize(const GArmV7MAccessOperand *, GAsmStorage *, packed_buffer_t *);
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'UN NOUVEAU TYPE */
+/* ---------------------------------------------------------------------------------- */
/* Indique le type défini par la GLib pour un accès à la mémoire depuis une base. */
-G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARCH_OPERAND);
+G_DEFINE_TYPE(GArmV7MAccessOperand, g_armv7_maccess_operand, G_TYPE_ARMV7_OPERAND);
/******************************************************************************
@@ -130,8 +140,12 @@ static void g_armv7_maccess_operand_class_init(GArmV7MAccessOperandClass *klass)
operand->print = (operand_print_fc)g_armv7_maccess_operand_print;
- operand->unserialize = (unserialize_operand_fc)g_armv7_maccess_operand_unserialize;
- operand->serialize = (serialize_operand_fc)g_armv7_maccess_operand_serialize;
+ operand->list_inner = (operand_list_inners_fc)g_armv7_maccess_operand_list_inner_instances;
+ operand->update_inner = (operand_update_inners_fc)g_armv7_maccess_operand_update_inner_instances;
+ operand->hash = (operand_hash_fc)g_armv7_maccess_operand_hash;
+
+ operand->load = g_arch_operand_load_generic_fixed_3;
+ operand->store = g_arch_operand_store_generic_fixed;
}
@@ -171,14 +185,9 @@ static void g_armv7_maccess_operand_init(GArmV7MAccessOperand *operand)
static void g_armv7_maccess_operand_dispose(GArmV7MAccessOperand *operand)
{
- if (operand->base != NULL)
- g_object_unref(G_OBJECT(operand->base));
-
- if (operand->offset != NULL)
- g_object_unref(G_OBJECT(operand->offset));
-
- if (operand->shift != NULL)
- g_object_unref(G_OBJECT(operand->shift));
+ g_clear_object(&operand->base);
+ g_clear_object(&operand->offset);
+ g_clear_object(&operand->shift);
G_OBJECT_CLASS(g_armv7_maccess_operand_parent_class)->dispose(G_OBJECT(operand));
@@ -206,8 +215,109 @@ static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *operand)
/******************************************************************************
* *
-* Paramètres : a = premier opérande à consulter. *
-* b = second opérande à consulter. *
+* Paramètres : base = représente le registre de la base d'accès. *
+* offset = détermine le décalage entre l'adresse et la base. *
+* shift = opération de décalage pour jouer sur le décalage. *
+* post = précise la forme donnée au décalage à appliquer. *
+* wback = indique une mise à jour de la base après usage. *
+* *
+* Description : Crée un accès à la mémoire depuis une base et un décalage. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_new(GArchOperand *base, GArchOperand *offset, GArchOperand *shift, bool post, bool wback)
+{
+ GArmV7MAccessOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_ARMV7_MACCESS_OPERAND, NULL);
+
+ result->base = base;
+ result->offset = offset;
+ result->shift = shift;
+
+ if (post)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7MAOF_POST_INDEXED);
+
+ if (wback)
+ g_arch_operand_set_flag(G_ARCH_OPERAND(result), A7MAOF_WRITE_BACK);
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit la base d'un accès à la mémoire. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_get_base(const GArmV7MAccessOperand *operand)
+{
+ return operand->base;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit le décalage d'un accès à la mémoire depuis la base. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_get_offset(const GArmV7MAccessOperand *operand)
+{
+ return operand->offset;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Founit le décalage d'un décalage pour un accès mémoire. *
+* *
+* Retour : Opérande en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_armv7_maccess_operand_get_shift(const GArmV7MAccessOperand *operand)
+{
+ return operand->shift;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : a = premier opérande à consulter. *
+* b = second opérande à consulter. *
+* lock = précise le besoin en verrouillage. *
* *
* Description : Compare un opérande avec un autre. *
* *
@@ -217,25 +327,24 @@ static void g_armv7_maccess_operand_finalize(GArmV7MAccessOperand *operand)
* *
******************************************************************************/
-static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *a, const GArmV7MAccessOperand *b)
+static int g_armv7_maccess_operand_compare(const GArmV7MAccessOperand *a, const GArmV7MAccessOperand *b, bool lock)
{
int result; /* Bilan à faire remonter */
+ GArchOperandClass *class; /* Classe parente normalisée */
result = g_arch_operand_compare(a->base, b->base);
- if (result != 0) goto gamoc_done;
-
- result = sort_pointer(a->offset, b->offset, (__compar_fn_t)g_arch_operand_compare);
- if (result != 0) goto gamoc_done;
-
- result = sort_pointer(a->shift, b->shift, (__compar_fn_t)g_arch_operand_compare);
- if (result != 0) goto gamoc_done;
- result = sort_boolean(a->post_indexed, b->post_indexed);
- if (result != 0) goto gamoc_done;
+ if (result)
+ result = g_arch_operand_compare(a->offset, b->offset);
- result = sort_boolean(a->write_back, b->write_back);
+ if (result)
+ result = g_arch_operand_compare(a->shift, b->shift);
- gamoc_done:
+ if (result == 0)
+ {
+ class = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
+ result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false);
+ }
return result;
@@ -392,11 +501,17 @@ static GArchOperand *g_armv7_maccess_operand_get_inner_operand_from_path(const G
static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, GBufferLine *line)
{
+ bool post; /* Forme post-indexée ? */
+ bool wback; /* Ecriture après coup ? */
+
+ post = g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7MAOF_POST_INDEXED);
+ wback = g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7MAOF_WRITE_BACK);
+
g_buffer_line_append_text(line, DLC_ASSEMBLY, "[", 1, RTT_HOOK, NULL);
g_arch_operand_print(operand->base, line);
- if (operand->post_indexed)
+ if (post)
g_buffer_line_append_text(line, DLC_ASSEMBLY, "]", 1, RTT_HOOK, NULL);
if (operand->offset != NULL)
@@ -417,10 +532,10 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, G
}
- if (!operand->post_indexed)
+ if (!post)
g_buffer_line_append_text(line, DLC_ASSEMBLY, "]", 1, RTT_HOOK, NULL);
- if (operand->post_indexed && operand->write_back)
+ if (post && wback)
g_buffer_line_append_text(line, DLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL);
}
@@ -428,306 +543,169 @@ static void g_armv7_maccess_operand_print(const GArmV7MAccessOperand *operand, G
/******************************************************************************
* *
-* Paramètres : base = représente le registre de la base d'accès. *
-* offset = détermine le décalage entre l'adresse et la base. *
-* shift = opération de décalage pour jouer sur le décalage. *
-* post = précise la forme donnée au décalage à appliquer. *
-* wback = indique une mise à jour de la base après usage. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Crée un accès à la mémoire depuis une base et un décalage. *
+* Description : Fournit une liste de candidats embarqués par un candidat. *
* *
-* Retour : Opérande mis en place. *
+* Retour : Liste de candidats internes ou NULL si aucun. *
* *
* Remarques : - *
* *
******************************************************************************/
-GArchOperand *g_armv7_maccess_operand_new(GArchOperand *base, GArchOperand *offset, GArchOperand *shift, bool post, bool wback)
+static GArchOperand **g_armv7_maccess_operand_list_inner_instances(const GArmV7MAccessOperand *operand, size_t *count)
{
- GArmV7MAccessOperand *result; /* Structure à retourner */
-
- result = g_object_new(G_TYPE_ARMV7_MACCESS_OPERAND, NULL);
-
- result->base = base;
- result->offset = offset;
- result->shift = shift;
-
- result->post_indexed = post;
- result->write_back = wback;
-
- return G_ARCH_OPERAND(result);
-
-}
+ GArchOperand **result; /* Instances à retourner */
+ size_t idx; /* Indice de traitement */
+ *count = 1;
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit la base d'un accès à la mémoire. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_maccess_operand_get_base(const GArmV7MAccessOperand *operand)
-{
- return operand->base;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit le décalage d'un accès à la mémoire depuis la base. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_maccess_operand_get_offset(const GArmV7MAccessOperand *operand)
-{
- return operand->offset;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Founit le décalage d'un décalage pour un accès mémoire. *
-* *
-* Retour : Opérande en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GArchOperand *g_armv7_maccess_operand_get_shift(const GArmV7MAccessOperand *operand)
-{
- return operand->shift;
+ if (operand->offset != NULL)
+ (*count)++;
-}
+ if (operand->shift != NULL)
+ (*count)++;
+ result = malloc(*count * sizeof(GArchOperand *));
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique si le décalage est post-indexé. *
-* *
-* Retour : Statut des opérations menées. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ result[0] = operand->base;
+ g_object_ref(G_OBJECT(result[0]));
-bool g_armv7_maccess_operand_is_post_indexed(const GArmV7MAccessOperand *operand)
-{
- return operand->post_indexed;
+ if (operand->offset != NULL)
+ {
+ result[1] = operand->offset;
+ g_object_ref(G_OBJECT(result[1]));
-}
+ idx = 2;
+ }
+ else
+ idx = 1;
-/******************************************************************************
-* *
-* Paramètres : operand = opérande à consulter. *
-* *
-* Description : Indique si la base est mise à jour après usage. *
-* *
-* Retour : Statut des opérations menées. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
+ if (operand->shift != NULL)
+ {
+ result[idx] = operand->shift;
+ g_object_ref(G_OBJECT(result[idx]));
+ }
-bool g_armv7_maccess_operand_has_to_write_back(const GArmV7MAccessOperand *operand)
-{
- return operand->write_back;
+ return result;
}
-
-/* ---------------------------------------------------------------------------------- */
-/* TRANSPOSITIONS VIA CACHE DES OPERANDES */
-/* ---------------------------------------------------------------------------------- */
-
-
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à constituer. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* format = format binaire chargé associé à l'architecture. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* instances = liste de candidats internes devenus singletons. *
+* count = quantité d'instances à l'unicité internes. *
* *
-* Description : Charge un opérande depuis une mémoire tampon. *
+* Description : Met à jour une liste de candidats embarqués par un candidat. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_maccess_operand_unserialize(GArmV7MAccessOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf)
+static void g_armv7_maccess_operand_update_inner_instances(GArmV7MAccessOperand *operand, GArchOperand **instances, size_t count)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- GArchOperand *subop; /* Sous-opérande à intégrer */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
-
- result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf);
-
- if (result)
- {
- subop = g_arch_operand_load(storage, format, pbuf);
-
- if (subop == NULL)
- result = false;
-
- else
- operand->base = subop;
-
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result && boolean == 1)
- {
- subop = g_arch_operand_load(storage, format, pbuf);
+#ifndef NDEBUG
+ size_t idx_check; /* Décompte des éléments utiles*/
+#endif
+ size_t i; /* Boucle de parcours */
- if (subop == NULL)
- result = false;
+#ifndef NDEBUG
+ idx_check = 1;
- else
- operand->offset = subop;
+ if (operand->offset != NULL)
+ (idx_check)++;
- }
+ if (operand->shift != NULL)
+ (idx_check)++;
- }
+ assert(count == idx_check);
+#endif
- if (result)
+ for (i = 0; i < count; i++)
{
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result && boolean == 1)
+ switch (i)
{
- subop = g_arch_operand_load(storage, format, pbuf);
-
- if (subop == NULL)
- result = false;
-
- else
- operand->shift = subop;
+ case 0:
+ g_clear_object(&operand->base);
+ operand->base = instances[i];
+ break;
+
+ case 1:
+ if (operand->offset != NULL)
+ {
+ g_clear_object(&operand->offset);
+ operand->offset = instances[i];
+ }
+ else
+ {
+ assert(count == 2);
+
+ g_clear_object(&operand->shift);
+ operand->shift = instances[i];
+
+ }
+ break;
+
+ case 2:
+ g_clear_object(&operand->shift);
+ operand->shift = instances[i];
+ break;
}
- }
-
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->post_indexed = (boolean == 1 ? true : false);
+ g_object_ref(G_OBJECT(instances[i]));
}
- if (result)
- {
- result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
-
- if (result)
- operand->write_back = (boolean == 1 ? true : false);
-
- }
-
- return result;
-
}
/******************************************************************************
* *
-* Paramètres : operand = opérande d'assemblage à consulter. *
-* storage = mécanisme de sauvegarde à manipuler. *
-* pbuf = zone tampon à remplir. *
+* Paramètres : operand = objet dont l'instance se veut unique. *
+* lock = précise le besoin en verrouillage. *
* *
-* Description : Sauvegarde un opérande dans une mémoire tampon. *
+* Description : Fournit l'empreinte d'un candidat à une centralisation. *
* *
-* Retour : Bilan de l'opération. *
+* Retour : Empreinte de l'élément représenté. *
* *
* Remarques : - *
* *
******************************************************************************/
-static bool g_armv7_maccess_operand_serialize(const GArmV7MAccessOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf)
+static guint g_armv7_maccess_operand_hash(const GArmV7MAccessOperand *operand, bool lock)
{
- bool result; /* Bilan à retourner */
- GArchOperandClass *parent; /* Classe parente à consulter */
- uint8_t boolean; /* Valeur booléenne */
-
- parent = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
-
- result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf);
-
- if (result)
- result = g_arch_operand_store(operand->base, storage, pbuf);
-
- if (result)
- {
- if (operand->offset == NULL)
- result = extend_packed_buffer(pbuf, (uint8_t []) { 0 }, sizeof(uint8_t), false);
-
- else
- {
- result = extend_packed_buffer(pbuf, (uint8_t []) { 1 }, sizeof(uint8_t), false);
+ guint result; /* Valeur à retourner */
+ operand_extra_data_t *extra; /* Données insérées à consulter*/
+ GArchOperandClass *class; /* Classe parente normalisée */
+ size_t count; /* Quantité d'éléments utiles */
- if (result)
- result = g_arch_operand_store(operand->offset, storage, pbuf);
+ extra = GET_ARCH_OP_EXTRA(G_ARCH_OPERAND(operand));
- }
+ if (lock)
+ LOCK_GOBJECT_EXTRA(extra);
- }
+ class = G_ARCH_OPERAND_CLASS(g_armv7_maccess_operand_parent_class);
+ result = class->hash(G_ARCH_OPERAND(operand), false);
- if (result)
- {
- if (operand->shift == NULL)
- result = extend_packed_buffer(pbuf, (uint8_t []) { 0 }, sizeof(uint8_t), false);
+ count = 1;
- else
- {
- result = extend_packed_buffer(pbuf, (uint8_t []) { 1 }, sizeof(uint8_t), false);
-
- if (result)
- result = g_arch_operand_store(operand->shift, storage, pbuf);
-
- }
+ if (operand->offset != NULL)
+ (count)++;
- }
+ if (operand->shift != NULL)
+ (count)++;
- if (result)
- {
- boolean = (operand->post_indexed ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ result ^= count;
- if (result)
- {
- boolean = (operand->write_back ? 1 : 0);
- result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false);
- }
+ if (lock)
+ UNLOCK_GOBJECT_EXTRA(extra);
return result;