/* gpregister.c - Handler of the processor registers and bits.
Copyright 2014 Molnár Károly
*/
#include "stdhdr.h"
#include "libgputils.h"
/*------------------------------------------------------------------------------------------------*/
int _cdecl gp_register_table_t::_mcu_cmp(const void *P1, const void *P2) {
const char *n1 = reinterpret_cast<const char*>(P1),
*n2 = reinterpret_cast<const gp_register_table_t*>(P2)->name;
return strcasecmp(n1,n2);
}
const gp_register_table_t* gp_register_table_t::find_mcu(const char *McuName) {
return (const gp_register_table_t*)bsearch(McuName,
gp_register_db, gp_register_db_size,
sizeof(gp_register_table_t), _mcu_cmp);
}
/*------------------------------------------------------------------------------------------------*/
const gp_register_t* gp_register_table_t::find_reg(unsigned Address) const{
// No bsearch as table is possibly not sorted and zero-terminated
// TODO: Similar PICs should inherit their registers somehow!
for (const gp_register_t**pp=registers;*pp;pp++) {
const gp_register_t*p = *pp;
unsigned sz = 1; // size of register in bytes (span)
if (p->mask&0xFF00) sz=2; // word with "L" and "H"
// TODO: Decode other special meanings of mask
if (p->addr<=Address && Address<p->addr+sz) return p;
}
return 0;
}
/*------------------------------------------------------------------------------------------------*/
const char* gp_register_table_t::find_reg_name(unsigned Address) const {
const gp_register_t*r = find_reg(Address);
if (!r) return 0;
if (r->mask&0xFF00) { // name must be synthesized
size_t l = strlen(r->name);
char*s = new char[l+2];
memcpy(s,r->name,l);
s[l] = "LHU"[Address-r->addr]; // append right suffix
s[l+1] = 0;
return s; // TODO: Solve string allocation problem
} // TODO: Do other syntheses
return r->name;
}
/*------------------------------------------------------------------------------------------------*/
static int _cdecl _bit_cmp(const void *P1, const void *P2) {
int a1 = *reinterpret_cast<const unsigned*>(P1),
a2 = reinterpret_cast<const gp_bit_t*>(P2)->address;
return a1-a2; // no overflow here
}
const char* gp_register_t::bit_name(unsigned Address) const {
assert(Address<16);
size_t bit_number = reinterpret_cast<size_t>(bitstring);
if (bit_number>16) { // compact bit description requiring string format
const char*s = bitstring;
if (!(1<<Address&mask)) return 0; // For that register, that bit is not available
// This string terminates each bit group with "\1" (1) upto "\10" (8), its bit count.
// In case of multiple bits, bit number is appended, relative ("\2".."\10"),
// adding 8 ("\12".."20"), adding 16 ("\22".."30") or adding 24 ("\32.."40").
// In case of given mask, the string can be simply zero-terminated, and a bit number is always added.
// For possible 16-bit values, mask is expected to have 16 bit, but for now only 8 bits.
unsigned a = Address; // "relative" address
do {
const char*e = s;
while ((unsigned char)*e>' ') ++e; // search terminator
unsigned n = *e;
if (!n) n=16; // expect a byte (?)
unsigned k = (n-1)>>3; // upper two bits control bit number insertion
n = (n-1&7)+1; // lower three bits = group length
if (a<n) { // right bit group
if (s==e) return 0; // empty bit name = no name
unsigned z = a+(k<<3); // add 0 / 8 / 16 / 24
assert(z<100); // 2 digits maximum
bool app = z||n>1; // append bit number?
char*r = new char[e-s+(app?z>=10?3:2:1)];
memcpy(r,s,e-s); // copy name without terminator
if (app) sprintf(r+(e-s),"%u",z); // append bit number (0..23)
else r[e-s]=0; // don't append
return r; // return allocated string. BUG: Don't know how to deallocate yet.
}
a -= n;
s = e;
}while(*s);
return 0; // Address too large = no name
}
const gp_bit_t *ret = (const gp_bit_t*)bsearch(&Address, bits, bit_number, sizeof(gp_bit_t), _bit_cmp);
return ret ? ret->name : 0;
}
Detected encoding: UTF-8 | 0
|