https://hal.archives-ouvertes.fr/hal-03445821
arch.c
/*
Copyright Universite de Versailles Saint-Quentin en Yvelines 2009
AUTHORS: Sebastien Briais, Sid Touati
This file is part of GDD.
GDD is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
GDD 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with GDD. If not, see
<http://www.gnu.org/licenses/>.
*/
#include <SCEDA/common.h>
#include "arch.h"
#include "opcode.h"
#include "util.h"
/* Include string hash and match functions */
#include "stringutil.h"
static unsigned int GDD_opcode_hash(GDD_Opcode *op) {
return string_hash(GDD_opcode_mnemonic(op));
}
static int GDD_opcode_match(GDD_Opcode *op1, GDD_Opcode *op2) {
return string_match(GDD_opcode_mnemonic(op1), GDD_opcode_mnemonic(op2));
}
typedef struct {
char *name;
int nb;
} TypeEntry;
static void type_entry_delete(TypeEntry *te) {
free(te->name);
free(te);
}
static unsigned int type_entry_hash(TypeEntry *te) {
return string_hash(te->name);
}
static int type_entry_match(TypeEntry *t1, TypeEntry *t2) {
return string_match(t1->name, t2->name);
}
/** Create a new architecture
@return an architecture */
GDD_Arch *GDD_arch_create() {
GDD_Arch *arch = (GDD_Arch *)safe_malloc(sizeof(GDD_Arch));
arch->opcodes = SCEDA_hashset_create((SCEDA_delete_fun)GDD_opcode_delete,
(SCEDA_match_fun)GDD_opcode_match,
(SCEDA_hash_fun)GDD_opcode_hash);
arch->types = SCEDA_hashset_create((SCEDA_delete_fun)type_entry_delete,
(SCEDA_match_fun)type_entry_match,
(SCEDA_hash_fun)type_entry_hash);
return arch;
}
/** Delete an architecture
@param[in] arch = architecture
It will also delete the opcodes. */
void GDD_arch_delete(GDD_Arch *arch) {
SCEDA_hashset_delete(arch->opcodes);
SCEDA_hashset_delete(arch->types);
free(arch);
}
/** Add an opcode to an architecture.
@param[in] arch = architecture
@param[in] op = opcode
@return 0 in case of success, 1 if opcode was already present (not
changed), -1 otherwise
*/
int GDD_arch_add_opcode(GDD_Arch *arch, GDD_Opcode *op) {
return SCEDA_hashset_add(arch->opcodes, op);
}
/** Get the opcode of given mnemonic.
@param[in] arch = architecture
@param[in] mnemo = mnemonic
@return the opcode of given mnemonic or NULL if not found */
GDD_Opcode *GDD_arch_get_opcode(GDD_Arch *arch, const char *mnemo) {
GDD_Opcode tmp;
tmp.mnemo = (char *)mnemo;
GDD_Opcode *op = &tmp;
if(SCEDA_hashset_lookup(arch->opcodes, (void **)&op) == 0) {
return op;
}
return NULL;
}
/** Add registers of given type to the architecture.
@param[in] arch = architecture
@param[in] type = considered type
@param[in] nb = number of registers (should be > 0)
@return 0 in case of success, 1 if registers of the given type
were already in the architecture (not modified), -1 otherwise */
int GDD_arch_add_regtype(GDD_Arch *arch, const char *type, int nb) {
if(nb <= 0) {
return -1;
}
TypeEntry *te = (TypeEntry *)safe_malloc(sizeof(TypeEntry));
te->name = safe_strdup(type);
te->nb = nb;
return SCEDA_hashset_add(arch->types, te);
}
/** Get the number of registers of given type.
@param[in] arch = architecture
@param[in] type = considered type
@return the number of registers of considered type */
int GDD_arch_get_regtype(GDD_Arch *arch, const char *type) {
TypeEntry tmp;
tmp.name = (char *)type;
TypeEntry *te = &tmp;
if(SCEDA_hashset_lookup(arch->types, (void **)&te) == 0) {
return te->nb;
}
return 0;
}
/** Modify the number of available registers of given type in the
architecture.
@param[in] arch = architecture
@param[in] type = considered type
@param[in] nb = new number of registers
@return 0 in case of success, -1 otherwise */
int GDD_arch_set_regtype(GDD_Arch *arch, const char *type, int nb) {
TypeEntry tmp;
tmp.name = (char *)type;
TypeEntry *te = &tmp;
if(SCEDA_hashset_lookup(arch->types, (void **)&te) == 0) {
te->nb = nb;
return 0;
}
return -1;
}
/** Print the description of an architecture.
@param[in] stream = file stream where to print
@param[in] arch = architecture */
void GDD_arch_fprint(FILE *stream, GDD_Arch *arch) {
SCEDA_HashSetIterator hiter;
SCEDA_hashset_iterator_init(arch->types, &hiter);
while(SCEDA_hashset_iterator_has_next(&hiter)) {
TypeEntry *te = SCEDA_hashset_iterator_next(&hiter);
fprintf(stream, "%d registers of type %s\n", te->nb, te->name);
}
SCEDA_hashset_iterator_cleanup(&hiter);
SCEDA_hashset_iterator_init(arch->opcodes, &hiter);
while(SCEDA_hashset_iterator_has_next(&hiter)) {
GDD_Opcode *op = SCEDA_hashset_iterator_next(&hiter);
fprintf(stream,"--\n");
GDD_opcode_fprint(stream, op);
}
SCEDA_hashset_iterator_cleanup(&hiter);
fprintf(stream,"--\n");
}
/** Return the next type in the iterator.
@param[in] iter = iterator
@return the type */
char *GDD_arch_types_iterator_next(GDD_ArchTypesIterator *aiter) {
TypeEntry *t = SCEDA_hashset_iterator_next(aiter);
return t->name;
}