/* GP Symbol table support.
Copyright 2014-2016 Molnár Károly
*/
#include "stdhdr.h"
#include "libgputils.h"
int hash128_t::compare(const hash128_t&b)const{
if (hi < b.hi) return -1;
if (hi > b.hi) return 1;
if (lo < b.lo) return -1;
if (lo > b.lo) return 1;
return 0;
}
/*------------------------------------------------------------------------------------------------*/
static int _cdecl _hash_sort_cmp(const void *P0, const void *P1) {
const gp_hash_t &h0 = *(const gp_hash_t *)P0;
const gp_hash_t &h1 = *(const gp_hash_t *)P1;
int v = h0.hash.compare(h1.hash);
if (v) return v;
const char* s0 = h0.symbol ? h0.symbol->name : 0;
const char* s1 = h1.symbol ? h1.symbol->name : 0;
if (!s0 && !s1) return 0;
if (s0 && s1) return strcmp(s0, s1);
if (s0) return 1;
return -1;
}
/*------------------------------------------------------------------------------------------------*/
static int _cdecl _hash_find_cmp(const void *P0, const void *P1) {
const gp_hash_t &h0 = *(const gp_hash_t *)P0;
const gp_hash_t &h1 = *(const gp_hash_t *)P1;
return h0.hash.compare(h1.hash);
}
/*------------------------------------------------------------------------------------------------*/
FUNC(gp_hash_t*) gp_symbol_make_hash_table(gp_object_t *Object) {
if (!Object) return 0;
unsigned n_symbols = 0;
FOR(gp_symbol_list_t,symbol,Object->symbol_list) {
FlagClr(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
if ((symbol->pclass != C_FILE) && (symbol->pclass != C_EOF) &&
(symbol->pclass != C_SECTION) && (symbol->section_name)) {
++n_symbols;
FlagSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
}
}
gp_hash_t*table = new gp_hash_t[n_symbols];
memset(table,0,sizeof*table*n_symbols);
Object->symbol_hashtable = table;
Object->symbol_hashtable_size = n_symbols;
gp_hash_t*tp = table;
FOR(gp_symbol_list_t,it,Object->symbol_list) {
if (FlagIsSet(it->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE)) {
hash128_t&h = tp->hash;
h.reset();
h.hash(it->section_name);
h.hash((char*)&it->value, sizeof it->value);
tp->symbol = &*it;
++tp;
}
}
qsort(table, n_symbols, sizeof(gp_hash_t), _hash_sort_cmp);
return table;
}
/*------------------------------------------------------------------------------------------------*/
/* Search a symbol on the basis of value and owner section name. */
const gp_symbol_t* gp_symbol_find(const gp_object_t *Object, const char *Section_name, gp_symvalue_t Symbol_value) {
gp_hash_t gp_hash;
gp_hash_t *ret;
if (!Object || !Section_name) return 0;
if (!Object->symbol_hashtable || !Object->symbol_hashtable_size) return 0;
gp_hash.hash.hash(Section_name,false);
gp_hash.hash.hash((char*)&Symbol_value,sizeof(Symbol_value));
ret = (gp_hash_t *)bsearch(&gp_hash, Object->symbol_hashtable, Object->symbol_hashtable_size,
sizeof(gp_hash_t), _hash_find_cmp);
return ret ? ret->symbol : NULL;
}
/*------------------------------------------------------------------------------------------------*/
static int _cdecl _value_cmp(const void *P0, const void *P1) {
const gp_symbol_t *s0 = *(const gp_symbol_t **)P0;
const gp_symbol_t *s1 = *(const gp_symbol_t **)P1;
gp_symvalue_t v0 = s0->value;
gp_symvalue_t v1 = s1->value;
if (v0 < v1) {
return -1;
}
if (v0 > v1) {
return 1;
}
return 0;
}
/*------------------------------------------------------------------------------------------------*/
/* Collects those labels that belong to the same "Section". */
gp_symbol_t** gp_symbol_make_label_array(gp_section_t *Section, unsigned Org_to_byte_shift,
unsigned *Num_labels) {
gp_symbol_t **array;
gp_symvalue_t start_addr;
gp_symvalue_t end_addr;
unsigned i;
unsigned n_labels;
if (!Section || !Num_labels) return 0;
start_addr = gp_insn_from_byte(Org_to_byte_shift, Section->address);
end_addr = start_addr + gp_insn_from_byte(Org_to_byte_shift, Section->size);
n_labels = 0;
gp_symbol_list_t::iterator symbol = Section->symbol;
while (&*symbol) {
FlagClr(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
if (((symbol->pclass == C_EXT) || (symbol->pclass == C_LABEL)) &&
(symbol->section) && FlagsIsNotAllClr(symbol->section->flags, STYP_ROM_AREA)) {
if ((symbol->value >= start_addr) && (symbol->value < end_addr)) {
++n_labels;
FlagSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
}
}
symbol++;
}
if (n_labels == 0) {
return NULL;
}
array = new gp_symbol_t*[n_labels];
i = 0;
symbol = Section->symbol;
while (&*symbol) {
if (FlagIsSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE)) {
array[i] = &*symbol;
++i;
}
symbol++;
}
qsort(array, n_labels, sizeof(gp_symbol_t *), _value_cmp);
*Num_labels = n_labels;
return array;
}
/*------------------------------------------------------------------------------------------------*/
/* Collects those registers that belong to the same "Section". */
gp_symbol_t** gp_symbol_make_register_array(gp_object_t *Object, unsigned &Num_registers) {
if (!Object || !Num_registers) return 0;
unsigned n_registers = 0;
FOR(gp_symbol_list_t,symbol,Object->symbol_list) {
FlagClr(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
if ((symbol->pclass != C_FILE) && (symbol->pclass != C_EOF) && (symbol->pclass != C_SECTION) &&
(symbol->section) && FlagsIsNotAllClr(symbol->section->flags, STYP_RAM_AREA)) {
++n_registers;
FlagSet(symbol->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE);
}
}
if (!n_registers) return 0;
gp_symbol_t**array = new gp_symbol_t*[n_registers];
unsigned i = 0;
FOR(gp_symbol_list_t,it,Object->symbol_list)
if (FlagIsSet(it->opt_flags, OPT_FLAGS_GPSYMBOL_MODULE)) array[i++] = &*it;
qsort(array, n_registers, sizeof(gp_symbol_t *), _value_cmp);
Num_registers = n_registers;
return array;
}
/*------------------------------------------------------------------------------------------------*/
/* Search a symbol on the basis of value. */
gp_symbol_t* gp_symbol_find_by_value(gp_symbol_t **Array, unsigned Num_symbols, gp_symvalue_t Value) {
gp_symbol_t symbol;
gp_symbol_t *sptr;
gp_symbol_t **ret;
if ((Array == NULL) || (Num_symbols == 0)) {
return NULL;
}
symbol.value = Value;
sptr = &symbol;
ret = (gp_symbol_t **)bsearch(&sptr, Array, Num_symbols, sizeof(gp_symbol_t *), _value_cmp);
return ((ret) ? *ret : NULL);
}
/*------------------------------------------------------------------------------------------------*/
/* Delete a symbol on the basis of value. */
bool gp_symbol_delete_by_value(gp_symbol_t **Array, unsigned *Num_symbols, gp_symvalue_t Value) {
unsigned n_symbols;
gp_symbol_t symbol;
gp_symbol_t *sptr;
gp_symbol_t **ret;
unsigned dst;
unsigned src;
unsigned num;
if ((Array == NULL) || (Num_symbols == NULL) || ((n_symbols = *Num_symbols) == 0)) {
return false;
}
symbol.value = Value;
sptr = &symbol;
ret = (gp_symbol_t **)bsearch(&sptr, Array, n_symbols, sizeof(gp_symbol_t *), _value_cmp);
if (ret) {
dst = ret - Array;
src = dst + 1;
num = n_symbols - src;
if (num != 0) {
memmove(&Array[dst], &Array[src], num * sizeof(gp_symbol_t *));
}
*Num_symbols = n_symbols - 1;
return true;
}
return false;
}
Detected encoding: UTF-8 | 0
|