summaryrefslogtreecommitdiff
path: root/src/decomp/instr
diff options
context:
space:
mode:
Diffstat (limited to 'src/decomp/instr')
-rw-r--r--src/decomp/instr/ite.c107
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;
+ }
+
+}