diff options
Diffstat (limited to 'src/decomp/instr')
-rw-r--r-- | src/decomp/instr/ite.c | 107 |
1 files changed, 88 insertions, 19 deletions
diff --git a/src/decomp/instr/ite.c b/src/decomp/instr/ite.c index c12d314..1abf61c 100644 --- a/src/decomp/instr/ite.c +++ b/src/decomp/instr/ite.c @@ -72,6 +72,12 @@ static void g_ite_instruction_class_init(GITEInstructionClass *); /* Initialise une instance d'aiguillage du flux d'exécution. */ static void g_ite_instruction_init(GITEInstruction *); +/* Visite un ensemble hiérarchique d'instructions décompilées. */ +static bool g_ite_instruction_visit(GITEInstruction *, dec_instr_visitor_cb, DecInstrVisitFlags, void *); + +/* Remplace une instruction décompilée par une autre. */ +static bool g_ite_instruction_replace(GITEInstruction *, GDecInstruction *, GDecInstruction *); + /* Imprime pour l'écran un version humaine d'une instruction. */ static GBufferLine *g_ite_instruction_print(const GITEInstruction *, GCodeBuffer *, GBufferLine *, GLangOutput *); @@ -117,6 +123,8 @@ static void g_ite_instruction_init(GITEInstruction *expr) instr = G_DEC_INSTRUCTION(expr); + instr->visit = (dec_instr_visit_fc)g_ite_instruction_visit; + instr->replace = (dec_instr_replace_fc)g_ite_instruction_replace; instr->print = (dec_instr_print_fc)g_ite_instruction_print; } @@ -153,34 +161,62 @@ GDecInstruction *g_ite_instruction_new(GDecExpression *cond, vmpa_t if_true, vmp /****************************************************************************** * * -* Paramètres : cond = expression fixant le choix de l'aiguillage. * -* true_branch = instructions si la condition est vérifiée. * -* false_branch = instructions si la cond. n'est pas vérifiée. * +* Paramètres : instr = première instruction à venir visiter. * +* callback = procédure à appeler à chaque instruction visitée. * +* flags = moments des appels à réaliser en retour. * +* data = données quelconques associées au visiteur. * * * -* Description : Détermine le corps des différentes branches possibles. * +* Description : Visite un ensemble hiérarchique d'instructions décompilées. * * * -* Retour : - * +* Retour : true si le parcours a été jusqu'à son terme, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -void g_ite_instruction_set_branches(GITEInstruction *expr, GDecInstruction *true_branch, GDecInstruction *false_branch) +static bool g_ite_instruction_visit(GITEInstruction *instr, dec_instr_visitor_cb callback, DecInstrVisitFlags flags, void *data) { + bool result; /* Bilan à retourner */ - if (true_branch == NULL) - { - expr->inverse = true; + result = g_dec_instruction_visit(G_DEC_INSTRUCTION(instr->cond), callback, flags, data); - expr->true_branch = false_branch; - expr->false_branch = true_branch; + if (result) + result = g_dec_instruction_visit(instr->true_branch, callback, flags, data); - } - else - { - expr->true_branch = true_branch; - expr->false_branch = false_branch; - } + if (result && instr->false_branch != NULL) + result = g_dec_instruction_visit(instr->false_branch, callback, flags, data); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : instr = première instruction à venir ausculter. * +* old = instruction décompilée à venir remplacer. * +* new = instruction décompilée à utiliser dorénavant. * +* * +* Description : Remplace une instruction décompilée par une autre. * +* * +* Retour : true si un remplacement a été effectué, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_ite_instruction_replace(GITEInstruction *instr, GDecInstruction *old, GDecInstruction *new) +{ + bool result; /* Bilan à retourner */ + + result = g_dec_instruction_replace(G_DEC_INSTRUCTION(instr->cond), old, new); + + result |= g_dec_instruction_replace(instr->true_branch, old, new); + + if (instr->false_branch != NULL) + result |= g_dec_instruction_replace(instr->false_branch, old, new); + + return result; } @@ -212,8 +248,7 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBu result = g_dec_instruction_print(G_DEC_INSTRUCTION(expr->cond), buffer, line, output); - if (expr->true_branch != NULL) - result = g_dec_instruction_print(expr->true_branch, buffer, result, output); + result = g_dec_instruction_print(expr->true_branch, buffer, result, output); if (expr->false_branch != NULL) { @@ -224,3 +259,37 @@ static GBufferLine *g_ite_instruction_print(const GITEInstruction *expr, GCodeBu return result; } + + +/****************************************************************************** +* * +* Paramètres : cond = expression fixant le choix de l'aiguillage. * +* true_branch = instructions si la condition est vérifiée. * +* false_branch = instructions si la cond. n'est pas vérifiée. * +* * +* Description : Détermine le corps des différentes branches possibles. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_ite_instruction_set_branches(GITEInstruction *expr, GDecInstruction *true_branch, GDecInstruction *false_branch) +{ + + if (true_branch == NULL) + { + expr->inverse = true; + + expr->true_branch = false_branch; + expr->false_branch = true_branch; + + } + else + { + expr->true_branch = true_branch; + expr->false_branch = false_branch; + } + +} |