diff options
Diffstat (limited to 'src/arch/instruction.c')
-rw-r--r-- | src/arch/instruction.c | 335 |
1 files changed, 334 insertions, 1 deletions
diff --git a/src/arch/instruction.c b/src/arch/instruction.c index be7ff37..e2d8d2a 100644 --- a/src/arch/instruction.c +++ b/src/arch/instruction.c @@ -30,6 +30,7 @@ #include "instruction-int.h" +#include "storage.h" #include "../glibext/linegen-int.h" @@ -51,6 +52,17 @@ static void g_arch_instruction_finalize(GArchInstruction *); +/* -------------------- CONSERVATION SUR DISQUE DES INSTRUCTIONS -------------------- */ + + +/* Charge une instruction depuis une mémoire tampon. */ +static bool g_arch_instruction_unserialize(GArchInstruction *, GAsmStorage *, GBinFormat *, packed_buffer *); + +/* Sauvegarde une instruction dans une mémoire tampon. */ +static bool g_arch_instruction_serialize(GArchInstruction *, GAsmStorage *, packed_buffer *); + + + /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */ @@ -103,6 +115,9 @@ static void g_arch_instruction_class_init(GArchInstructionClass *klass) instr = G_ARCH_INSTRUCTION_CLASS(klass); + instr->unserialize = (unserialize_instruction_fc)g_arch_instruction_unserialize; + instr->serialize = (serialize_instruction_fc)g_arch_instruction_serialize; + instr->print = (print_instruction_fc)_g_arch_instruction_print; } @@ -1055,7 +1070,7 @@ char *g_arch_instruction_build_tooltip(const GArchInstruction *instr) * Remarques : - * * * ******************************************************************************/ - + const char *g_arch_instruction_get_description(const GArchInstruction *instr) { const char *result; /* Description à retourner */ @@ -1069,6 +1084,324 @@ const char *g_arch_instruction_get_description(const GArchInstruction *instr) /* ---------------------------------------------------------------------------------- */ +/* CONSERVATION SUR DISQUE DES INSTRUCTIONS */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_unserialize(GArchInstruction *instr, GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + packed_buffer op_pbuf; /* Tampon des données à écrire */ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ + off64_t pos; /* Position dans le flux */ + GArchOperand *op; /* Opérande à traiter */ + instr_link_t link; /* Lien vers une instruction */ + packed_buffer ins_pbuf; /* Tampon des données à écrire */ + + result = unpack_mrange(&instr->range, pbuf); + + if (result) + { + init_packed_buffer(&op_pbuf); + + result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + result = extract_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + if (result) + result = g_asm_storage_load_operand_data(storage, &op_pbuf, pos); + + if (result) + { + op = g_arch_operand_load(storage, format, &op_pbuf); + result = (op != NULL); + } + + if (result) + g_arch_instruction_attach_extra_operand(instr, op); + + } + + exit_packed_buffer(&op_pbuf); + + } + + bool unserialize_link(instr_link_t *lk) + { + bool status; /* Bilan d'une conservation */ + phys_t lk_phys; /* Position physique courante */ + + status = extract_packed_buffer(pbuf, &lk_phys, sizeof(phys_t), true); + + if (status) + { + lk->linked = g_asm_storage_get_instruction_at(storage, format, lk_phys, &ins_pbuf); + status = (lk->linked != NULL); + } + + if (status) + { + status = extract_packed_buffer(pbuf, &lk->type, sizeof(InstructionLinkType), true); + + if (!status) + g_object_unref(G_OBJECT(lk->linked)); + + } + + return status; + + } + + if (result) + { + init_packed_buffer(&ins_pbuf); + + result = extract_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + result = unserialize_link(&link); + + if (result) + { + g_arch_instruction_link_with(instr, link.linked, link.type); + g_object_unref(G_OBJECT(link.linked)); + } + + } + + exit_packed_buffer(&ins_pbuf); + + } + + if (result) + result = extract_packed_buffer(pbuf, &instr->uid, sizeof(itid_t), true); + + if (result) + result = extract_packed_buffer(pbuf, &instr->flags, sizeof(ArchInstrFlag), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : storage = mécanisme de sauvegarde à manipuler. * +* format = format binaire chargé associé à l'architecture. * +* pbuf = zone tampon à remplir. * +* * +* Description : Charge une instruction depuis une mémoire tampon. * +* * +* Retour : Instruction d'assemblage constitué ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GArchInstruction *g_arch_instruction_load(GAsmStorage *storage, GBinFormat *format, packed_buffer *pbuf) +{ + GArchInstruction *result; /* Instance à retourner */ + bool status; /* Bilan du chargement */ + + result = G_ARCH_INSTRUCTION(g_asm_storage_create_object(storage, pbuf)); + + if (result != NULL) + { + status = G_ARCH_INSTRUCTION_GET_CLASS(result)->unserialize(result, storage, format, pbuf); + + if (!status) + { + g_object_unref(G_OBJECT(result)); + result = NULL; + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_arch_instruction_serialize(GArchInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + packed_buffer op_pbuf; /* Tampon des données à écrire */ + size_t count; /* Nombre d'éléments à traiter */ + size_t i; /* Boucle de parcours */ + GArchOperand *op; /* Opérande à traiter */ + off64_t pos; /* Position dans le flux */ + size_t kept; /* Nombre de liens conservés */ + instr_link_t *link; /* Lien vers une instruction */ + + result = pack_mrange(&instr->range, pbuf); + + if (result) + { + init_packed_buffer(&op_pbuf); + + g_arch_instruction_lock_operands(instr); + + count = _g_arch_instruction_count_operands(instr); + + result = extend_packed_buffer(pbuf, &count, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + op = _g_arch_instruction_get_operand(instr, i); + + result = g_arch_operand_store(op, storage, &op_pbuf); + + if (result) + result = g_asm_storage_store_operand_data(storage, &op_pbuf, &pos); + + if (result) + result = extend_packed_buffer(pbuf, &pos, sizeof(off64_t), true); + + g_object_unref(G_OBJECT(op)); + + } + + g_arch_instruction_unlock_operands(instr); + + exit_packed_buffer(&op_pbuf); + + } + + bool serialize_link(const instr_link_t *lk) + { + bool status; /* Bilan d'une conservation */ + const mrange_t *range; /* Emplacement d'une instruct° */ + phys_t lk_phys; /* Position physique courante */ + + if (lk->type == ILT_REF) + status = true; + + else + { + range = g_arch_instruction_get_range(lk->linked); + + lk_phys = get_phy_addr(get_mrange_addr(range)); + + status = extend_packed_buffer(pbuf, &lk_phys, sizeof(phys_t), true); + + if (status) + status = extend_packed_buffer(pbuf, &lk->type, sizeof(InstructionLinkType), true); + + } + + return status; + + } + + if (result) + { + g_arch_instruction_lock_dest(instr); + + count = g_arch_instruction_count_destinations(instr); + + /** + * Le type de lien ILT_REF n'est mis en place que lors de la création + * d'opérandes de type G_TYPE_TARGET_OPERAND, et sera donc remis en place + * dynamiquement lors de la restauration de ces derniers. + */ + + kept = 0; + + for (i = 0; i < count && result; i++) + { + link = g_arch_instruction_get_destination(instr, i); + + if (link->type != ILT_REF) + kept++; + + } + + result = extend_packed_buffer(pbuf, &kept, sizeof(size_t), true); + + for (i = 0; i < count && result; i++) + { + link = g_arch_instruction_get_destination(instr, i); + result = serialize_link(link); + } + + g_arch_instruction_unlock_dest(instr); + + } + + if (result) + result = extend_packed_buffer(pbuf, &instr->uid, sizeof(itid_t), true); + + if (result) + result = extend_packed_buffer(pbuf, &instr->flags, sizeof(ArchInstrFlag), true); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = instruction d'assemblage à consulter. * +* storage = mécanisme de sauvegarde à manipuler. * +* pbuf = zone tampon à remplir. * +* * +* Description : Sauvegarde une instruction dans une mémoire tampon. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_arch_instruction_store(GArchInstruction *instr, GAsmStorage *storage, packed_buffer *pbuf) +{ + bool result; /* Bilan à retourner */ + + result = g_asm_storage_store_object_gtype(storage, G_OBJECT(instr), pbuf); + + if (result) + result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->serialize(instr, storage, pbuf); + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ /* OFFRE DE CAPACITES DE GENERATION */ /* ---------------------------------------------------------------------------------- */ |