summaryrefslogtreecommitdiff
path: root/src/arch/mips/operand.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-05-31 20:58:20 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-05-31 20:58:20 (GMT)
commit8724afdc73e0ddad86f46de1a3fbe0254575a76e (patch)
treede666b66e154c6c6453807d3fa4272efb6877a91 /src/arch/mips/operand.c
parent0b7d7f26c745ff0f52e9e483a0980351368ca824 (diff)
Supported a new architecture (MIPS).
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@67 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/arch/mips/operand.c')
-rw-r--r--src/arch/mips/operand.c649
1 files changed, 649 insertions, 0 deletions
diff --git a/src/arch/mips/operand.c b/src/arch/mips/operand.c
new file mode 100644
index 0000000..68599a4
--- /dev/null
+++ b/src/arch/mips/operand.c
@@ -0,0 +1,649 @@
+
+/* OpenIDA - Outil d'analyse de fichiers binaires
+ * operand.h - prototypes pour la gestion des operandes de l'architecture MIPS
+ *
+ * Copyright (C) 2008 Cyrille Bagard
+ *
+ * This file is part of OpenIDA.
+ *
+ * OpenIDA 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.
+ *
+ * OpenIDA 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 <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "operand.h"
+
+
+#include <stdarg.h>
+
+
+#include "../immediate.h"
+#include "../operand-int.h"
+#include "../../common/endianness.h"
+#include "../../common/extstr.h"
+
+
+
+/* ------------------------ COQUILLE VIDE POUR OPERANDE MIPS ------------------------ */
+
+
+/* Définition d'un opérande de la MIPS (instance) */
+struct _GMipsOperand
+{
+ GArchOperand parent; /* Instance parente */
+
+};
+
+
+/* Définition d'un opérande de la MIPS (classe) */
+struct _GMipsOperandClass
+{
+ GArchOperandClass parent; /* Classe parente */
+
+};
+
+
+/* Initialise la classe des opérandes MIPS de base. */
+static void g_mips_operand_class_init(GMipsOperandClass *);
+
+/* Initialise une instance d'opérande de base pour MIPS. */
+static void g_mips_operand_init(GMipsOperand *);
+
+
+
+/* ----------------------- OPERANDES OFFRANT UN REGISTRE MIPS ----------------------- */
+
+
+/* Définition d'un opérande visant un registre MIPS (instance) */
+struct _GMipsRegisterOperand
+{
+ GMipsOperand parent; /* Instance parente */
+
+ mips_register *reg; /* Registre représenté */
+
+};
+
+
+/* Définition d'un opérande visant un registre MIPS (classe) */
+struct _GMipsRegisterOperandClass
+{
+ GMipsOperandClass parent; /* Classe parente */
+
+};
+
+
+/* Initialise la classe des opérandes de registre MIPS. */
+static void g_mips_register_operand_class_init(GMipsRegisterOperandClass *);
+
+/* Initialise une instance d'opérande de registre MIPS. */
+static void g_mips_register_operand_init(GMipsRegisterOperand *);
+
+/* Traduit un opérande en version humainement lisible. */
+static char *g_mips_register_operand_get_text(const GMipsRegisterOperand *, const exe_format *, AsmSyntax);
+
+
+
+/* -------------------------- OPERANDES DE CONTENU MEMOIRE -------------------------- */
+
+
+/* Définition d'un opérande MIPS pointeur un contenu mémoire (instance) */
+struct _GMipsMemContentOperand
+{
+ GMipsOperand parent; /* Instance parente */
+
+ mips_register *base; /* Base de la lecture */
+ GArchOperand *offset; /* Décallage à appliquer */
+
+};
+
+
+/* Définition d'un opérande MIPS pointeur un contenu mémoire (classe) */
+struct _GMipsMemContentOperandClass
+{
+ GMipsOperandClass parent; /* Classe parente */
+
+};
+
+
+/* Initialise la classe des opérandes MIPS de contenu mémoire. */
+static void g_mips_mem_content_operand_class_init(GMipsMemContentOperandClass *);
+
+/* Initialise une instance d'opérande MIPS de contenu mémoire. */
+static void g_mips_mem_content_operand_init(GMipsMemContentOperand *);
+
+/* Traduit un opérande en version humainement lisible. */
+static char *g_mips_mem_content_operand_get_text(const GMipsMemContentOperand *, const exe_format *, AsmSyntax);
+
+
+
+/* ----------------------------- OPERANDES DE DECALLAGE ----------------------------- */
+
+
+/* Définition d'un opérande MIPS de décallage (instance) */
+struct _GMipsOffsetOperand
+{
+ GMipsOperand parent; /* Instance parente */
+
+ GArchOperand *offset; /* Décallage à appliquer */
+
+};
+
+
+/* Définition d'un opérande MIPS de décallage (classe) */
+struct _GMipsOffsetOperandClass
+{
+ GMipsOperandClass parent; /* Classe parente */
+
+};
+
+
+/* Initialise la classe des opérandes MIPS de décallage. */
+static void g_mips_offset_operand_class_init(GMipsOffsetOperandClass *);
+
+/* Initialise une instance d'opérande MIPS de décallage. */
+static void g_mips_offset_operand_init(GMipsOffsetOperand *);
+
+/* Traduit un opérande en version humainement lisible. */
+static char *g_mips_offset_operand_get_text(const GMipsOffsetOperand *, const exe_format *, AsmSyntax);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COQUILLE VIDE POUR OPERANDE MIPS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour un opérande de MIPS. */
+G_DEFINE_TYPE(GMipsOperand, g_mips_operand, G_TYPE_ARCH_OPERAND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérandes MIPS de base. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_operand_class_init(GMipsOperandClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opérande de base pour MIPS. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_operand_init(GMipsOperand *operand)
+{
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES OFFRANT UN REGISTRE MIPS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour un opérande de registre MIPS. */
+G_DEFINE_TYPE(GMipsRegisterOperand, g_mips_register_operand, G_TYPE_MIPS_OPERAND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérandes de registre MIPS. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_register_operand_class_init(GMipsRegisterOperandClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opérande de registre MIPS. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_register_operand_init(GMipsRegisterOperand *operand)
+{
+ GArchOperand *parent; /* Instance parente */
+
+ parent = G_ARCH_OPERAND(operand);
+
+ parent->get_text = (get_operand_text_fc)g_mips_register_operand_get_text;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : index = identifiant du registre à représenter. *
+* *
+* Description : Crée un opérande visant un registre MIPS. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_mips_register_operand_new(bin_t index)
+{
+ GMipsRegisterOperand *result; /* Structure à retourner */
+ mips_register *reg; /* Registre lu */
+
+ reg = get_mips_register(index);
+
+ if (reg != NULL)
+ {
+ result = g_object_new(G_TYPE_MIPS_REGISTER_OPERAND, NULL);
+
+ result->reg = reg;
+
+ }
+ else result = NULL;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
+* syntax = type de représentation demandée. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_mips_register_operand_get_text(const GMipsRegisterOperand *operand, const exe_format *format, AsmSyntax syntax)
+{
+ char *result; /* Chaîne à retourner */
+
+ result = mips_register_as_text(operand->reg, syntax);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à consulter. *
+* *
+* Description : Fournit le registre MIPS représenté. *
+* *
+* Retour : Régistre MIPS représenté. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const mips_register *g_mips_register_operand_get_register(const GMipsRegisterOperand *operand)
+{
+ return operand->reg;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES DE CONTENU MEMOIRE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour un opérande MIPS de contenu mémoire. */
+G_DEFINE_TYPE(GMipsMemContentOperand, g_mips_mem_content_operand, G_TYPE_MIPS_OPERAND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérandes MIPS de contenu mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_mem_content_operand_class_init(GMipsMemContentOperandClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opérande MIPS de contenu mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_mem_content_operand_init(GMipsMemContentOperand *operand)
+{
+ GArchOperand *parent; /* Instance parente */
+
+ parent = G_ARCH_OPERAND(operand);
+
+ parent->get_text = (get_operand_text_fc)g_mips_mem_content_operand_get_text;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : index = indice du registre de base. *
+* offset = décallage supplémentaire à appliquer. *
+* *
+* Description : Crée un opérande MIPS de contenu mémoire. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_mips_mem_content_operand_new(bin_t index, int16_t offset)
+{
+ GMipsMemContentOperand *result; /* Structure à retourner */
+ mips_register *base; /* Registre lu */
+
+ base = get_mips_register(index);
+
+ if (base != NULL)
+ {
+ result = g_object_new(G_TYPE_MIPS_MEM_CONTENT_OPERAND, NULL);
+
+ result->base = base;
+ result->offset = g_imm_operand_new_from_value(AOS_16_BITS_SIGNED, offset);
+
+ }
+ else result = NULL;
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
+* syntax = type de représentation demandée. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_mips_mem_content_operand_get_text(const GMipsMemContentOperand *operand, const exe_format *format, AsmSyntax syntax)
+{
+ char *result; /* Chaîne à retourner */
+ char *tmp; /* Déplacement */
+
+ result = mips_register_as_text(operand->base, syntax);
+
+ result = strprep(result, "[");
+
+ if (g_imm_operand_is_negative(operand->offset)) result = stradd(result, "-");
+ else result = stradd(result, "+");
+
+ tmp = g_arch_operand_get_text(G_ARCH_OPERAND(operand->offset), format, syntax);
+ result = stradd(result, tmp);
+ free(tmp);
+
+ result = stradd(result, "]");
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* OPERANDES DE DECALLAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini par la GLib pour un opérande MIPS de décallage. */
+G_DEFINE_TYPE(GMipsOffsetOperand, g_mips_offset_operand, G_TYPE_MIPS_OPERAND);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des opérandes MIPS de décallage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_offset_operand_class_init(GMipsOffsetOperandClass *klass)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = instance à initialiser. *
+* *
+* Description : Initialise une instance d'opérande MIPS de décallage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_mips_offset_operand_init(GMipsOffsetOperand *operand)
+{
+ GArchOperand *parent; /* Instance parente */
+
+ parent = G_ARCH_OPERAND(operand);
+
+ parent->get_text = (get_operand_text_fc)g_mips_offset_operand_get_text;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : offset = valeur de décallage à représenter. *
+* *
+* Description : Crée un opérande MIPS de décallage. *
+* *
+* Retour : Opérande mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *g_mips_offset_operand_new(int16_t offset)
+{
+ GMipsOffsetOperand *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_MIPS_OFFSET_OPERAND, NULL);
+
+ result->offset = g_imm_operand_new_from_value(AOS_16_BITS_SIGNED, offset);
+
+ return G_ARCH_OPERAND(result);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = opérande à traiter. *
+* format = format du binaire manipulé. *
+* syntax = type de représentation demandée. *
+* *
+* Description : Traduit un opérande en version humainement lisible. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *g_mips_offset_operand_get_text(const GMipsOffsetOperand *operand, const exe_format *format, AsmSyntax syntax)
+{
+ return g_arch_operand_get_text(G_ARCH_OPERAND(operand->offset), format, syntax);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* AIDE A LA CREATION D'OPERANDES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : instr = instruction dont la définition est à compléter. [OUT]*
+* data = flux de données à analyser. *
+* pos = position courante dans ce flux. [OUT] *
+* len = taille totale des données à analyser. *
+* count = type du premier opérande. *
+* ... = type des opérandes à interpréter. *
+* *
+* Description : Procède à la lecture de deux opérandes donnés. *
+* *
+* Retour : Bilan de l'opération : true en cas de succès, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool mips_read_n_operands(GArchInstruction *instr, const bin_t *data, off_t *pos, off_t len, unsigned int count, ...)
+{
+ bool result; /* Statut à retourner */
+ uint32_t code; /* Code binaire à décoder */
+ MipsOperandType type; /* Type d'opérand interprétée */
+ va_list ap; /* Arguments potentiels */
+ unsigned int i; /* Boucle de parcours */
+ bin_t reg; /* Identifiant de registre */
+ GArchOperand *op; /* Opérande décodé */
+
+ if (!read_u32(&code, data, pos, len, SRE_LITTLE/* FIXME */))
+ return false;
+
+ result = true;
+
+ va_start(ap, count);
+
+ for (i = 0; i < count; i++)
+ {
+ type = va_arg(ap, MipsOperandType);
+
+ switch (type)
+ {
+ case MIPS_OTP_RS:
+ reg = (code & 0x3e00000) >> 21;
+ op = g_mips_register_operand_new(reg);
+ break;
+
+ case MIPS_OTP_RT:
+ reg = (code & 0x1f0000) >> 16;
+ op = g_mips_register_operand_new(reg);
+ break;
+
+ case MIPS_OTP_RD:
+ reg = (code & 0xf800) >> 11;
+ op = g_mips_register_operand_new(reg);
+ break;
+
+ case MIPS_OTP_IMMEDIATE:
+ op = g_imm_operand_new_from_value(AOS_16_BITS, code & 0xffff);
+ break;
+
+
+
+
+ case MIPS_OTP_MEM_CONTENT:
+ op = g_mips_mem_content_operand_new((code & 0x3e00000) >> 21, code & 0xffff);
+ break;
+
+ case MIPS_OTP_OFFSET:
+ op = g_mips_offset_operand_new(code & 0xffff);
+ break;
+
+ case MIPS_OTP_SA:
+ op = g_imm_operand_new_from_value(AOS_8_BITS, (code & 0x7c0) >> 6);
+ break;
+
+ default:
+ op = NULL;
+ break;
+
+ }
+
+ if (op == NULL) result = false;
+ else g_arch_instruction_attach_extra_operand(instr, op);
+
+ }
+
+ va_end(ap);
+
+ return result;
+
+}