/*
Copyright (C) 1998 T. Scott Dattalo
This file is part of gpsim.
gpsim 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 2, or (at your option)
any later version.
gpsim 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 gpasm; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
//
// symbol.cc
//
// The file contains the code that controls all of the symbol
// stuff for gpsim. Most of the work is handled by the C++ map
// container class.
//
#include "symbol.h"
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include "../config.h"
#include "14bit-processors.h"
#include "stimuli.h"
#include "symbol_orb.h"
#include "expr.h"
#include "ValueCollections.h"
#include "operator.h"
#include "errors.h"
#include "protocol.h"
#include "cmd_gpsim.h"
#include "sim_context.h"
class IIndexedCollection;
//
// ***NOTE*** Ideally, I would like to use a the std container 'map'
// to implement symbol tables. Unfortunately, iterators do not work
// correctly with maps in libg++ (?version 1.27?)
// Create a map for the symbol table. Note that the scope of the
// symbol table is only within symbol.cc. The symbol table is
// indexed by the symbol's name (a string). If a symbol is found
// in the table then a pointer to it is returned.
//map <string, symbol *, less<string> > st;
//map <string, symbol *, less<string> >::iterator sti;
Symbol_Table symbol_table; // There's only one instance of "the" symbol table
#if defined(_WIN32)
Symbol_Table &get_symbol_table(void) {
return symbol_table;
}
#endif
Symbol_Table::Symbol_Table() {
reserve(500);
}
void Symbol_Table::add_ioport(PortRegister *_ioport)
{
ioport_symbol *is = new ioport_symbol(_ioport);
if(!add(is)) {
delete is;
}
}
void Symbol_Table::add_stimulus_node(Stimulus_Node *s)
{
node_symbol *sym = findNodeSymbol(s->name());
// New paradigm is for the named stimulus objects
// to add themselves and remove them selves.
// Since there is a lot of code that adds a stimulus
// object we will ignore them if the stimulus already
// exists unless it is a different object with the
// same name.
if(sym == NULL) {
node_symbol *ns = new node_symbol(s);
if(!add(ns)) {
delete ns;
}
}
else if(sym->getNode() != s) {
GetUserInterface().DisplayMessage("Warning: Attempt to add symbol %s that already exists\n",
s->name().c_str());
}
else {
// use this code to capture calls to add_stimulus_node() that are not needed
GetUserInterface().DisplayMessage("Warning: Attempt to add symbol object '%s' twice\n",
s->name().c_str());
}
}
void Symbol_Table::add_stimulus(stimulus *s)
{
stimulus_symbol *sym = findStimulusSymbol(s->name());
// New paradigm is for the named stimulus objects
// to add themselves and remove them selves.
// Since there is a lot of code that adds a stimulus
// object we will ignore them if the stimulus already
// exists unless it is a different object with the
// same name.
if(sym == NULL) {
stimulus_symbol *ss = new stimulus_symbol(s);
if(!add(ss)) {
delete ss;
}
}
else if(sym->getStimulus() != s) {
GetUserInterface().DisplayMessage("Warning: Attempt to add symbol %s that already exists\n",
s->name().c_str());
}
else {
// use this code to capture calls to add_stimulus() that are not needed
GetUserInterface().DisplayMessage("Warning: Attempt to add symbol object '%s' twice\n",
s->name().c_str());
}
}
// This is an experiment to have the symbol table ordered
// case insensitive unless their is a match for a case insensitive
// compare, then a case sensitive compare is made.
int SymbolCompare(const char *pLeft, const char *pRight) {
#if 0
int iResult = stricmp(pLeft, pRight);
if(iResult < 0) {
return -1;
}
else if(iResult > 0) {
return 1;
}
else {
return strcmp(pLeft, pRight);
}
#else
return strcmp(pLeft, pRight);
#endif
}
//------------------------------------------------------------------------
// add(Value *) - add a symbol to the symbol table
bool Symbol_Table::add(Value *s)
{
if(s) {
if(s->name().empty()) {
printf("Symbol_Table::add() attempt to add a symbol with no name: %s\n",
s->toString().c_str());
}
else {
iterator it = lower_bound(begin( ), end( ),
s, NameLessThan());
if (it != end() &&
(*it)->name() == s->name()) {
GetUserInterface().DisplayMessage(
"Symbol_Table::add(): Warning: failed to add symbol "
"because a symbol by the name '%s' already exists, new object is type %s\n",
s->name().c_str(), s->showType().c_str());
return false;
}
if(verbose)
cout << "Adding '" << s->name() << "' to the symbol table\n";
insert(it, s);
return true;
}
}
return false;
}
//------------------------------------------------------------------------
// add_register
register_symbol *Symbol_Table::add_register(Register *new_reg, const char *symbol_name)
{
// mask of zero lets the register_symbol calculate a default mask
return add_register(new_reg, symbol_name, 0);
}
register_symbol * Symbol_Table::add_register(Register *new_reg,
const char *symbol_name,
unsigned int uMask)
{
if(!new_reg)
return 0;
if(symbol_name) {
string sName(symbol_name);
if((new_reg->name() == sName && find(new_reg->name()) ) ||
new_reg->baseName() == sName && find(new_reg->baseName())) {
if(verbose)
GetUserInterface().DisplayMessage(
"Symbol_Table::add_register(): Warning: Not adding register symbol '%s'"
" to symbol table\n because it already exists.\n",
symbol_name);
return 0;
}
}
register_symbol *rs = new register_symbol(symbol_name, new_reg, uMask);
add(rs);
return rs;
}
void Symbol_Table::add_w(WREG *new_w)
{
if(!new_w)
return;
w_symbol *ws = new w_symbol((char *)0, new_w);
add(ws);
}
void Symbol_Table::add_constant(const char *_name, int value, bool bClearable)
{
Integer *i = new Integer(value);
i->new_name(_name);
i->setClearableSymbol(bClearable);
add(i);
}
void Symbol_Table::add_address(const char *new_name, int value)
{
address_symbol *as = new address_symbol(new_name,value);
add(as);
}
void Symbol_Table::add_line_number(int address, const char *symbol_name)
{
line_number_symbol *lns = new line_number_symbol(symbol_name, address);
add(lns);
}
void Symbol_Table::add_module(Module * m, const char *cPname)
{
module_symbol *ms = new module_symbol(m,cPname);
if(!add(ms)) {
delete ms;
}
}
void Symbol_Table::remove_module(Module * m)
{
iterator sti = FindIt(m->name());
Value *sym;
while( sti != end()) {
sym = *sti;
if((typeid(sym) == typeid(module_symbol)) &&
sym->name() == m->name()) {
erase(sti);
return;
}
sti++;
}
}
Value *Symbol_Table::remove(string &s)
{
iterator it = FindIt(s);
if(it != end() && (*it)->name() == s) {
Value *pValue = *it;
erase(it);
return pValue;
}
return NULL;
}
void Symbol_Table::rename(const char *pOldName, const char *pNewName)
{
// First make sure the old and new names are both valid.
if (pNewName && pOldName && *pOldName && *pNewName) {
iterator it = FindIt(pOldName);
if(it != end() && (*it)->name() == pOldName) {
Value *pValue = *it;
erase(it);
pValue->new_name(pNewName);
add(pValue);
}
}
}
Value * Symbol_Table::find(const char *str)
{
string s(str);
return(find(s));
}
Value * Symbol_Table::find(type_info const &symt, const char *str)
{
string s(str);
iterator sti = FindIt(str);
while( sti != end()) {
Value *val = *sti;
int iResult = val->name().compare(s);
if(iResult == 0) {
return val;
}
else if(iResult > 0) {
// leave early for efficiency
return NULL;
}
sti++;
}
return 0;
}
Register * Symbol_Table::findRegister(unsigned int address)
{
iterator sti = begin();
while( sti != end()) {
register_symbol *pSymbol = dynamic_cast<register_symbol*>(*sti);
if(pSymbol != 0) {
Register * pReg = pSymbol->getReg();
if(pReg->address == address &&
pSymbol->getBitmask() == pReg->get_cpu()->register_mask())
// This function will find the first symbol that
// uses the entire bit field of the register.
return(pReg);
}
sti++;
}
return NULL;
}
register_symbol * Symbol_Table::findRegisterSymbol(const char *pName)
{
iterator sti;
register_symbol *pRegSym;
for( sti = FindIt(pName) ;sti != end(); sti++) {
Value *val = *sti;
if(val->name() == pName) {
if((pRegSym = dynamic_cast<register_symbol*>(val)) != NULL) {
return pRegSym;
}
}
}
return 0;
}
register_symbol * Symbol_Table::findRegisterSymbol(unsigned int uAddress)
{
iterator sti = begin();
ostringstream sDumbLabel;
sDumbLabel << "R" << hex << uppercase << uAddress;
while( sti != end()) {
register_symbol *pRegSymbol = dynamic_cast<register_symbol*>(*sti);
if(pRegSymbol != 0) {
Register * pReg = pRegSymbol->getReg();
if (0 && pReg && pReg->get_cpu() == NULL) {
// hmmm we need to fix this... It's possible for
// modules (which are not processors) to have registers.
//cout << " Null cpu for reg named:"<<pReg->name()<<endl;
}
//assert(pReg->get_cpu() != NULL);
if(pReg && pReg->get_cpu() && pRegSymbol->getAddress() == uAddress &&
pRegSymbol->getBitmask() == pReg->get_cpu()->register_mask() &&
// This function will find the first symbol that
// uses the entire bit field of the register.
sDumbLabel.str() != pRegSymbol->name()) {
return(pRegSymbol);
}
}
sti++;
}
return NULL;
}
register_symbol * Symbol_Table::findRegisterSymbol(unsigned int uAddress,
unsigned int uBitmask)
{
if(uBitmask == 0) {
uBitmask = get_active_cpu()->register_mask();
}
iterator sti = begin();
ostringstream sDumbLabel;
sDumbLabel << "R" << hex << uppercase << uAddress;
while( sti != end()) {
register_symbol *pRegSymbol = dynamic_cast<register_symbol*>(*sti);
if(pRegSymbol != 0) {
if(pRegSymbol->getAddress() == uAddress &&
pRegSymbol->getBitmask() == uBitmask &&
sDumbLabel.str() != pRegSymbol->name()) {
return(pRegSymbol);
}
}
sti++;
}
return NULL;
}
Register * Symbol_Table::findRegister(const char *s)
{
iterator sti = FindIt(s); // .begin();
while( sti != end()) {
Value *val = *sti;
if(val && typeid(*val) == typeid(register_symbol)) {
if(val->name() == s) {
return ((register_symbol*)val)->getReg();
}
}
sti++;
}
return NULL;
}
const char * Symbol_Table::findProgramAddressLabel(unsigned int address) {
iterator sti = begin();
while( sti != end()) {
Value *val = *sti;
address_symbol * pAddSym = dynamic_cast<address_symbol*>(val);
if(pAddSym != NULL) {
gint64 iSymbolAddress;
pAddSym->get(iSymbolAddress);
if(iSymbolAddress == address &&
strncmp(pAddSym->name().c_str(), "line_", sizeof("line_") - 1) != 0) {
return pAddSym->name().c_str();
}
}
sti++;
}
return "";
}
const char * Symbol_Table::findConstant(unsigned int uValue,
unsigned int uReferencedFromAddress)
{
// regarding uReferencingAddress
// see comment in the header.
iterator sti = begin();
while( sti != end()) {
Integer *val = dynamic_cast<Integer*>(*sti);
if(val != NULL) {
gint64 uSymValue;
val->get(uSymValue);
if(uValue == (unsigned int)uSymValue)
return(val->name().c_str());
}
sti++;
}
return NULL;
}
Integer * Symbol_Table::findInteger(const char *s)
{
return findSymbol(s, (Integer*)NULL);
}
Boolean * Symbol_Table::findBoolean(const char *s)
{
return findSymbol(s, (Boolean*)NULL);
}
module_symbol *Symbol_Table::findModuleSymbol(const char *s)
{
return findSymbol(s, (module_symbol*)NULL);
}
Module * Symbol_Table::findModule(const char *s)
{
module_symbol * pNodeSym = findModuleSymbol(s);
if( pNodeSym != NULL) {
return pNodeSym->get_module();
}
return ((Module *)0);
}
node_symbol * Symbol_Table::findNodeSymbol(const char *s)
{
return findSymbol(s, (node_symbol*)NULL);
}
Stimulus_Node * Symbol_Table::findNode(const char *s)
{
node_symbol * pNodeSym = findNodeSymbol(s);
if( pNodeSym != NULL) {
return pNodeSym->getNode();
}
return ((Stimulus_Node *)0);
}
String * Symbol_Table::findString(const char *s)
{
return findSymbol(s, (String *)NULL);
}
template<class _symbol_iterator_t, class _symbol_t>
_symbol_iterator_t Symbol_Table::beginSymbol(_symbol_iterator_t *pit, _symbol_t*psym) {
iterator it;
iterator itEnd = _Myt::end();
for(it = _Myt::begin(); itEnd != it; it++) {
if(dynamic_cast<_symbol_t*>(*it) != NULL) {
return _symbol_iterator_t(this, it);
}
}
return _symbol_iterator_t(this, itEnd);
}
template<class _symbol_iterator_t, class _symbol_t>
_symbol_iterator_t Symbol_Table::endSymbol(_symbol_iterator_t *pit, _symbol_t*psym) {
return _symbol_iterator_t(this,_Myt::end());
}
Symbol_Table::node_symbol_iterator Symbol_Table::beginNodeSymbol()
{
return (node_symbol_iterator)beginSymbol((node_symbol_iterator*)0,
(node_symbol*)0);
}
Symbol_Table::node_symbol_iterator Symbol_Table::endNodeSymbol()
{
return endSymbol((node_symbol_iterator*) 0, (node_symbol*)0);
}
stimulus_symbol * Symbol_Table::findStimulusSymbol(const char *s)
{
return findSymbol(s, (stimulus_symbol*)NULL);
}
stimulus * Symbol_Table::findStimulus(const char *s)
{
stimulus_symbol * pNodeSym = findStimulusSymbol(s);
if( pNodeSym != NULL) {
return pNodeSym->getStimulus();
}
attribute_symbol *pSymbol = findAttributeSymbol(s);
if(pSymbol != NULL) {
Value *pValue;
pSymbol->get(&pValue);
return dynamic_cast<stimulus*>(pValue);
}
return ((stimulus *)0);
}
attribute_symbol * Symbol_Table::findAttributeSymbol(const char *s)
{
return findSymbol(s, (attribute_symbol*)NULL);
}
Symbol_Table::stimulus_symbol_iterator Symbol_Table::beginStimulusSymbol() {
return (stimulus_symbol_iterator)beginSymbol(
(stimulus_symbol_iterator*)NULL,
(stimulus_symbol*)NULL);
}
Symbol_Table::stimulus_symbol_iterator Symbol_Table::endStimulusSymbol() {
return endSymbol((stimulus_symbol_iterator*) NULL,
(stimulus_symbol*)NULL);
}
Symbol_Table::module_symbol_iterator Symbol_Table::beginModuleSymbol() {
iterator it;
iterator itEnd = _Myt::end();
for(it = _Myt::begin(); itEnd != it; it++) {
if(dynamic_cast<module_symbol*>(*it) != NULL &&
dynamic_cast<attribute_symbol*>(*it) == NULL) {
return module_symbol_iterator(this, it);
}
}
return module_symbol_iterator(this, itEnd);
// return (module_symbol_iterator)beginSymbol(
// (module_symbol_iterator*)NULL,
// (module_symbol*)NULL);
}
Symbol_Table::module_symbol_iterator Symbol_Table::endModuleSymbol() {
return endSymbol((module_symbol_iterator*) NULL,
(module_symbol*)NULL);
}
Symbol_Table::module_symbol_iterator
Symbol_Table::module_symbol_iterator::operator++(int) {
// postincrement
Symbol_Table::iterator & it = (Symbol_Table::iterator&)*this;
for(it++; it != m_pSymbolTable->end(); it++) {
if(dynamic_cast<module_symbol*>(*it) != NULL &&
dynamic_cast<attribute_symbol*>(*it) == NULL) {
return (*this);
}
}
return (*this);
}
bool Symbol_Table::Exist(const char *s) {
return this->FindIt(s) != end();
}
void Symbol_Table::dump_one(string *s)
{
Value *val = find(*s);
if(val)
cout << val->name() << " = " << val->toString() << endl;
}
void Symbol_Table::dump_one(const char *str)
{
string s = string(str);
dump_one(&s);
}
void Symbol_Table::dump_all(void)
{
cout << " Symbol Table\n";
bool bUserCanceled = false;
CSimulationContext::GetContext()->SetUserCanceledFlag(&bUserCanceled);
iterator sti = begin();
iterator last;
while( sti != end()) {
Value *val = *sti;
if(val && (typeid(*val) != typeid(line_number_symbol))) {
if(dynamic_cast<IIndexedCollection*>(val) == NULL) {
cout << val->name() << " = " ;
}
cout << val->toString() << endl;
}
last = sti;
sti++;
if(sti != end() && (*last)->name() == (*sti)->name()) {
cout << "***************** Duplicate Found ***********" << endl;
}
if(bUserCanceled) {
cout << endl << "Symbol dump canceled." << endl;
break;
}
}
CSimulationContext::GetContext()->SetUserCanceledFlag(NULL);
}
bool beginsWith(string &sTarget, string &sBeginsWith) {
string sT;
sT = sTarget.substr(0, sBeginsWith.size());
return sT == sBeginsWith;
}
void Symbol_Table::dump_filtered(const string & sSymbol)
{
string sBeginsWith;
int nLastCharPos = sSymbol.size() - 1;
if(nLastCharPos < 1) {
dump_all();
return;
}
bool bUserCanceled = false;
CSimulationContext::GetContext()->SetUserCanceledFlag(&bUserCanceled);
if(sSymbol[nLastCharPos] == '.') {
sBeginsWith = sSymbol.substr(0, nLastCharPos);
}
else {
dump_one(sSymbol.c_str());
}
Value KeyValue(sBeginsWith.c_str(), "key value");
iterator sti = lower_bound(begin( ), end( ),
&KeyValue, NameLessThan());
iterator last;
while( sti != end()) {
Value *val = *sti;
if(val && (typeid(*val) != typeid(line_number_symbol)) &&
beginsWith(val->name(), sBeginsWith)) {
if(dynamic_cast<IIndexedCollection*>(val) == NULL) {
cout << val->name() << " = " ;
}
cout << val->toString() << endl;
}
last = sti;
sti++;
if(bUserCanceled) {
cout << endl << "Symbol dump canceled." << endl;
break;
}
}
CSimulationContext::GetContext()->SetUserCanceledFlag(NULL);
}
void Symbol_Table::dump_type(type_info const &symt)
{
cout << DisplayType(symt);
}
string Symbol_Table::DisplayType(type_info const &symt)
{
ostringstream stream;
// Now loop through the whole table and display all instances of the type of interest
int first=1; // On the first encounter of one, display the title
iterator sti = begin();
while( sti != end()) {
Value *sym = *sti;
if(sym && (typeid(*sym) == symt)) {
if(first) {
first = 0;
stream << "Symbol Table for \"" << sym->showType() << "\"" << endl;
}
stream << sym->toString() << endl;
}
sti++;
}
if(first)
stream << "No symbols found" << endl << ends;
return string(stream.str());
}
bool IsClearable(Value* value)
{
return value->isClearable();
}
void Symbol_Table::clear()
{
iterator it;
for(it = begin(); it != end();) {
Value *value = *it;
if(value && value->isClearable()) {
delete value;
erase(it);
}
else {
++it;
}
}
// remove_if(begin(), end(), IsClearable);
}
void Symbol_Table::Initialize()
{
#if 0
PopulateWithCommandLineSymbols();
#endif
}
void Symbol_Table::Reinitialize()
{
clear();
}
void Symbol_Table::clear_all()
{
iterator it;
for(it = begin(); it != end(); ++it)
delete *it;
_Myt::clear();
}
Value * Symbol_Table::find(const string &s)
{
const bool findDuplicates=false;
iterator sti = FindIt(s); // .begin();
Value *ret=0;
while( sti != end()) {
Value *val = *sti;
if(val && val->name() == s) {
if(!findDuplicates)
return val;
if(!ret) {
ret = val;
} else
cout << "Found duplicate:" << val->show()<<endl;
}
sti++;
}
return ret;
}
Symbol_Table::iterator
Symbol_Table::FindIt(const char *pszKey) {
Value KeyValue(pszKey, "key value");
return FindIt(&KeyValue);
}
Symbol_Table::iterator
Symbol_Table::FindIt(const string &sKey) {
Value KeyValue(sKey.c_str(), "key value");
return FindIt(&KeyValue);
}
Symbol_Table::iterator
Symbol_Table::FindIt(Value *key) {
iterator it = lower_bound(begin( ), end( ),
key, NameLessThan());
if (it != end() &&
(*it)->name() == key->name()) {
return it;
}
return end();
}
//------------------------------------------------------------------------
// symbols
//
//
symbol::symbol(const char *_name)
{
new_name(_name);
}
symbol::symbol(string &_name)
{
new_name(_name);
}
symbol::~symbol(void)
{
}
Value* symbol::evaluate()
{
string msg("symbol '");
msg.append(this->name());
msg.append("' of type '");
msg.append(showType());
msg.append("' cannot not be evaluated in an expression");
throw Error( msg );
}
//------------------------------------------------------------------------
string symbol::toString()
{
return showType();
}
//------------------------------------------------------------------------
node_symbol::node_symbol(Stimulus_Node *_sn)
: symbol(0) , stimulus_node(_sn)
{
if(stimulus_node)
new_name(stimulus_node->name());
}
string node_symbol::toString(void)
{
return string("node:")+name();
}
// Count LSB that are off
static int BitShiftCount( unsigned int uMask ) {
unsigned int uBitMaskCount = 0;
if( uMask != 0 ) {
for ( int i = 0; i < 16; i++ ) {
if( (uMask & (0x1 << i)) == 0 )
uBitMaskCount++;
else
break;
}
}
return uBitMaskCount;
}
//------------------------------------------------------------------------
// register_symbol
//
register_symbol::register_symbol(const register_symbol & regsym)
: symbol(regsym.name_str.c_str()), reg(regsym.reg)
{
m_uMask = regsym.m_uMask;
m_uMaskShift = regsym.m_uMaskShift;
if (name_str.empty()) {
name_str = regsym.reg->name();
}
}
register_symbol::register_symbol(const char *_name, Register *_reg)
: symbol(_name), reg(_reg)
{
setMask(reg);
if (_name == NULL && reg != NULL) {
name_str = _reg->name();
}
}
register_symbol::register_symbol(const char *_name, Register *_reg,
unsigned int uMask)
: symbol(_name), reg(_reg)
{
if(uMask == 0) {
setMask(reg);
}
else {
m_uMask = uMask;
m_uMaskShift = BitShiftCount(m_uMask);
}
if (_name == NULL && reg != NULL) {
name_str = _reg->name();
}
}
register_symbol::register_symbol(Register *_reg)
: symbol(_reg->name()), reg(_reg)
{
setMask(reg);
}
void register_symbol::setMask(Register *pReg) {
m_uMask = 0xff;
for(unsigned int i = 1; i < pReg->register_size(); i++) {
m_uMask <<= 8;
m_uMask |= 0xff;
}
m_uMaskShift = BitShiftCount(m_uMask);
}
unsigned int register_symbol::getAddress()
{
return reg ? reg->address : 0xffffffff;
}
unsigned int register_symbol::getBitmask(void) {
return m_uMask;
}
string ®ister_symbol::name() const
{
return (string &)name_str;
}
char *register_symbol::name(char *buf, int len) {
return symbol::name(buf, len);
}
string register_symbol::toString()
{
if(reg) {
char buff[256];
char bits[256];
reg->toBitStr(bits,sizeof(bits));
int iDigits = reg->register_size() * 2;
// turn off masked bits in dwRead
unsigned int uValue = reg->get_value() & m_uMask;
uValue = uValue >> m_uMaskShift;
if ( (unsigned int)((1<<(4*iDigits))-1) != m_uMask)
snprintf(buff,sizeof(buff),"[0x%x] BITS 0x%0*x = 0x%0*x = 0b",
reg->address, iDigits, m_uMask,
iDigits, uValue);
else
snprintf(buff,sizeof(buff),"[0x%x] = 0x%0*x = 0b",
reg->address,
iDigits, uValue);
return string(buff) + string(bits);
}
return string("");
}
char *register_symbol::toString(char *return_str, int len)
{
if(!return_str)
return 0;
if(reg)
return reg->toString(return_str,len);
*return_str=0;
return return_str;
}
char *register_symbol::toBitStr(char *return_str, int len)
{
if(!return_str)
return 0;
if(reg)
return reg->toBitStr(return_str,len);
*return_str=0;
return return_str;
}
void register_symbol::get(int &i)
{
if(reg) {
i = reg->get_value() & m_uMask;
i >>= m_uMaskShift;
}
else
i = 0;
}
void register_symbol::get(gint64 &i)
{
if(reg) {
i = reg->get_value() & m_uMask;
i >>= m_uMaskShift;
}
else
i = 0;
}
void register_symbol::get(char *buffer, int buf_size)
{
if(buffer) {
int v;
get(v);
snprintf(buffer,buf_size,"%d",v);
}
}
void register_symbol::get(Packet &p)
{
if(reg) {
int i;
get(i);
p.EncodeUInt32(i);
}
}
void register_symbol::set(int new_value)
{
if(reg)
reg->putRV(RegisterValue(SetMaskedValue(new_value),0));
}
void register_symbol::set(Value *v)
{
if(reg && v) {
int i;
v->get(i);
reg->putRV(RegisterValue(SetMaskedValue(i),0));
}
}
void register_symbol::set(const char *buffer, int buf_size)
{
if(buffer) {
int i;
int converted=0;
// if a straight decimal conversion fails, then try hexadecimal.
converted = sscanf(buffer, "0x%x", &i);
if(!converted)
converted = sscanf(buffer, "%d", &i);
if(!converted)
converted = sscanf(buffer, "$%x", &i);
if(converted)
set(i);
}
}
unsigned int register_symbol::SetMaskedValue(unsigned int uValue) {
Register *reg = getReg();
unsigned int uCurrentValue = reg ? reg->get_value() & m_uMask: 0;
// turn off masked bits in uCurrentValue
uCurrentValue &= ~m_uMask;
// turn off non-mask bits in uValue
uValue = uValue << m_uMaskShift;
uValue &= m_uMask;
// map the passed in value into the target
uCurrentValue |= ((long)uValue);
return uCurrentValue;
}
void register_symbol::set(Packet &p)
{
unsigned int i;
if(p.DecodeUInt32(i)) {
set((int)i);
}
}
bool register_symbol::compare(ComparisonOperator *compOp, Value *rvalue)
{
if(!compOp || !rvalue)
return false;
gint64 i,r;
get(i);
rvalue->get(r);
if(i < r)
return compOp->less();
if(i > r)
return compOp->greater();
return compOp->equal();
}
void register_symbol::update(void) {
reg->update();
}
symbol *register_symbol::copy()
{
return new register_symbol(*this);
}
Register *register_symbol::getReg()
{
return reg;
}
Value* register_symbol::evaluate() {
gint64 v;
get(v);
return new Integer(v);
}
int register_symbol::set_break(ObjectBreakTypes bt, ObjectActionTypes at,
Expression *pExpr)
{
return get_bp().set_break(bt,at, reg,pExpr);
}
int register_symbol::clear_break()
{
cout << showType() << " objects breakpoints can only be cleared by 'clear #'\n where # is the breakpoint number\n";
return -1;
}
//------------------------------------------------------------------------
w_symbol::w_symbol(const char *_name, Register *_reg)
: register_symbol(_name, _reg)
{
}
string w_symbol::toString()
{
if(reg) {
char buff[256];
char bits[256];
reg->toBitStr(bits,sizeof(bits));
snprintf(buff,sizeof(buff)," = 0x%02x = 0b", reg->get_value() & 0xff);
return string(buff) + string(bits);
}
return string("");
}
//------------------------------------------------------------------------
ioport_symbol::ioport_symbol(PortRegister *_ioport)
: register_symbol(_ioport->name().c_str(), _ioport)
{
}
//------------------------------------------------------------------------
address_symbol::address_symbol(const char *_name, unsigned int _val)
: Integer(_val)
{
new_name(_name);
}
string address_symbol::toString()
{
char buf[256];
int i = (int)getVal();
snprintf(buf,sizeof(buf), " at address %d = 0x%X",i,i);
return string(buf);
}
Value* address_symbol::evaluate()
{
return copy();
}
int address_symbol::set_break(ObjectBreakTypes bt, ObjectActionTypes at,
Expression *pExpr)
{
if (bt == gpsimObject::eBreakExecute)
return get_bp().set_execution_break(get_active_cpu(),getVal(),pExpr);
return -1;
}
line_number_symbol::line_number_symbol(const char *_name, unsigned int _val)
: address_symbol(_name,_val)
{
if(!_name) {
char buf[64];
snprintf(buf,sizeof(buf), "line_%04x",_val);
new_name(buf);
}
}
//------------------------------------------------------------------------
module_symbol::module_symbol(Module *_module, const char *_name)
: symbol(_name), module(_module)
{
}
Value *module_symbol::copy()
{
cout << "copying module symbol: " << name() << endl;
return new module_symbol(module,name().c_str());
}
void module_symbol::set(const char *cP,int len)
{
throw new Error("object cannot be assigned a value\n");
}
void module_symbol::get(char *cP, int len)
{
if(cP) {
*cP = 0;
}
}
string module_symbol::description()
{
return module ? module->description() : string("no description");
}
string module_symbol::toString()
{
return module ? module->toString() : name();
}
//------------------------------------------------------------------------
attribute_symbol::attribute_symbol(Module *_module, Value *_attribute)
: module_symbol(_module, 0) , attribute(_attribute)
{
if(module && attribute) {
char buf[256];
snprintf(buf,sizeof(buf),"%s.%s",module->name().c_str(), attribute->name().c_str());
if(verbose)
cout << "creating attribute symbol named: " << buf << endl;
new_name(buf);
attribute->new_name(buf);
}
}
string attribute_symbol::toString()
{
if(attribute)
return attribute->toString();
else
return string("(null)");
}
char *attribute_symbol::toString(char *return_str, int len)
{
if(attribute)
return attribute->toString(return_str,len);
else if(return_str)
*return_str=0;
return return_str;
}
char *attribute_symbol::toBitStr(char *return_str, int len)
{
if(attribute)
return attribute->toBitStr(return_str,len);
else if(return_str)
*return_str=0;
return return_str;
}
string attribute_symbol::description()
{
if(attribute)
return attribute->description();
else
return string("no attribute"); // <-- this has to be an error
}
Value *attribute_symbol::copy()
{
if (attribute)
return attribute->copy();
return copy();
}
Value* attribute_symbol::evaluate()
{
return copy();
}
void attribute_symbol::set(double d)
{
if(attribute)
attribute->set(d);
}
void attribute_symbol::set(gint64 i)
{
if(attribute)
attribute->set(i);
}
void attribute_symbol::set(int i)
{
if(attribute)
attribute->set(i);
}
void attribute_symbol::set(Value *v)
{
if(attribute)
attribute->set(v);
}
void attribute_symbol::set(const char *cp,int len)
{
if(attribute)
attribute->set(cp,len);
}
void attribute_symbol::set(Expression *e)
{
if(attribute)
attribute->set(e);
}
void attribute_symbol::set(Packet &p)
{
if(attribute)
attribute->set(p);
}
void attribute_symbol::get(int &i)
{
if(attribute)
attribute->get(i);
}
void attribute_symbol::get(gint64 &i)
{
if(attribute)
attribute->get(i);
}
void attribute_symbol::get(double &d)
{
if(attribute)
attribute->get(d);
}
void attribute_symbol::get(char *c, int len)
{
if(attribute)
attribute->get(c,len);
}
void attribute_symbol::get(Packet &p)
{
if(attribute)
attribute->get(p);
}
void attribute_symbol::get(Value **v)
{
if(attribute && v)
*v = attribute;
}
void attribute_symbol::set_xref(Value *v)
{
if(attribute) {
attribute->set_xref(v);
}
Value::set_xref(v);
}
Value *attribute_symbol::get_xref()
{
if(attribute)
return attribute->get_xref();
return Value::get_xref();
}
//------------------------------------------------------------------------
stimulus_symbol::stimulus_symbol(stimulus *_s)
: symbol(_s->name().c_str()), s(_s)
{
}
//------------------------------------------------------------------------
string &stimulus_symbol::name() const
{
if(s)
return s->name();
return Value::name();
}
char *stimulus_symbol::name(char *pName, int len) {
if(s)
return s->name(pName, len);
return Value::name(pName, len);
}
void stimulus_symbol::new_name(const char *pNewName) {
if(s)
return s->new_name(pNewName);
return Value::new_name(pNewName);
}
void stimulus_symbol::new_name(string &sNewName) {
if(s)
return s->new_name(sNewName);
return Value::new_name(sNewName);
}
string stimulus_symbol::toString()
{
if(s)
return s->toString();
return name();
}
//------------------------------------------------------------------------
val_symbol::val_symbol(gpsimValue *v)
: symbol((char*)0)
{
if(!v)
throw string(" val_symbol");
val = v;
}
string val_symbol::toString()
{
return val->toString();
}
void val_symbol::get(int &i)
{
if (val)
i = val->get_value();
else
i = 0;
}
void val_symbol::get(gint64 &i)
{
if (val)
i = val->get_value();
else
i = 0;
}
void val_symbol::set(int new_value)
{
if(val)
val->put_value(new_value);
}
void val_symbol::set(gint64 new_value)
{
if(val)
val->put_value((int)new_value);
}
string &val_symbol::name(void) const
{
return val->name();
}
symbol *val_symbol::copy()
{
return new val_symbol(val);
}
bool val_symbol::compare(ComparisonOperator *compOp, Value *rvalue)
{
if(!compOp || !rvalue)
return false;
gint64 i,r;
get(i);
rvalue->get(r);
if(i < r)
return compOp->less();
if(i > r)
return compOp->greater();
return compOp->equal();
}
syntax highlighted by Code2HTML, v. 0.9.1