diff options
Diffstat (limited to 'plugins/arm/v7/operands/register.c')
-rw-r--r-- | plugins/arm/v7/operands/register.c | 279 |
1 files changed, 185 insertions, 94 deletions
diff --git a/plugins/arm/v7/operands/register.c b/plugins/arm/v7/operands/register.c index bfbaa70..fa5b887 100644 --- a/plugins/arm/v7/operands/register.c +++ b/plugins/arm/v7/operands/register.c @@ -25,20 +25,29 @@ #include <arch/operands/register-int.h> -#include <gtkext/gtkblockdisplay.h> +#include <common/sort.h> +#include <core/columns.h> +/* -------------------------- DEFINITION D'UN NOUVEAU TYPE -------------------------- */ + + +/* Informations glissées dans la structure GObject de GArchOperand */ +typedef struct _a7regop_extra_data_t +{ + operand_extra_data_t parent; /* A laisser en premier */ + + uint8_t alignment; /* Eventuel alignement */ + +} a7regop_extra_data_t; + + /* Définition d'un opérande visant un registre ARMv7 (instance) */ struct _GArmV7RegisterOperand { GRegisterOperand parent; /* Instance parente */ - unsigned int alignment; /* Eventuel alignement */ - bool has_alignment; /* Validité du champ */ - - bool write_back; /* Mise à jour du registre ? */ - }; @@ -50,6 +59,21 @@ struct _GArmV7RegisterOperandClass }; +/** + * Accès aux informations éventuellement déportées. + */ + +#if 1 //__SIZEOF_INT__ == __SIZEOF_LONG__ + +# define GET_ARMV7_REGISTER_OP_EXTRA(op) ((a7regop_extra_data_t *)&((GArchOperand *)op)->extra) + +#else + +# define GET_ARMV7_REGISTER_OP_EXTRA(op) GET_GOBJECT_EXTRA(G_OBJECT(op), a7regop_extra_data_t) + +#endif + + /* Initialise la classe des opérandes de registre ARMv7. */ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *); @@ -62,20 +86,31 @@ static void g_armv7_register_operand_dispose(GArmV7RegisterOperand *); /* Procède à la libération totale de la mémoire. */ static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *); + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Compare un opérande avec un autre. */ +static int g_armv7_register_operand_compare(const GArmV7RegisterOperand *, const GArmV7RegisterOperand *, bool); + /* Traduit un opérande en version humainement lisible. */ static void g_armv7_register_operand_print(const GArmV7RegisterOperand *, GBufferLine *); +/* Fournit l'empreinte d'un candidat à une centralisation. */ +static guint g_armv7_register_operand_hash(const GArmV7RegisterOperand *, bool); +/* Charge un contenu depuis une mémoire tampon. */ +static bool g_armv7_register_operand_load(GArmV7RegisterOperand *, GObjectStorage *, packed_buffer_t *); -/* --------------------- TRANSPOSITIONS VIA CACHE DES OPERANDES --------------------- */ +/* Sauvegarde un contenu dans une mémoire tampon. */ +static bool g_armv7_register_operand_store(GArmV7RegisterOperand *, GObjectStorage *, packed_buffer_t *); -/* Charge un opérande depuis une mémoire tampon. */ -static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *, GAsmStorage *, GBinFormat *, packed_buffer_t *); - -/* Sauvegarde un opérande dans une mémoire tampon. */ -static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *, GAsmStorage *, packed_buffer_t *); +/* ---------------------------------------------------------------------------------- */ +/* DEFINITION D'UN NOUVEAU TYPE */ +/* ---------------------------------------------------------------------------------- */ /* Indique le type défini par la GLib pour un opérande de registre ARMv7. */ @@ -106,10 +141,14 @@ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *klas operand = G_ARCH_OPERAND_CLASS(klass); + operand->compare = (operand_compare_fc)g_armv7_register_operand_compare; + operand->print = (operand_print_fc)g_armv7_register_operand_print; - operand->unserialize = (unserialize_operand_fc)g_armv7_register_operand_unserialize; - operand->serialize = (serialize_operand_fc)g_armv7_register_operand_serialize; + operand->hash = (operand_hash_fc)g_armv7_register_operand_hash; + + operand->load = (load_operand_fc)g_armv7_register_operand_load; + operand->store = (store_operand_fc)g_armv7_register_operand_store; } @@ -128,7 +167,6 @@ static void g_armv7_register_operand_class_init(GArmV7RegisterOperandClass *klas static void g_armv7_register_operand_init(GArmV7RegisterOperand *operand) { - operand->write_back = false; } @@ -173,33 +211,6 @@ static void g_armv7_register_operand_finalize(GArmV7RegisterOperand *operand) /****************************************************************************** * * -* Paramètres : operand = opérande à traiter. * -* line = ligne tampon où imprimer l'opérande donné. * -* * -* Description : Traduit un opérande en version humainement lisible. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_armv7_register_operand_print(const GArmV7RegisterOperand *operand, GBufferLine *line) -{ - GArchOperandClass *parent; /* Classe parente */ - - parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); - - parent->print(G_ARCH_OPERAND(operand), line); - - if (operand->write_back) - g_buffer_line_append_text(line, DLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL); - -} - - -/****************************************************************************** -* * * Paramètres : reg = registre déjà en place. * * * * Description : Crée un opérande visant un registre ARMv7. * @@ -238,9 +249,20 @@ GArchOperand *g_armv7_register_operand_new(GArmV7Register *reg) void g_armv7_register_operand_define_alignement(GArmV7RegisterOperand *operand, unsigned int align) { - operand->alignment = align; + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ + + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); + + LOCK_GOBJECT_EXTRA(extra); + + extra->alignment = align; - operand->has_alignment = true; + if (align > 0) + _g_arch_operand_set_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT, false); + else + _g_arch_operand_unset_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT, false); + + UNLOCK_GOBJECT_EXTRA(extra); } @@ -260,83 +282,159 @@ void g_armv7_register_operand_define_alignement(GArmV7RegisterOperand *operand, void g_armv7_register_operand_write_back(GArmV7RegisterOperand *operand, bool wback) { - operand->write_back = wback; + g_arch_operand_set_flag(G_ARCH_OPERAND(operand), A7ROF_WRITE_BACK); } + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + /****************************************************************************** * * -* Paramètres : operand = opérande représentant un registre. * +* Paramètres : a = premier opérande à consulter. * +* b = second opérande à consulter. * +* lock = précise le besoin en verrouillage. * * * -* Description : Indique si le registre est mis à jour après coup. * +* Description : Compare un opérande avec un autre. * * * -* Retour : Evolution du registre. * +* Retour : Bilan de la comparaison. * * * * Remarques : - * * * ******************************************************************************/ -bool g_armv7_register_operand_is_written_back(const GArmV7RegisterOperand *operand) +static int g_armv7_register_operand_compare(const GArmV7RegisterOperand *a, const GArmV7RegisterOperand *b, bool lock) { - bool result; /* Statut à retourner */ + int result; /* Bilan à faire remonter */ + a7regop_extra_data_t *ea; /* Données insérées à consulter*/ + a7regop_extra_data_t *eb; /* Données insérées à consulter*/ + GArchOperandClass *class; /* Classe parente normalisée */ + + ea = GET_ARMV7_REGISTER_OP_EXTRA(a); + eb = GET_ARMV7_REGISTER_OP_EXTRA(b); - result = operand->write_back; + if (lock) + { + LOCK_GOBJECT_EXTRA(ea); + LOCK_GOBJECT_EXTRA(eb); + } + + result = sort_unsigned_long(ea->alignment, eb->alignment); + + if (result == 0) + { + class = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + result = class->compare(G_ARCH_OPERAND(a), G_ARCH_OPERAND(b), false); + } + + if (lock) + { + UNLOCK_GOBJECT_EXTRA(eb); + UNLOCK_GOBJECT_EXTRA(ea); + } return result; } +/****************************************************************************** +* * +* Paramètres : operand = opérande à traiter. * +* line = ligne tampon où imprimer l'opérande donné. * +* * +* Description : Traduit un opérande en version humainement lisible. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_armv7_register_operand_print(const GArmV7RegisterOperand *operand, GBufferLine *line) +{ + GArchOperandClass *parent; /* Classe parente */ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + + parent->print(G_ARCH_OPERAND(operand), line); -/* ---------------------------------------------------------------------------------- */ -/* TRANSPOSITIONS VIA CACHE DES OPERANDES */ -/* ---------------------------------------------------------------------------------- */ + if (g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_WRITE_BACK)) + g_buffer_line_append_text(line, DLC_ASSEMBLY, "!", 1, RTT_PUNCT, NULL); + +} /****************************************************************************** * * -* 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. * +* lock = précise le besoin en verrouillage. * * * -* Description : Charge un opérande depuis 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_register_operand_unserialize(GArmV7RegisterOperand *operand, GAsmStorage *storage, GBinFormat *format, packed_buffer_t *pbuf) +static guint g_armv7_register_operand_hash(const GArmV7RegisterOperand *operand, bool lock) { - bool result; /* Bilan à retourner */ - GArchOperandClass *parent; /* Classe parente à consulter */ - uint8_t boolean; /* Valeur booléenne */ + guint result; /* Valeur à retourner */ + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ + GArchOperandClass *class; /* Classe parente normalisée */ - parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); - result = parent->unserialize(G_ARCH_OPERAND(operand), storage, format, pbuf); + if (lock) + LOCK_GOBJECT_EXTRA(extra); - if (result) - { - result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + class = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + result = class->hash(G_ARCH_OPERAND(operand), false); - if (result) - operand->has_alignment = (boolean == 1 ? true : false); + result ^= extra->alignment; - } + if (lock) + UNLOCK_GOBJECT_EXTRA(extra); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : operand = élément GLib à constuire. * +* storage = conservateur de données à manipuler ou NULL. * +* pbuf = zone tampon à lire. * +* * +* Description : Charge un contenu depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - if (result && operand->has_alignment) - result = extract_packed_buffer(pbuf, &operand->alignment, sizeof(unsigned int), true); +static bool g_armv7_register_operand_load(GArmV7RegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) +{ + bool result; /* Bilan à retourner */ + GArchOperandClass *parent; /* Classe parente à consulter */ + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ + + parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); + + result = parent->load(G_ARCH_OPERAND(operand), storage, pbuf); - if (result) + if (result && g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT)) { - result = extract_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); - if (result) - operand->write_back = (boolean == 1 ? true : false); + result = extract_packed_buffer(pbuf, &extra->alignment, sizeof(uint8_t), false); } @@ -347,11 +445,11 @@ static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand, /****************************************************************************** * * -* Paramètres : operand = opérande d'assemblage à consulter. * -* storage = mécanisme de sauvegarde à manipuler. * +* Paramètres : operand = élément GLib à consulter. * +* storage = conservateur de données à manipuler ou NULL. * * pbuf = zone tampon à remplir. * * * -* Description : Sauvegarde un opérande dans une mémoire tampon. * +* Description : Sauvegarde un contenu dans une mémoire tampon. * * * * Retour : Bilan de l'opération. * * * @@ -359,29 +457,22 @@ static bool g_armv7_register_operand_unserialize(GArmV7RegisterOperand *operand, * * ******************************************************************************/ -static bool g_armv7_register_operand_serialize(const GArmV7RegisterOperand *operand, GAsmStorage *storage, packed_buffer_t *pbuf) +static bool g_armv7_register_operand_store(GArmV7RegisterOperand *operand, GObjectStorage *storage, packed_buffer_t *pbuf) { bool result; /* Bilan à retourner */ GArchOperandClass *parent; /* Classe parente à consulter */ - uint8_t boolean; /* Valeur booléenne */ + a7regop_extra_data_t *extra; /* Données internes à manipuler*/ parent = G_ARCH_OPERAND_CLASS(g_armv7_register_operand_parent_class); - result = parent->serialize(G_ARCH_OPERAND(operand), storage, pbuf); + result = parent->store(G_ARCH_OPERAND(operand), storage, pbuf); - if (result) + if (result && g_arch_operand_has_flag(G_ARCH_OPERAND(operand), A7ROF_HAS_ALIGNMENT)) { - boolean = (operand->has_alignment ? 1 : 0); - result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); - } + extra = GET_ARMV7_REGISTER_OP_EXTRA(operand); - if (result && operand->has_alignment) - result = extend_packed_buffer(pbuf, &operand->alignment, sizeof(unsigned int), true); + result = extend_packed_buffer(pbuf, &extra->alignment, sizeof(uint8_t), false); - if (result) - { - boolean = (operand->write_back ? 1 : 0); - result = extend_packed_buffer(pbuf, &boolean, sizeof(uint8_t), false); } return result; |