You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ktechlab/src/electronics/gpsimprocessor.cpp

881 lines
22 KiB

/***************************************************************************
* Copyright (C) 2005 by David Saxton *
* david@bluehaze.org *
* *
* This program 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 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "config.h"
#ifndef NO_GPSIM
#include "asmparser.h"
#include "debugmanager.h"
#include "flowcodedocument.h"
#include "gpsimprocessor.h"
#include "language.h"
#include "languagemanager.h"
#include "microlibrary.h"
#include "processchain.h"
#include "simulator.h"
#include <assert.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <ktempfile.h>
#include <kstandarddirs.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <tqtimer.h>
#include "gpsim/cod.h"
#include "gpsim/interface.h"
#include "gpsim/gpsim_classes.h"
#include "gpsim/pic-processor.h"
#include "gpsim/registers.h"
#include "gpsim/14bit-registers.h"
#include "gpsim/symbol.h"
#include "gpsim/sim_context.h"
bool bDoneGpsimInit = false;
bool bUseGUI = true;
// extern "C" void initialize_gpsim();
// void initialize_gpsim(void);
extern void initialize_commands();
void initialize_ConsoleUI();
extern void initialize_readline();
extern void gui_main(void);
extern void cli_main();
void gpsim_version() {};
void quit_gui() {};
//BEGIN class GpsimProcessor
/**
Work around a bug in gpsim: the directory in a filename is recorded twice, e.g.
"/home/david/afile.asm" is recorded as "/home/david//home/david/afile.asm". This
function will remove the duplicated directory path (by searching for a "//").
*/
TQString sanitizeGpsimFile( TQString file )
{
int pos = file.find("//");
if ( pos != -1 )
{
file.remove( 0, pos + 1 );
}
return file;
}
GpsimProcessor::GpsimProcessor( TQString symbolFile, TQObject *tqparent )
: TQObject(tqparent),
m_symbolFile(symbolFile)
{
if (!bDoneGpsimInit)
{
#ifndef GPSIM_0_21_4
initialize_ConsoleUI();
#endif
initialize_gpsim_core();
initialization_is_complete();
bDoneGpsimInit = true;
}
m_bCanExecuteNextCycle = true;
m_bIsRunning = false;
m_pPicProcessor = 0l;
m_codLoadtqStatus = CodUnknown;
m_pRegisterMemory = 0l;
m_debugMode = GpsimDebugger::AsmDebugger;
m_pDebugger[0] = m_pDebugger[1] = 0l;
Processor * tempProcessor = 0l;
const char * fileName = symbolFile.ascii();
#ifdef GPSIM_0_21_4
switch ( (cod_errors)load_symbol_file( &tempProcessor, fileName ) )
{
case COD_SUCCESS:
m_codLoadtqStatus = CodSuccess;
break;
case COD_FILE_NOT_FOUND:
m_codLoadtqStatus = CodFileNotFound;
break;
case COD_UNRECOGNIZED_PROCESSOR:
m_codLoadtqStatus = CodUnrecognizedProcessor;
break;
case COD_FILE_NAME_TOO_LONG:
m_codLoadtqStatus = CodFileNameTooLong;
break;
case COD_LST_NOT_FOUND:
m_codLoadtqStatus = CodLstNotFound;
break;
case COD_BAD_FILE:
m_codLoadtqStatus = CodBadFile;
break;
default:
m_codLoadtqStatus = CodUnknown;
}
#else // GPSIM_0_21_11+
FILE * pFile = fopen( fileName, "r" );
if ( !pFile )
m_codLoadtqStatus = CodFileUnreadable;
else
m_codLoadtqStatus = ( ProgramFileTypeList::GetList().LoadProgramFile( & tempProcessor, fileName, pFile ) ) ? CodSuccess : CodFailure;
#endif
m_pPicProcessor = dynamic_cast<pic_processor*>(tempProcessor);
if ( codLoadtqStatus() == CodSuccess )
{
m_pRegisterMemory = new RegisterSet( m_pPicProcessor );
m_pDebugger[0] = new GpsimDebugger( GpsimDebugger::AsmDebugger, this );
m_pDebugger[1] = new GpsimDebugger( GpsimDebugger::HLLDebugger, this );
Simulator::self()->attachGpsimProcessor(this);
DebugManager::self()->registerGpsim(this);
}
}
GpsimProcessor::~GpsimProcessor()
{
Simulator::self()->detachGpsimProcessor(this);
delete m_pRegisterMemory;
if ( m_pDebugger[0] )
m_pDebugger[0]->deleteLater();
if ( m_pDebugger[1] )
m_pDebugger[1]->deleteLater();
}
void GpsimProcessor::displayCodLoadtqStatus( )
{
switch (m_codLoadtqStatus)
{
case CodSuccess:
break;
case CodFileNotFound:
KMessageBox::sorry( 0l, i18n("The cod file \"%1\" was not found.").tqarg(m_symbolFile), i18n("File Not Found") );
break;
case CodUnrecognizedProcessor:
KMessageBox::sorry( 0l, i18n("The processor for cod file \"%1\" is unrecognized.").tqarg(m_symbolFile), i18n("Unrecognized Processor") );
break;
case CodFileNameTooLong:
KMessageBox::sorry( 0l, i18n("The file name \"%1\" is too long.").tqarg(m_symbolFile), i18n("Filename Too Long") );
break;
case CodLstNotFound:
KMessageBox::sorry( 0l, i18n("The lst file associated with the cod file \"%1\" was not found.").tqarg(m_symbolFile), i18n("LST File Not Found") );
break;
case CodBadFile:
KMessageBox::sorry( 0l, i18n("The cod file \"%1\" is bad.").tqarg(m_symbolFile), i18n("Bad File") );
break;
case CodFileUnreadable:
KMessageBox::sorry( 0l, i18n("The cod file \"%1\" could not be read from.").tqarg(m_symbolFile), i18n("Unreadable File") );
break;
case CodFailure:
case CodUnknown:
KMessageBox::sorry( 0l, i18n("An error occured with the cod file \"%1\".").tqarg(m_symbolFile), i18n("Error") );
break;
}
}
unsigned GpsimProcessor::programMemorySize() const
{
return m_pPicProcessor->program_memory_size();
}
TQStringList GpsimProcessor::sourceFileList()
{
TQStringList files;
// Work around nasty bug in gpsim 0.21.4 where nsrc_files value might be used uninitiazed
int max = m_pPicProcessor->files.nsrc_files();
#ifdef GPSIM_0_21_4
if ( max > 10 )
max = 10;
#endif
for ( int i = 0; i < max; ++i )
{
if ( !m_pPicProcessor->files[i] )
continue;
files << sanitizeGpsimFile( m_pPicProcessor->files[i]->name().c_str() );
}
return files;
}
void GpsimProcessor::emitLineReached()
{
m_pDebugger[0]->emitLineReached();
m_pDebugger[1]->emitLineReached();
}
void GpsimProcessor::setRunning( bool run )
{
if ( m_bIsRunning == run )
return;
m_bIsRunning = run;
emit runningStatusChanged(run);
}
void GpsimProcessor::executeNext()
{
if ( !m_bIsRunning )
return;
if ( !m_bCanExecuteNextCycle )
{
m_bCanExecuteNextCycle = true;
return;
}
unsigned long long beforeExecuteCount = get_cycles().get();
m_pPicProcessor->step_one(false); // Don't know what the false is for; gpsim ignores its value anyway
// Some instructions take more than one cycle to execute, so ignore next cycle if this was the case
if ( (get_cycles().get() - beforeExecuteCount) > 1 )
m_bCanExecuteNextCycle = false;
currentDebugger()->checkForBreak();
// Let's also update the values of RegisterInfo every 50 milliseconds
if ( (beforeExecuteCount % 20000) == 0 )
registerMemory()->update();
}
void GpsimProcessor::reset()
{
bool wasRunning = isRunning();
m_pPicProcessor->reset(SIM_RESET);
setRunning(false);
if (!wasRunning)
{
// If we weren't running before, then the next signal won't have been emitted
emitLineReached();
}
}
MicroInfo * GpsimProcessor::microInfo( ) const
{
if ( !m_pPicProcessor )
return 0l;
return MicroLibrary::self()->microInfoWithID( m_pPicProcessor->name().c_str() );
}
int GpsimProcessor::operandRegister( unsigned address )
{
instruction * ins = m_pPicProcessor->program_memory[ address ];
if ( Register_op * reg = dynamic_cast<Register_op*>(ins) )
return reg->register_address;
return -1;
}
int GpsimProcessor::operandLiteral( unsigned address )
{
instruction * ins = m_pPicProcessor->program_memory[ address ];
if ( Literal_op * lit = dynamic_cast<Literal_op*>(ins) )
return lit->L;
return -1;
}
GpsimProcessor::ProgramFileValidity GpsimProcessor::isValidProgramFile( const TQString & programFile )
{
if ( !KStandardDirs::exists(programFile) )
return DoesntExist;
TQString extension = programFile.right( programFile.length() - programFile.findRev('.') - 1 ).lower();
if ( extension == "flowcode" ||
extension == "asm" ||
extension == "cod" ||
extension == "basic" || extension == "microbe" ||
extension == "c" )
return Valid;
if ( extension == "hex" && TQFile::exists( TQString(programFile).replace(".hex",".cod") ) )
return Valid;
return IncorrectType;
}
TQString GpsimProcessor::generateSymbolFile( const TQString &fileName, TQObject *receiver, const char *successMember, const char * failMember )
{
if ( !isValidProgramFile(fileName) )
return TQString();
TQString extension = fileName.right( fileName.length() - fileName.findRev('.') - 1 ).lower();
if ( extension == "cod" )
{
TQTimer::singleShot( 0, receiver, successMember );
return fileName;
}
if ( extension == "hex" )
{
TQTimer::singleShot( 0, receiver, successMember );
// We've already checked for the existance of the ".cod" file in GpsimProcessor::isValidProgramFile
return TQString(fileName).replace(".hex",".cod");
}
else if ( extension == "basic" || extension == "microbe" )
{
compileMicrobe( fileName, receiver, successMember, failMember );
return TQString(fileName).replace( "."+extension, ".cod" );
}
else if ( extension == "flowcode" )
{
const TQString hexFile = KTempFile( TQString(), ".hex" ).name();
ProcessOptions o;
o.b_addToProject = false;
o.setTargetFile( hexFile );
o.setInputFiles( fileName );
o.setMethod( ProcessOptions::Method::Forget );
o.setProcessPath( ProcessOptions::ProcessPath::FlowCode_Program );
ProcessChain * pc = LanguageManager::self()->compile(o);
if (receiver)
{
if (successMember)
connect( pc, TQT_SIGNAL(successful()), receiver, successMember );
if (failMember)
connect( pc, TQT_SIGNAL(failed()), receiver, failMember );
}
return TQString(hexFile).replace( ".hex", ".cod" );
}
else if ( extension == "asm" )
{
ProcessOptions o;
o.b_addToProject = false;
o.setTargetFile( TQString(fileName).replace(".asm",".hex"));
o.setInputFiles(fileName);
o.setMethod( ProcessOptions::Method::Forget );
o.setProcessPath( ProcessOptions::ProcessPath::path( ProcessOptions::guessMediaType(fileName), ProcessOptions::ProcessPath::Program ) );
ProcessChain *pc = LanguageManager::self()->compile(o);
if (receiver)
{
if (successMember)
connect( pc, TQT_SIGNAL(successful()), receiver, successMember );
if (failMember)
connect( pc, TQT_SIGNAL(failed()), receiver, failMember );
}
return TQString(fileName).replace(".asm",".cod");
}
else if ( extension == "c" )
{
ProcessOptions o;
o.b_addToProject = false;
o.setTargetFile( TQString(fileName).replace(".c",".hex"));
o.setInputFiles(fileName);
o.setMethod( ProcessOptions::Method::Forget );
o.setProcessPath( ProcessOptions::ProcessPath::C_Program );
ProcessChain *pc = LanguageManager::self()->compile(o);
if (receiver)
{
if (successMember)
connect( pc, TQT_SIGNAL(successful()), receiver, successMember );
if (failMember)
connect( pc, TQT_SIGNAL(failed()), receiver, failMember );
}
return TQString(fileName).replace(".c",".cod");
}
if ( failMember )
TQTimer::singleShot( 0, receiver, failMember );
return TQString();
}
void GpsimProcessor::compileMicrobe( const TQString &filename, TQObject *receiver, const char * successMember, const char * failMember )
{
ProcessOptions o;
o.b_addToProject = false;
o.setTargetFile( TQString(filename).replace(".microbe",".hex") );
o.setInputFiles(filename);
o.setMethod( ProcessOptions::Method::Forget );
o.setProcessPath( ProcessOptions::ProcessPath::Microbe_Program );
ProcessChain * pc = LanguageManager::self()->compile(o);
if (receiver)
{
if (successMember)
connect( pc, TQT_SIGNAL(successful()), receiver, successMember );
if (failMember)
connect( pc, TQT_SIGNAL(failed()), receiver, failMember );
}
}
//END class GpsimProcessor
//BEGIN class GpsimDebugger
GpsimDebugger::GpsimDebugger( Type type, GpsimProcessor * gpsim )
: TQObject()
{
m_pGpsim = gpsim;
m_type = type;
m_pBreakFromOldLine = 0l;
m_addressToLineMap = 0l;
m_stackLevelLowerBreak = -1;
m_addressSize = 0;
connect( m_pGpsim, TQT_SIGNAL(runningStatusChanged(bool )), this, TQT_SLOT(gpsimRunningStatusChanged(bool )) );
if ( type == HLLDebugger )
{
const TQStringList sourceFileList = m_pGpsim->sourceFileList();
TQStringList::const_iterator sflEnd = sourceFileList.end();
for ( TQStringList::const_iterator it = sourceFileList.begin(); it != sflEnd; ++it )
{
AsmParser p(*it);
p.parse(this);
}
}
initAddressToLineMap();
}
GpsimDebugger::~GpsimDebugger()
{
TQValueList<DebugLine*> debugLinesToDelete;
for ( unsigned i = 0; i < m_addressSize; ++i )
{
DebugLine * dl = m_addressToLineMap[i];
if ( !dl || dl->markedAsDeleted() )
continue;
dl->markAsDeleted();
debugLinesToDelete += dl;
}
const TQValueList<DebugLine*>::iterator end = debugLinesToDelete.end();
for ( TQValueList<DebugLine*>::iterator it = debugLinesToDelete.begin(); it != end; ++it )
delete *it;
delete [] m_addressToLineMap;
}
void GpsimDebugger::gpsimRunningStatusChanged( bool isRunning )
{
if (!isRunning)
{
m_stackLevelLowerBreak = -1;
m_pBreakFromOldLine = 0l;
emitLineReached();
}
}
void GpsimDebugger::associateLine( const TQString & sourceFile, int sourceLine, const TQString & assemblyFile, int assemblyLine )
{
if ( assemblyLine < 0 || sourceLine < 0 )
{
kdWarning() << k_funcinfo << "Invalid lines: assemblyLine="<<assemblyLine<<" sourceLine="<<sourceLine<<endl;
return;
}
SourceLine hllSource = SourceLine( sourceFile, sourceLine );
SourceLine asmSource = SourceLine( assemblyFile, assemblyLine );
if ( m_sourceLineMap.contains(asmSource) )
{
kdWarning() << k_funcinfo << "Already have an association for assembly (\""<<assemblyFile<<"\","<<assemblyLine<<")"<<endl;
return;
}
m_sourceLineMap[asmSource] = hllSource;
}
void GpsimDebugger::initAddressToLineMap()
{
m_addressSize = m_pGpsim->programMemorySize();
delete [] m_addressToLineMap;
m_addressToLineMap = new DebugLine*[m_addressSize];
memset( m_addressToLineMap, 0, m_addressSize * sizeof(DebugLine*) );
if ( m_type == AsmDebugger )
{
for ( unsigned i = 0; i < m_addressSize; ++i )
{
int line = m_pGpsim->picProcessor()->pma->get_src_line(i) - 1;
int fileID = m_pGpsim->picProcessor()->pma->get_file_id(i);
FileContext * fileContext = m_pGpsim->picProcessor()->files[fileID];
if (fileContext)
m_addressToLineMap[i] = new DebugLine( sanitizeGpsimFile( fileContext->name().c_str() ), line );
}
}
else
{
SourceLineMap::const_iterator slmEnd = m_sourceLineMap.end();
for ( SourceLineMap::const_iterator it = m_sourceLineMap.begin(); it != slmEnd; ++it )
{
SourceLineMap::const_iterator next = it;
++next;
int asmToLine = ((next == slmEnd) || (next.key().fileName() != it.key().fileName())) ? -1 : next.key().line() - 1;
TQString asmFile = it.key().fileName();
int asmFromLine = it.key().line();
SourceLine sourceLine = it.data();
std::string stdAsmFile( asmFile.ascii() );
int fileID = m_pGpsim->picProcessor()->files.Find( stdAsmFile );
if ( fileID == -1 )
{
kdWarning() << k_funcinfo << "Could not find FileContext (asmFile=\""<<asmFile<<"\")"<<endl;
continue;
}
if ( asmToLine == -1 )
asmToLine = m_pGpsim->picProcessor()->files[fileID]->max_line() - 2;
if ( (asmFromLine < 0) || (asmToLine < asmFromLine) )
{
kdWarning() << k_funcinfo << "Invalid lines: asmFromLine="<<asmFromLine<<" asmToLine="<<asmToLine<<endl;
continue;
}
DebugLine * debugLine = new DebugLine( sourceLine.fileName(), sourceLine.line() );
bool used = false;
for ( int i = asmFromLine; i <= asmToLine; ++i )
{
#ifdef GPSIM_0_21_4
int address = m_pGpsim->picProcessor()->pma->find_address_from_line( fileID, i+1 );
#else // GPSIM_0_21_11
int address = m_pGpsim->picProcessor()->pma->find_address_from_line( m_pGpsim->picProcessor()->files[fileID], i+1 );
#endif
if ( address != -1 )
{
used = true;
m_addressToLineMap[address] = debugLine;
}
}
if (!used)
delete debugLine;
}
}
}
void GpsimDebugger::setBreakpoints( const TQString & path, const IntList & lines )
{
for ( unsigned i = 0; i < m_addressSize; i++ )
{
DebugLine * dl = m_addressToLineMap[i];
if ( !dl || dl->fileName() != path )
continue;
dl->setBreakpoint( lines.contains( dl->line() ) );
}
}
void GpsimDebugger::setBreakpoint( const TQString & path, int line, bool isBreakpoint )
{
for ( unsigned i = 0; i < m_addressSize; i++ )
{
if ( !m_addressToLineMap[i] )
continue;
if ( (m_addressToLineMap[i]->fileName() == path) &&
( line == m_addressToLineMap[i]->line() ) )
m_addressToLineMap[i]->setBreakpoint(isBreakpoint);
}
}
DebugLine * GpsimDebugger::currentDebugLine()
{
return m_addressToLineMap[ m_pGpsim->picProcessor()->pc->get_value() ];
}
SourceLine GpsimDebugger::currentLine()
{
DebugLine * dl = currentDebugLine();
return dl ? *dl : SourceLine();
}
void GpsimDebugger::emitLineReached()
{
SourceLine currentAt = currentLine();
if ( currentAt == m_previousAtLineEmit )
return;
m_previousAtLineEmit = currentAt;
m_pGpsim->registerMemory()->update();
emit lineReached(currentAt);
}
void GpsimDebugger::checkForBreak()
{
DebugLine * currentLine = m_addressToLineMap[ m_pGpsim->picProcessor()->pc->get_value() ];
int currentStackLevel = int( m_pGpsim->picProcessor()->stack->pointer & m_pGpsim->picProcessor()->stack->stack_mask );
bool ontoNextLine = m_pBreakFromOldLine != currentLine;
bool lineBreakpoint = currentLine ? currentLine->isBreakpoint() : false;
bool stackBreakpoint = m_stackLevelLowerBreak >= currentStackLevel;
if ( ontoNextLine && (lineBreakpoint || stackBreakpoint) )
m_pGpsim->setRunning(false);
}
int GpsimDebugger::programAddress( const TQString & path, int line )
{
for ( unsigned i = 0; i < m_addressSize; ++i )
{
DebugLine * dl = m_addressToLineMap[i];
if ( !dl || (dl->line() != line) || (dl->fileName() != path) )
continue;
return i;
}
return -1;
}
void GpsimDebugger::stepInto()
{
// I'm not aware of the stack being able to increase in size by more than
// one at a time, so "1" should suffice here...but to be on the safe side,
// make it a nice large number
stackStep( 1 << 16 );
}
void GpsimDebugger::stepOver()
{
stackStep(0);
}
void GpsimDebugger::stepOut()
{
stackStep(-1);
}
void GpsimDebugger::stackStep( int dl )
{
if ( m_pGpsim->isRunning() )
return;
int initialStack = (m_pGpsim->picProcessor()->stack->pointer & m_pGpsim->picProcessor()->stack->stack_mask) + dl;
DebugLine * initialLine = currentDebugLine();
if ( initialStack < 0 )
initialStack = 0;
// Reset any previous stackStep, and step
m_pBreakFromOldLine = 0l;
m_stackLevelLowerBreak = -1;
m_pGpsim->picProcessor()->step_one(false);
int currentStack = m_pGpsim->picProcessor()->stack->pointer & m_pGpsim->picProcessor()->stack->stack_mask;
DebugLine * currentLine = currentDebugLine();
if ( (initialStack >= currentStack) && (initialLine != currentLine) )
emitLineReached();
else
{
// Looks like we stepped into something or haven't gone onto the next
// instruction, wait until we step back out....
m_stackLevelLowerBreak = initialStack;
m_pBreakFromOldLine = initialLine;
m_pGpsim->setRunning(true);
}
}
//END class Debugger
//BEGIN class RegisterSet
RegisterSet::RegisterSet( pic_processor * picProcessor )
{
unsigned numRegisters = picProcessor->rma.get_size();
m_registers.resize( numRegisters, 0l );
for ( unsigned i = 0; i < numRegisters; ++i )
{
RegisterInfo * info = new RegisterInfo( & picProcessor->rma[i] );
m_registers[i] = info;
m_nameToRegisterMap[ info->name() ] = info;
}
RegisterInfo * info = new RegisterInfo( picProcessor->W );
m_registers.append( info );
m_nameToRegisterMap[ info->name() ] = info;
}
RegisterSet::~RegisterSet()
{
for ( unsigned i = 0; i < m_registers.size(); ++i )
delete m_registers[i];
}
RegisterInfo * RegisterSet::fromAddress( unsigned address )
{
return (address < m_registers.size()) ? m_registers[address] : 0l;
}
RegisterInfo * RegisterSet::fromName( const TQString & name )
{
// First try the name as case sensitive, then as case insensitive.
if ( m_nameToRegisterMap.contains( name ) )
return m_nameToRegisterMap[ name ];
TQString nameLower = name.lower();
RegisterInfoMap::iterator end = m_nameToRegisterMap.end();
for ( RegisterInfoMap::iterator it = m_nameToRegisterMap.begin(); it != end; ++ it )
{
if ( it.key().lower() == nameLower )
return it.data();
}
return 0l;
}
void RegisterSet::update()
{
for ( unsigned i = 0; i < m_registers.size(); ++i )
m_registers[i]->update();
}
//END class RegisterSet
//BEGIN class RegisterInfo
RegisterInfo::RegisterInfo( Register * reg )
{
assert(reg);
m_pRegister = reg;
m_type = Invalid;
m_prevEmitValue = 0;
switch ( m_pRegister->isa() )
{
case Register::GENERIC_REGISTER:
m_type = Generic;
break;
case Register::FILE_REGISTER:
m_type = File;
break;
case Register::SFR_REGISTER:
m_type = SFR;
break;
case Register::BP_REGISTER:
m_type = Breakpoint;
break;
case Register::INVALID_REGISTER:
m_type = Invalid;
break;
}
m_name = m_pRegister->baseName();
}
unsigned RegisterInfo::value() const
{
return m_pRegister->value.data;
}
void RegisterInfo::update()
{
unsigned newValue = value();
if ( newValue != m_prevEmitValue )
{
m_prevEmitValue = newValue;
emit valueChanged(newValue);
}
}
TQString RegisterInfo::toString( RegisterType type )
{
switch ( type )
{
case Generic:
return i18n("Generic");
case File:
return i18n("File");
case SFR:
return i18n("SFR");
case Breakpoint:
return i18n("Breakpoint");
case Invalid:
return i18n("Invalid");
}
return i18n("Unknown");
}
//END class RegisterInfo
//BEGIN class DebugLine
DebugLine::DebugLine( const TQString & fileName, int line )
: SourceLine( fileName, line )
{
m_bIsBreakpoint = false;
m_bMarkedAsDeleted = false;
}
DebugLine::DebugLine()
: SourceLine()
{
m_bIsBreakpoint = false;
m_bMarkedAsDeleted = false;
}
//END class DebugLine
#include "gpsimprocessor.moc"
#endif