/* Chrysalide - Outil d'analyse de fichiers binaires
 * instruction.c - gestion générique des instructions
 *
 * Copyright (C) 2008-2017 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  Chrysalide is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Chrysalide is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar.  If not, see .
 */
#include "instruction.h"
#include 
#include 
#include 
#include "instruction-int.h"
#include "sharing/container-int.h"
#include "../glibext/linegen-int.h"
/* Initialise la classe générique des instructions. */
static void g_arch_instruction_class_init(GArchInstructionClass *);
/* Initialise une instance d'opérande d'architecture. */
static void g_arch_instruction_init(GArchInstruction *);
/* Procède à l'initialisation de l'interface de partage. */
static void g_arch_instruction_share_interface_init(GShareContainerInterface *);
/* Procède à l'initialisation de l'interface de génération. */
static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *);
/* Supprime toutes les références externes. */
static void g_arch_instruction_dispose(GArchInstruction *);
/* Procède à la libération totale de la mémoire. */
static void g_arch_instruction_finalize(GArchInstruction *);
/* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
/* Indique le nombre de ligne prêtes à être générées. */
static size_t g_arch_instruction_count_lines(const GArchInstruction *);
/* Retrouve l'emplacement correspondant à une position donnée. */
static void g_arch_instruction_compute_addr(const GArchInstruction *, gint, vmpa2t *, size_t, size_t);
/* Détermine si le conteneur s'inscrit dans une plage donnée. */
static int g_arch_instruction_contains_addr(const GArchInstruction *, const vmpa2t *, size_t, size_t);
/* Renseigne sur les propriétés liées à un générateur. */
static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *, size_t, size_t);
/* Ajoute à un tampon GLib le contenu de l'instance spécifiée. */
static void _g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t);
/* Imprime dans une ligne de rendu le contenu représenté. */
static void g_arch_instruction_print(GArchInstruction *, GBufferLine *, size_t, size_t);
/* Indique le type défini pour une instruction d'architecture. */
G_DEFINE_TYPE_WITH_CODE(GArchInstruction, g_arch_instruction, G_TYPE_OBJECT,
                        G_IMPLEMENT_INTERFACE(G_TYPE_SHARE_CONTAINER, g_arch_instruction_share_interface_init)
                        G_IMPLEMENT_INTERFACE(G_TYPE_LINE_GENERATOR, g_arch_instruction_generator_interface_init));
/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe générique des instructions.             *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_class_init(GArchInstructionClass *klass)
{
    GObjectClass *object;                   /* Autre version de la classe  */
    GArchInstructionClass *instr;           /* Encore une autre vision...  */
    object = G_OBJECT_CLASS(klass);
    object->dispose = (GObjectFinalizeFunc/* ! */)g_arch_instruction_dispose;
    object->finalize = (GObjectFinalizeFunc)g_arch_instruction_finalize;
    instr = G_ARCH_INSTRUCTION_CLASS(klass);
    instr->print = (print_instruction_fc)_g_arch_instruction_print;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance à initialiser.                              *
*                                                                             *
*  Description : Initialise une instance d'instruction d'architecture.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_init(GArchInstruction *instr)
{
    instr->operands = NULL;
    instr->from = NULL;
    instr->to = NULL;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : iface = interface GLib à initialiser.                        *
*                                                                             *
*  Description : Procède à l'initialisation de l'interface de partage.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_share_interface_init(GShareContainerInterface *iface)
{
    iface->replace = (replace_shared_fc)g_arch_instruction_replace_operand;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : iface = interface GLib à initialiser.                        *
*                                                                             *
*  Description : Procède à l'initialisation de l'interface de génération.     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_generator_interface_init(GLineGeneratorInterface *iface)
{
    iface->count = (linegen_count_lines_fc)g_arch_instruction_count_lines;
    iface->compute = (linegen_compute_fc)g_arch_instruction_compute_addr;
    iface->contains = (linegen_contains_fc)g_arch_instruction_contains_addr;
    iface->get_flags = (linegen_get_flags_fc)g_arch_instruction_get_flags2;
    iface->print = (linegen_print_fc)g_arch_instruction_print;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
*                                                                             *
*  Description : Supprime toutes les références externes.                     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_dispose(GArchInstruction *instr)
{
    if (instr->content != NULL)
        g_object_unref(G_OBJECT(instr->content));
    G_OBJECT_CLASS(g_arch_instruction_parent_class)->dispose(G_OBJECT(instr));
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance d'objet GLib à traiter.                     *
*                                                                             *
*  Description : Procède à la libération totale de la mémoire.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_finalize(GArchInstruction *instr)
{
    G_OBJECT_CLASS(g_arch_instruction_parent_class)->finalize(G_OBJECT(instr));
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction quelconque à consulter.                  *
*                                                                             *
*  Description : Indique l'encodage d'une instruction de façon détaillée.     *
*                                                                             *
*  Retour      : Description humaine de l'encodage utilisé.                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
const char *g_arch_instruction_get_encoding(const GArchInstruction *instr)
{
    return G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_encoding(instr);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction quelconque à modifier.                   *
*                flag  = drapeau d'information complémentaire à planter.      *
*                                                                             *
*  Description : Ajoute une information complémentaire à une instruction.     *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool g_arch_instruction_set_flag(GArchInstruction *instr, ArchInstrFlag flag)
{
    instr->flags |= flag;
    return true;
}
/******************************************************************************
*                                                                             *
*  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.                     *
*                                                                             *
*  Description : Définit un traitement complémentare au désassemblage.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_set_hooks(GArchInstruction *instr, const instr_hook_fc hooks[IPH_COUNT])
{
    instr->hooks = hooks;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instruction quelconque à traiter.                  *
*                type    = type de procédure à utiliser.                      *
*                proc    = représentation de l'architecture utilisée.         *
*                context = contexte associé à la phase de désassemblage.      *
*                format  = accès aux données du binaire d'origine.            *
*                                                                             *
*  Description : Complète un désassemblage accompli pour une instruction.     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_call_hook(GArchInstruction *instr, InstrProcessHook type, GArchProcessor *proc, GProcContext *context, GExeFormat *format)
{
    assert(type < IPH_COUNT);
    if (instr->hooks != NULL && instr->hooks[type] != NULL)
        instr->hooks[type](instr, proc, context, format);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instruction quelconque à modifier.                 *
*                content = contenu binaire global à référencer.               *
*                                                                             *
*  Description : Note le contenu du sein duquel l'instruction est issue.      *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_set_global_content(GArchInstruction *instr, const GBinContent *content)
{
    g_object_ref(G_OBJECT(content));
    instr->content = content;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instruction quelconque à modifier.                 *
*                address = adresse virtuelle et/ou position physique.         *
*                length  = taille de l'instruction.                           *
*                                                                             *
*  Description : Définit la localisation d'une instruction.                   *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_set_range(GArchInstruction *instr, const mrange_t *range)
{
    copy_mrange(&instr->range, range);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instruction quelconque à consulter.                *
*                                                                             *
*  Description : Fournit la place mémoire d'une instruction.                  *
*                                                                             *
*  Retour      : Zone mémoire couverte par l'instruction.                     *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
const mrange_t *g_arch_instruction_get_range(const GArchInstruction *instr)
{
    return &instr->range;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instruction quelconque à consulter.                *
*                offset  = position physique dans le code binaire/NULL. [OUT] *
*                length  = taille de l'instruction ou NULL. [OUT]             *
*                address = adresse virtuelle ou position physique/NULL. [OUT] *
*                                                                             *
*  Description : Fournit la localisation d'une instruction.                   *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_get_location(const GArchInstruction *instr, off_t *offset, off_t *length, vmpa_t *address)
{
    //if (offset != NULL) *offset = instr->offset;
    //if (length != NULL) *length = instr->length;
    //if (address != NULL) *address = instr->address;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = instruction à consulter.                            *
*                rregs  = liste des rgistres lus. [OUT]                       *
*                rcount = nombre de registres lus. [OUT]                      *
*                wregs  = liste des rgistres écrits. [OUT]                    *
*                wcount = nombre de registres écrits. [OUT]                   *
*                                                                             *
*  Description : Liste les registres lus et écrits par l'instruction.         *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : Les compteurs de références sont à décrémenter après usage ! *
*                                                                             *
******************************************************************************/
void g_arch_instruction_get_rw_registers(const GArchInstruction *instr, GArchRegister ***rregs, size_t *rcount, GArchRegister ***wregs, size_t *wcount)
{
#if 0
    size_t i;                               /* Boucle de parcours          */
    *rregs = NULL;
    *rcount = 0;
    *wregs = NULL;
    *wcount = 0;
    instr->get_rw_regs(instr, rregs, rcount, wregs, wcount);
    for (i = 0; i < *rcount; i++)
        g_object_ref(G_OBJECT((*rregs)[i]));
    for (i = 0; i < *wcount; i++)
        g_object_ref(G_OBJECT((*wregs)[i]));
#endif
}
/* ---------------------------------------------------------------------------------- */
/*                             MANIPULATION DES OPERANDES                             */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à mettre à jour.                         *
*                                                                             *
*  Description : Verrouille les accès la liste des opérandes.                 *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_lock_operands(GArchInstruction *instr)
{
    lock_flat_array(&instr->operands);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à mettre à jour.                         *
*                                                                             *
*  Description : Déverrouille les accès la liste des opérandes.               *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_unlock_operands(GArchInstruction *instr)
{
    unlock_flat_array(&instr->operands);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instance à mettre à jour.                          *
*                operand = instruction à venir associer.                      *
*                                                                             *
*  Description : Attache un opérande supplémentaire à une instruction.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_attach_extra_operand(GArchInstruction *instr, GArchOperand *operand)
{
    g_arch_instruction_lock_operands(instr);
    add_item_to_flat_array(&instr->operands, &operand, sizeof(GArchOperand *));
    g_arch_instruction_unlock_operands(instr);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance à consulter.                                *
*                                                                             *
*  Description : Indique la quantité d'opérandes présents dans l'instruction. *
*                                                                             *
*  Retour      : Nombre d'opérandes attachés.                                 *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
size_t _g_arch_instruction_count_operands(const GArchInstruction *instr)
{
    size_t result;                          /* Décompte à retourner        */
    result = count_flat_array_items(instr->operands);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance à mettre à jour.                            *
*                index = indice de l'opérande concernée.                      *
*                                                                             *
*  Description : Fournit un opérande donné d'une instruction.                 *
*                                                                             *
*  Retour      : Opérande trouvée ou NULL si aucune.                          *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
GArchOperand *_g_arch_instruction_get_operand(const GArchInstruction *instr, size_t index)
{
    GArchOperand *result;                   /* Opérande à retourner        */
    GArchOperand **ptr;                     /* Adresse dans le tableau     */
    ptr = get_flat_array_item(instr->operands, index, sizeof(GArchOperand *));
    result = *ptr;
    /* TODO : incrémenter la référence ! */
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance à mettre à jour.                            *
*                old   = ancien opérande à remplacer.                         *
*                new   = nouvel opérande à intégrer.                          *
*                                                                             *
*  Description : Remplace un opérande d'une instruction par un autre.         *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
{
    bool result;                            /* Bilan à retourner           */
    g_arch_instruction_lock_operands(instr);
    result = _g_arch_instruction_replace_operand(instr, old, new);
    g_arch_instruction_unlock_operands(instr);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instance à mettre à jour.                            *
*                old   = ancienne opérande à détacher.                        *
*                new   = nouvelle opérande à attacher.                        *
*                                                                             *
*  Description : Remplace un opérande d'une instruction par un autre.         *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool _g_arch_instruction_replace_operand(GArchInstruction *instr, GArchOperand *old, GArchOperand *new)
{
    bool result;                            /* Bilan à retourner           */
    size_t count;                           /* Nombre d'opérandes en place */
    size_t i;                               /* Boucle de parcours          */
    GArchOperand *op;                       /* Opérande à manipuler        */
    result = false;
    count = _g_arch_instruction_count_operands(instr);
    for (i = 0; i < count; i++)
    {
        op = _g_arch_instruction_get_operand(instr, i);
        if (op == old)
        {
            result = true;
            break;
        }
    }
    if (result)
    {
        rpl_item_in_flat_array(instr->operands, i, &new, sizeof(GArchOperand *));
        //g_object_unref(G_OBJECT(old));
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = instance à mettre à jour.                           *
*                target = instruction à venir dissocier.                      *
*                                                                             *
*  Description : Détache un opérande liée d'une instruction.                  *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void _g_arch_instruction_detach_operand(GArchInstruction *instr, GArchOperand *target)
{
    size_t count;                           /* Nombre d'opérandes en place */
    size_t i;                               /* Boucle de parcours          */
    GArchOperand *op;                       /* Opérande à manipuler        */
    count = _g_arch_instruction_count_operands(instr);
    for (i = 0; i < count; i++)
    {
        op = _g_arch_instruction_get_operand(instr, i);
        if (op == target)
            break;
    }
    rem_item_from_flat_array(&instr->operands, i, sizeof(GArchOperand *));
    g_object_unref(G_OBJECT(target));
}
/* ---------------------------------------------------------------------------------- */
/*                     DEFINITION DES LIAISONS ENTRE INSTRUCTIONS                     */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction à mettre à jour.                         *
*                src   = sélection de l'extrémité à traiter.                  *
*                lock  = indique le sens du verrouillage à mener.             *
*                                                                             *
*  Description : Met à disposition un encadrement des accès aux liens.        *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_lock_unlock_links(GArchInstruction *instr, bool src, bool lock)
{
    flat_array_t **array;                   /* Choix du tableau ciblé      */
    array = (src ? &instr->from : &instr->to);
    if (lock)
        lock_flat_array(array);
    else
        unlock_flat_array(array);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                dest  = ligne visée par la liaison (côté destination).       *
*                                                                             *
*  Description : Détermine si un lien est déjà établi entre deux instructions.*
*                                                                             *
*  Retour      : Bilan de l'état actuel des liaisons.                         *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool g_arch_instruction_has_link_to(GArchInstruction *instr, const GArchInstruction *dest)
{
    bool result;                            /* Bilan à retourner           */
    size_t count;                           /* Nombre de liens à parcourir */
    size_t i;                               /* Boucle de parcours          */
    instr_link_t *dlink;                    /* Définition de destination   */
    result = false;
    g_arch_instruction_lock_dest(instr);
    count = g_arch_instruction_count_destinations(instr);
    for (i = 0; i < count && !result; i++)
    {
        dlink = g_arch_instruction_get_destination(instr, i);
        result = (dlink->linked == dest);
    }
    g_arch_instruction_unlock_dest(instr);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                dest  = ligne visée par la liaison (côté destination).       *
*                type  = type de lien à construire.                           *
*                                                                             *
*  Description : Etablit un lien entre deux instructions.                     *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void g_arch_instruction_link_with(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType type)
{
    instr_link_t new_src;                   /* Nouveau lien à définir #1   */
    instr_link_t new_dst;                   /* Nouveau lien à définir #2   */
    /* Côté destination */
    new_src.linked = instr;
    new_src.type = type;
    /* Côté point de départ */
    new_dst.linked = dest;
    new_dst.type = type;
    /* Ajout dans le respect d'une cohérence globale */
    g_arch_instruction_lock_src(dest);
    g_arch_instruction_lock_dest(instr);
    add_item_to_flat_array(&dest->from, &new_src, sizeof(instr_link_t));
    add_item_to_flat_array(&instr->to, &new_dst, sizeof(instr_link_t));
    g_arch_instruction_unlock_dest(instr);
    g_arch_instruction_unlock_src(dest);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                dest  = ligne visée par la liaison (côté destination).       *
*                old   = ancien type de lien construit.                       *
*                new   = nouveau type de lien à construire.                   *
*                                                                             *
*  Description : Change la nature d'un lien entre deux instructions.          *
*                                                                             *
*  Retour      : true pour une mise à jour réussie, false sinon.              *
*                                                                             *
*  Remarques   : Le verrou doit être posé sur les destinations de 'instr'.    *
*                                                                             *
******************************************************************************/
bool g_arch_instruction_change_link(GArchInstruction *instr, GArchInstruction *dest, InstructionLinkType old, InstructionLinkType new)
{
    bool result;                            /* Bilan à retourner           */
    size_t count;                           /* Raccourci pour la lecture   */
    size_t i;                               /* Boucle de parcours          */
    instr_link_t *slink;                    /* Définition de source        */
    instr_link_t *dlink;                    /* Définition de destination   */
    result = false;
    g_arch_instruction_lock_src(dest);
    /* Côté destination */
    count = g_arch_instruction_count_sources(dest);
    for (i = 0; i < count; i++)
    {
        slink = g_arch_instruction_get_source(dest, i);
        if (slink->linked == instr && slink->type == old)
            break;
    }
    if (i == count)
        goto gaicl_exit;
    /* Côté point de départ */
    count = g_arch_instruction_count_destinations(instr);
    for (i = 0; i < count; i++)
    {
        dlink = g_arch_instruction_get_destination(instr, i);
        if (dlink->linked == dest && dlink->type == old)
            break;
    }
    if (i == count)
        goto gaicl_exit;
    /* Si les deux extrémités sont raccord... */
    slink->type = new;
    dlink->type = new;
    result = true;
 gaicl_exit:
    g_arch_instruction_unlock_src(dest);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                                                                             *
*  Description : Fournit la quantité d'instructions pointant vers une autre.  *
*                                                                             *
*  Retour      : Nombre de ces origines.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
size_t g_arch_instruction_count_sources(const GArchInstruction *instr)
{
    size_t result;                          /* Nombre de liens à renvoyer  */
    result = count_flat_array_items(instr->from);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                index = indice de l'élément à retrouver.                     *
*                                                                             *
*  Description : Fournit les détails d'une origine d'une instruction donnée.  *
*                                                                             *
*  Retour      : Lien déterminé vers une instruction d'origine.               *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
instr_link_t *g_arch_instruction_get_source(GArchInstruction *instr, size_t index)
{
    instr_link_t *result;                   /* Détails présents à renvoyer */
    result = get_flat_array_item(instr->from, index, sizeof(instr_link_t));
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                                                                             *
*  Description : Donne le nombre d'instructions non naturellement suivantes.  *
*                                                                             *
*  Retour      : Nombre de ces destinations.                                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
size_t g_arch_instruction_count_destinations(const GArchInstruction *instr)
{
    size_t result;                          /* Nombre de liens à renvoyer  */
    result = count_flat_array_items(instr->to);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                index = indice de l'élément à retrouver.                     *
*                                                                             *
*  Description : Fournit les détails d'une destination d'une instruction.     *
*                                                                             *
*  Retour      : Lien déterminé vers une instruction de destination.          *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
instr_link_t *g_arch_instruction_get_destination(GArchInstruction *instr, size_t index)
{
    instr_link_t *result;                   /* Détails présents à renvoyer */
    result = get_flat_array_item(instr->to, index, sizeof(instr_link_t));
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = instruction dont les informations sont à consulter.  *
*                type  = type de lien recherché.                              *
*                                                                             *
*  Description : Fournit la destination d'une instruction et d'un type donné. *
*                                                                             *
*  Retour      : Instruction de destination trouvée ou NULL.                  *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
GArchInstruction *g_arch_instruction_get_given_destination(GArchInstruction *instr, InstructionLinkType type)
{
    GArchInstruction *result;               /* Résultat à remonter         */
    size_t count;                           /* Nombre de liens à parcourir */
    size_t i;                               /* Boucle de parcours          */
    instr_link_t *dest;                     /* Destination à étudier       */
    result = NULL;
    g_arch_instruction_lock_dest(instr);
    count = g_arch_instruction_count_destinations(instr);
    for (i = 0; i < count && result == NULL; i++)
    {
        dest = g_arch_instruction_get_destination(instr, i);
        if (dest->type == type)
        {
            result = dest->linked;
            g_object_ref(G_OBJECT(result));
        }
    }
    g_arch_instruction_unlock_dest(instr);
    return result;
}
/* ---------------------------------------------------------------------------------- */
/*                       CONVERSIONS DU FORMAT DES INSTRUCTIONS                       */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = instruction d'assemblage à consulter.               *
*                syntax = type de représentation demandée.                    *
*                                                                             *
*  Description : Fournit le nom humain de l'instruction manipulée.            *
*                                                                             *
*  Retour      : Mot clef de bas niveau.                                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
const char *g_arch_instruction_get_keyword(GArchInstruction *instr, AsmSyntax syntax)
{
    const char *result;                     /* Désignation à retourner     */
    result = G_ARCH_INSTRUCTION_GET_CLASS(instr)->get_keyword(instr, syntax);
    return result;
}
/* ---------------------------------------------------------------------------------- */
/*                          OFFRE DE CAPACITES DE GENERATION                          */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : instr = générateur à consulter.                              *
*                                                                             *
*  Description : Indique le nombre de ligne prêtes à être générées.           *
*                                                                             *
*  Retour      : Nombre de lignes devant apparaître au final.                 *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static size_t g_arch_instruction_count_lines(const GArchInstruction *instr)
{
    return 1;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = générateur à consulter.                             *
*                x      = position géographique sur la ligne concernée.       *
*                addr   = position en mémoire à analyser.                     *
*                index  = indice de cette même ligne dans le tampon global.   *
*                repeat = indice d'utilisations successives du générateur.    *
*                                                                             *
*  Description : Retrouve l'emplacement correspondant à une position donnée.  *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_compute_addr(const GArchInstruction *instr, gint x, vmpa2t *addr, size_t index, size_t repeat)
{
    copy_vmpa(addr, get_mrange_addr(&instr->range));
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = générateur à consulter.                             *
*                addr   = position en mémoire à analyser.                     *
*                index  = indice de cette même ligne dans le tampon global.   *
*                repeat = indice d'utilisations successives du générateur.    *
*                                                                             *
*  Description : Détermine si le conteneur s'inscrit dans une plage donnée.   *
*                                                                             *
*  Retour      : Bilan de la détermination, utilisable en comparaisons.       *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static int g_arch_instruction_contains_addr(const GArchInstruction *instr, const vmpa2t *addr, size_t index, size_t repeat)
{
    int result;                             /* Conclusion à retourner      */
    result = cmp_mrange_with_vmpa(&instr->range, addr);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = générateur à consulter.                             *
*                index  = indice de cette même ligne dans le tampon global.   *
*                repeat = indice d'utilisations successives du générateur.    *
*                                                                             *
*  Description : Renseigne sur les propriétés liées à un générateur.          *
*                                                                             *
*  Retour      : Propriétés particulières associées.                          *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static BufferLineFlags g_arch_instruction_get_flags2(const GArchInstruction *instr, size_t index, size_t repeat)
{
    return BLF_HAS_CODE;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr   = instruction d'assemblage à représenter.            *
*                buffer  = espace où placer ledit contenu.                    *
*                msize   = taille idéale des positions et adresses;           *
*                content = contenu binaire global à venir lire.               *
*                syntax  = type de représentation demandée.                   *
*                                                                             *
*  Description : Ajoute à un tampon GLib le contenu de l'instance spécifiée.  *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void _g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat)
{
    const char *key;                        /* Mot clef principal          */
    size_t klen;                            /* Taille de ce mot clef       */
    size_t count;                           /* Nombre d'opérandes en place */
    size_t i;                               /* Boucle de parcours          */
    GArchOperand *op;                       /* Opérande à manipuler        */
    g_buffer_line_fill_vmpa(line, get_mrange_addr(&instr->range), MDS_32_BITS_UNSIGNED, MDS_32_BITS_UNSIGNED);
    g_buffer_line_fill_content(line, instr->content, &instr->range, VMPA_NO_PHYSICAL);
    /* Instruction proprement dite */
    key = g_arch_instruction_get_keyword(instr, 0/*, syntax*/);
    klen = strlen(key);
    g_buffer_line_append_text(line, BLC_ASSEMBLY_HEAD, key, klen, RTT_INSTRUCTION, NULL);
    /* Liste des opérandes */
    g_arch_instruction_lock_operands(instr);
    count = _g_arch_instruction_count_operands(instr);
    if (count > 0)
    {
        op = _g_arch_instruction_get_operand(instr, 0);
        g_arch_operand_print(op, line, 0/*syntax*/);
        for (i = 1; i < count; i++)
        {
            g_buffer_line_append_text(line, BLC_ASSEMBLY, ",", 1, RTT_PUNCT, NULL);
            g_buffer_line_append_text(line, BLC_ASSEMBLY, " ", 1, RTT_RAW, NULL);
            op = _g_arch_instruction_get_operand(instr, i);
            g_arch_operand_print(op, line, 0/*syntax*/);
        }
    }
    g_arch_instruction_unlock_operands(instr);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : instr  = générateur à utiliser pour l'impression.            *
*                line   = ligne de rendu à compléter.                         *
*                index  = indice de cette même ligne dans le tampon global.   *
*                repeat = indice d'utilisations successives du générateur.    *
*                                                                             *
*  Description : Imprime dans une ligne de rendu le contenu représenté.       *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static void g_arch_instruction_print(GArchInstruction *instr, GBufferLine *line, size_t index, size_t repeat)
{
    G_ARCH_INSTRUCTION_GET_CLASS(instr)->print(instr, line, index, repeat);
}