File indexing completed on 2024-12-01 11:20:28
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "config.h" 0012 #ifndef NO_GPSIM 0013 0014 #include "asmparser.h" 0015 #include "debugmanager.h" 0016 #include "flowcodedocument.h" 0017 #include "gpsimprocessor.h" 0018 #include "language.h" 0019 #include "languagemanager.h" 0020 #include "microlibrary.h" 0021 #include "processchain.h" 0022 #include "simulator.h" 0023 0024 #include <cassert> 0025 0026 #include <KLocalizedString> 0027 #include <KMessageBox> 0028 0029 #include <QDir> 0030 #include <QFile> 0031 #include <QTemporaryFile> 0032 #include <QTextStream> 0033 #include <QTimer> 0034 0035 #include <ktechlab_debug.h> 0036 0037 // gpsim has problems with dependent include headers 0038 // clang-format off 0039 #include "gpsim/cod.h" 0040 #include "gpsim/interface.h" 0041 #include "gpsim/gpsim_classes.h" 0042 #include "gpsim/pic-processor.h" 0043 #include "gpsim/registers.h" 0044 #include "gpsim/14bit-registers.h" 0045 #include "gpsim/sim_context.h" 0046 #include "gpsim/symbol.h" 0047 // clang-format on 0048 0049 bool bDoneGpsimInit = false; 0050 bool bUseGUI = true; 0051 // extern "C" void initialize_gpsim(); 0052 // void initialize_gpsim(void); 0053 extern void initialize_commands(); 0054 extern void initialize_readline(); 0055 extern void gui_main(void); 0056 extern void cli_main(); 0057 void gpsim_version() 0058 { 0059 } 0060 void quit_gui() 0061 { 0062 } 0063 0064 // BEGIN class GpsimProcessor 0065 /** 0066 Work around a bug in gpsim: the directory in a filename is recorded twice, e.g. 0067 "/home/david/afile.asm" is recorded as "/home/david//home/david/afile.asm". This 0068 function will remove the duplicated directory path (by searching for a "//"). 0069 */ 0070 QString sanitizeGpsimFile(QString file) 0071 { 0072 int pos = file.indexOf("//"); 0073 if (pos != -1) { 0074 file.remove(0, pos + 1); 0075 } 0076 return file; 0077 } 0078 0079 GpsimProcessor::GpsimProcessor(QString symbolFile, QObject *parent) 0080 : QObject(parent) 0081 , m_symbolFile(symbolFile) 0082 { 0083 if (!bDoneGpsimInit) { 0084 initialize_gpsim_core(); 0085 initialization_is_complete(); 0086 0087 bDoneGpsimInit = true; 0088 } 0089 0090 m_bCanExecuteNextCycle = true; 0091 m_bIsRunning = false; 0092 m_pPicProcessor = nullptr; 0093 m_codLoadStatus = CodUnknown; 0094 m_pRegisterMemory = nullptr; 0095 m_debugMode = GpsimDebugger::AsmDebugger; 0096 m_pDebugger[0] = m_pDebugger[1] = nullptr; 0097 0098 Processor *tempProcessor = nullptr; 0099 const QByteArray fileName = QFile::encodeName(symbolFile); 0100 0101 qCDebug(KTL_LOG) << "GPSIM_0_21_11+ GpsimProcessor " << symbolFile; 0102 FILE *pFile = fopen(fileName.constData(), "r"); 0103 if (!pFile) 0104 m_codLoadStatus = CodFileUnreadable; 0105 else 0106 m_codLoadStatus = (ProgramFileTypeList::GetList().LoadProgramFile(&tempProcessor, fileName.constData(), pFile)) ? CodSuccess : CodFailure; 0107 qCDebug(KTL_LOG) << " m_codLoadStatus=" << m_codLoadStatus; 0108 0109 m_pPicProcessor = dynamic_cast<pic_processor *>(tempProcessor); 0110 0111 if (codLoadStatus() == CodSuccess) { 0112 m_pRegisterMemory = new RegisterSet(m_pPicProcessor); 0113 m_pDebugger[0] = new GpsimDebugger(GpsimDebugger::AsmDebugger, this); 0114 m_pDebugger[1] = new GpsimDebugger(GpsimDebugger::HLLDebugger, this); 0115 Simulator::self()->attachGpsimProcessor(this); 0116 DebugManager::self()->registerGpsim(this); 0117 } 0118 } 0119 0120 GpsimProcessor::~GpsimProcessor() 0121 { 0122 if (!Simulator::isDestroyedSim()) { 0123 Simulator::self()->detachGpsimProcessor(this); 0124 } 0125 delete m_pRegisterMemory; 0126 0127 if (m_pDebugger[0]) 0128 m_pDebugger[0]->deleteLater(); 0129 if (m_pDebugger[1]) 0130 m_pDebugger[1]->deleteLater(); 0131 } 0132 0133 void GpsimProcessor::displayCodLoadStatus() 0134 { 0135 switch (m_codLoadStatus) { 0136 case CodSuccess: 0137 break; 0138 case CodFileNotFound: 0139 KMessageBox::error(nullptr, i18n("The cod file \"%1\" was not found.", m_symbolFile), i18n("File Not Found")); 0140 break; 0141 case CodUnrecognizedProcessor: 0142 KMessageBox::error(nullptr, i18n("The processor for cod file \"%1\" is unrecognized.", m_symbolFile), i18n("Unrecognized Processor")); 0143 break; 0144 case CodFileNameTooLong: 0145 KMessageBox::error(nullptr, i18n("The file name \"%1\" is too long.", m_symbolFile), i18n("Filename Too Long")); 0146 break; 0147 case CodLstNotFound: 0148 KMessageBox::error(nullptr, i18n("The lst file associated with the cod file \"%1\" was not found.", m_symbolFile), i18n("LST File Not Found")); 0149 break; 0150 case CodBadFile: 0151 KMessageBox::error(nullptr, i18n("The cod file \"%1\" is bad.", m_symbolFile), i18n("Bad File")); 0152 break; 0153 case CodFileUnreadable: 0154 KMessageBox::error(nullptr, i18n("The cod file \"%1\" could not be read from.", m_symbolFile), i18n("Unreadable File")); 0155 break; 0156 case CodFailure: 0157 case CodUnknown: 0158 KMessageBox::error(nullptr, i18n("An error occurred with the cod file \"%1\".", m_symbolFile), i18n("Error")); 0159 break; 0160 } 0161 } 0162 0163 unsigned GpsimProcessor::programMemorySize() const 0164 { 0165 return m_pPicProcessor->program_memory_size(); 0166 } 0167 0168 QStringList GpsimProcessor::sourceFileList() 0169 { 0170 QStringList files; 0171 0172 int max = m_pPicProcessor->files.nsrc_files(); 0173 0174 for (int i = 0; i < max; ++i) { 0175 if (!m_pPicProcessor->files[i]) 0176 continue; 0177 0178 files << sanitizeGpsimFile(m_pPicProcessor->files[i]->name().c_str()); 0179 } 0180 0181 return files; 0182 } 0183 0184 void GpsimProcessor::emitLineReached() 0185 { 0186 m_pDebugger[0]->emitLineReached(); 0187 m_pDebugger[1]->emitLineReached(); 0188 } 0189 0190 void GpsimProcessor::setRunning(bool run) 0191 { 0192 if (m_bIsRunning == run) 0193 return; 0194 0195 m_bIsRunning = run; 0196 emit runningStatusChanged(run); 0197 } 0198 0199 void GpsimProcessor::executeNext() 0200 { 0201 if (!m_bIsRunning) 0202 return; 0203 0204 if (!m_bCanExecuteNextCycle) { 0205 m_bCanExecuteNextCycle = true; 0206 return; 0207 } 0208 0209 unsigned long long beforeExecuteCount = get_cycles().get(); 0210 0211 if (get_bp().have_interrupt()) { 0212 m_pPicProcessor->interrupt(); 0213 } else { 0214 m_pPicProcessor->step_one(false); // Don't know what the false is for; gpsim ignores its value anyway 0215 0216 // Some instructions take more than one cycle to execute, so ignore next cycle if this was the case 0217 if ((get_cycles().get() - beforeExecuteCount) > 1) 0218 m_bCanExecuteNextCycle = false; 0219 } 0220 0221 currentDebugger()->checkForBreak(); 0222 0223 // Let's also update the values of RegisterInfo every 25 milliseconds 0224 if ((beforeExecuteCount % 10000) == 0) 0225 registerMemory()->update(); 0226 } 0227 0228 void GpsimProcessor::reset() 0229 { 0230 bool wasRunning = isRunning(); 0231 m_pPicProcessor->reset(SIM_RESET); 0232 setRunning(false); 0233 if (!wasRunning) { 0234 // If we weren't running before, then the next signal won't have been emitted 0235 emitLineReached(); 0236 } 0237 } 0238 0239 MicroInfo *GpsimProcessor::microInfo() const 0240 { 0241 if (!m_pPicProcessor) { 0242 qCWarning(KTL_LOG) << " m_pPicProcessor == nullptr"; 0243 return nullptr; 0244 } 0245 0246 return MicroLibrary::self()->microInfoWithID(m_pPicProcessor->name().c_str()); 0247 } 0248 0249 int GpsimProcessor::operandRegister(unsigned address) 0250 { 0251 instruction *ins = m_pPicProcessor->program_memory[address]; 0252 if (Register_op *reg = dynamic_cast<Register_op *>(ins)) 0253 return reg->register_address; 0254 return -1; 0255 } 0256 0257 int GpsimProcessor::operandLiteral(unsigned address) 0258 { 0259 instruction *ins = m_pPicProcessor->program_memory[address]; 0260 if (Literal_op *lit = dynamic_cast<Literal_op *>(ins)) 0261 return lit->L; 0262 return -1; 0263 } 0264 0265 GpsimProcessor::ProgramFileValidity GpsimProcessor::isValidProgramFile(const QString &programFile) 0266 { 0267 if (!QFile::exists(programFile)) 0268 return DoesntExist; 0269 0270 QString extension = programFile.right(programFile.length() - programFile.lastIndexOf('.') - 1).toLower(); 0271 0272 if (extension == "flowcode" || extension == "asm" || extension == "cod" || extension == "basic" || extension == "microbe" || extension == "c") 0273 return Valid; 0274 0275 if (extension == "hex" && QFile::exists(QString(programFile).replace(".hex", ".cod"))) 0276 return Valid; 0277 0278 return IncorrectType; 0279 } 0280 0281 QString GpsimProcessor::generateSymbolFile(const QString &fileName, QObject *receiver, const char *successMember, const char *failMember) 0282 { 0283 qCDebug(KTL_LOG) << "fileName=" << fileName; 0284 if (isValidProgramFile(fileName) != GpsimProcessor::Valid) { 0285 qCDebug(KTL_LOG) << "not valid program file"; 0286 return QString(); 0287 } 0288 0289 QString extension = fileName.right(fileName.length() - fileName.lastIndexOf('.') - 1).toLower(); 0290 0291 if (extension == "cod") { 0292 QTimer::singleShot(0, receiver, successMember); 0293 return fileName; 0294 } 0295 if (extension == "hex") { 0296 QTimer::singleShot(0, receiver, successMember); 0297 // We've already checked for the existance of the ".cod" file in GpsimProcessor::isValidProgramFile 0298 return QString(fileName).replace(".hex", ".cod"); 0299 } 0300 0301 else if (extension == "basic" || extension == "microbe") { 0302 compileMicrobe(fileName, receiver, successMember, failMember); 0303 return QString(fileName).replace("." + extension, ".cod"); 0304 } else if (extension == "flowcode") { 0305 QTemporaryFile tmpFile(QDir::tempPath() + QLatin1String("/ktechlab_XXXXXX.hex")); 0306 if (!tmpFile.open()) { 0307 qCWarning(KTL_LOG) << " failed to open " << tmpFile.fileName() << " error " << tmpFile.errorString(); 0308 return QString(); 0309 } 0310 const QString hexFile = tmpFile.fileName(); 0311 ProcessOptions o; 0312 o.b_addToProject = false; 0313 o.setTargetFile(hexFile); 0314 o.setInputFiles(QStringList(fileName)); 0315 o.setMethod(ProcessOptions::Method::Forget); 0316 o.setProcessPath(ProcessOptions::ProcessPath::FlowCode_Program); 0317 0318 ProcessChain *pc = LanguageManager::self()->compile(o); 0319 if (receiver) { 0320 if (successMember) 0321 connect(pc, SIGNAL(successful()), receiver, successMember); 0322 if (failMember) 0323 connect(pc, SIGNAL(failed()), receiver, failMember); 0324 } 0325 0326 return QString(hexFile).replace(".hex", ".cod"); 0327 } else if (extension == "asm") { 0328 ProcessOptions o; 0329 o.b_addToProject = false; 0330 o.setTargetFile(QString(fileName).replace(".asm", ".hex")); 0331 o.setInputFiles(QStringList(fileName)); 0332 o.setMethod(ProcessOptions::Method::Forget); 0333 o.setProcessPath(ProcessOptions::ProcessPath::path(ProcessOptions::guessMediaType(fileName), ProcessOptions::ProcessPath::Program)); 0334 0335 ProcessChain *pc = LanguageManager::self()->compile(o); 0336 if (receiver) { 0337 if (successMember) 0338 connect(pc, SIGNAL(successful()), receiver, successMember); 0339 if (failMember) 0340 connect(pc, SIGNAL(failed()), receiver, failMember); 0341 } 0342 0343 return QString(fileName).replace(".asm", ".cod"); 0344 } else if (extension == "c") { 0345 ProcessOptions o; 0346 o.b_addToProject = false; 0347 o.setTargetFile(QString(fileName).replace(".c", ".hex")); 0348 o.setInputFiles(QStringList(fileName)); 0349 o.setMethod(ProcessOptions::Method::Forget); 0350 o.setProcessPath(ProcessOptions::ProcessPath::C_Program); 0351 0352 ProcessChain *pc = LanguageManager::self()->compile(o); 0353 if (receiver) { 0354 if (successMember) 0355 connect(pc, SIGNAL(successful()), receiver, successMember); 0356 if (failMember) 0357 connect(pc, SIGNAL(failed()), receiver, failMember); 0358 } 0359 0360 return QString(fileName).replace(".c", ".cod"); 0361 } 0362 0363 if (failMember) 0364 QTimer::singleShot(0, receiver, failMember); 0365 return QString(); 0366 } 0367 0368 void GpsimProcessor::compileMicrobe(const QString &filename, QObject *receiver, const char *successMember, const char *failMember) 0369 { 0370 ProcessOptions o; 0371 o.b_addToProject = false; 0372 o.setTargetFile(QString(filename).replace(".microbe", ".hex")); 0373 o.setInputFiles(QStringList(filename)); 0374 o.setMethod(ProcessOptions::Method::Forget); 0375 o.setProcessPath(ProcessOptions::ProcessPath::Microbe_Program); 0376 ProcessChain *pc = LanguageManager::self()->compile(o); 0377 if (receiver) { 0378 if (successMember) 0379 connect(pc, SIGNAL(successful()), receiver, successMember); 0380 if (failMember) 0381 connect(pc, SIGNAL(failed()), receiver, failMember); 0382 } 0383 } 0384 // END class GpsimProcessor 0385 0386 // BEGIN class GpsimDebugger 0387 GpsimDebugger::GpsimDebugger(Type type, GpsimProcessor *gpsim) 0388 : QObject() 0389 { 0390 m_pGpsim = gpsim; 0391 m_type = type; 0392 m_pBreakFromOldLine = nullptr; 0393 m_addressToLineMap = nullptr; 0394 m_stackLevelLowerBreak = -1; 0395 m_addressSize = 0; 0396 0397 connect(m_pGpsim, &GpsimProcessor::runningStatusChanged, this, &GpsimDebugger::gpsimRunningStatusChanged); 0398 0399 if (type == HLLDebugger) { 0400 const QStringList sourceFileList = m_pGpsim->sourceFileList(); 0401 QStringList::const_iterator sflEnd = sourceFileList.end(); 0402 for (QStringList::const_iterator it = sourceFileList.begin(); it != sflEnd; ++it) { 0403 AsmParser p(*it); 0404 p.parse(this); 0405 } 0406 } 0407 0408 initAddressToLineMap(); 0409 } 0410 0411 GpsimDebugger::~GpsimDebugger() 0412 { 0413 QList<DebugLine *> debugLinesToDelete; 0414 0415 for (unsigned i = 0; i < m_addressSize; ++i) { 0416 DebugLine *dl = m_addressToLineMap[i]; 0417 if (!dl || dl->markedAsDeleted()) 0418 continue; 0419 0420 dl->markAsDeleted(); 0421 debugLinesToDelete += dl; 0422 } 0423 0424 qDeleteAll(debugLinesToDelete); 0425 0426 delete[] m_addressToLineMap; 0427 } 0428 0429 void GpsimDebugger::gpsimRunningStatusChanged(bool isRunning) 0430 { 0431 if (!isRunning) { 0432 m_stackLevelLowerBreak = -1; 0433 m_pBreakFromOldLine = nullptr; 0434 emitLineReached(); 0435 } 0436 } 0437 0438 void GpsimDebugger::associateLine(const QString &sourceFile, int sourceLine, const QString &assemblyFile, int assemblyLine) 0439 { 0440 if (assemblyLine < 0 || sourceLine < 0) { 0441 qCWarning(KTL_LOG) << "Invalid lines: assemblyLine=" << assemblyLine << " sourceLine=" << sourceLine; 0442 return; 0443 } 0444 0445 SourceLine hllSource = SourceLine(sourceFile, sourceLine); 0446 SourceLine asmSource = SourceLine(assemblyFile, assemblyLine); 0447 0448 if (m_sourceLineMap.contains(asmSource)) { 0449 qCWarning(KTL_LOG) << "Already have an association for assembly (\"" << assemblyFile << "\"," << assemblyLine << ")"; 0450 return; 0451 } 0452 0453 m_sourceLineMap[asmSource] = hllSource; 0454 } 0455 0456 void GpsimDebugger::initAddressToLineMap() 0457 { 0458 m_addressSize = m_pGpsim->programMemorySize(); 0459 0460 delete[] m_addressToLineMap; 0461 m_addressToLineMap = new DebugLine *[m_addressSize]; 0462 memset(m_addressToLineMap, 0, m_addressSize * sizeof(DebugLine *)); 0463 0464 if (m_type == AsmDebugger) { 0465 for (unsigned i = 0; i < m_addressSize; ++i) { 0466 int line = m_pGpsim->picProcessor()->pma->get_src_line(i) - 1; 0467 int fileID = m_pGpsim->picProcessor()->pma->get_file_id(i); 0468 FileContext *fileContext = m_pGpsim->picProcessor()->files[fileID]; 0469 0470 if (fileContext) 0471 m_addressToLineMap[i] = new DebugLine(sanitizeGpsimFile(fileContext->name().c_str()), line); 0472 } 0473 } else { 0474 SourceLineMap::const_iterator slmEnd = m_sourceLineMap.end(); 0475 for (SourceLineMap::const_iterator it = m_sourceLineMap.begin(); it != slmEnd; ++it) { 0476 SourceLineMap::const_iterator next = it; 0477 ++next; 0478 0479 int asmToLine = ((next == slmEnd) || (next.key().fileName() != it.key().fileName())) ? -1 : next.key().line() - 1; 0480 0481 QString asmFile = it.key().fileName(); 0482 int asmFromLine = it.key().line(); 0483 SourceLine sourceLine = it.value(); 0484 0485 std::string stdAsmFile(asmFile.toLatin1()); 0486 int fileID = m_pGpsim->picProcessor()->files.Find(stdAsmFile); 0487 if (fileID == -1) { 0488 qCWarning(KTL_LOG) << "Could not find FileContext (asmFile=\"" << asmFile << "\")"; 0489 continue; 0490 } 0491 0492 if (asmToLine == -1) 0493 asmToLine = m_pGpsim->picProcessor()->files[fileID]->max_line() - 2; 0494 0495 if ((asmFromLine < 0) || (asmToLine < asmFromLine)) { 0496 qCWarning(KTL_LOG) << "Invalid lines: asmFromLine=" << asmFromLine << " asmToLine=" << asmToLine; 0497 continue; 0498 } 0499 0500 DebugLine *debugLine = new DebugLine(sourceLine.fileName(), sourceLine.line()); 0501 bool used = false; 0502 0503 for (int i = asmFromLine; i <= asmToLine; ++i) { 0504 int address = m_pGpsim->picProcessor()->pma->find_address_from_line(m_pGpsim->picProcessor()->files[fileID], i + 1); 0505 if (address != -1) { 0506 used = true; 0507 m_addressToLineMap[address] = debugLine; 0508 } 0509 } 0510 0511 if (!used) 0512 delete debugLine; 0513 } 0514 } 0515 } 0516 0517 void GpsimDebugger::setBreakpoints(const QString &path, const IntList &lines) 0518 { 0519 for (unsigned i = 0; i < m_addressSize; i++) { 0520 DebugLine *dl = m_addressToLineMap[i]; 0521 if (!dl || dl->fileName() != path) 0522 continue; 0523 0524 dl->setBreakpoint(lines.contains(dl->line())); 0525 } 0526 } 0527 0528 void GpsimDebugger::setBreakpoint(const QString &path, int line, bool isBreakpoint) 0529 { 0530 for (unsigned i = 0; i < m_addressSize; i++) { 0531 if (!m_addressToLineMap[i]) 0532 continue; 0533 0534 if ((m_addressToLineMap[i]->fileName() == path) && (line == m_addressToLineMap[i]->line())) 0535 m_addressToLineMap[i]->setBreakpoint(isBreakpoint); 0536 } 0537 } 0538 0539 DebugLine *GpsimDebugger::currentDebugLine() 0540 { 0541 return m_addressToLineMap[m_pGpsim->picProcessor()->pc->get_value()]; 0542 } 0543 0544 SourceLine GpsimDebugger::currentLine() 0545 { 0546 DebugLine *dl = currentDebugLine(); 0547 return dl ? *dl : SourceLine(); 0548 } 0549 0550 void GpsimDebugger::emitLineReached() 0551 { 0552 SourceLine currentAt = currentLine(); 0553 0554 if (currentAt == m_previousAtLineEmit) 0555 return; 0556 0557 m_previousAtLineEmit = currentAt; 0558 m_pGpsim->registerMemory()->update(); 0559 emit lineReached(currentAt); 0560 } 0561 0562 void GpsimDebugger::checkForBreak() 0563 { 0564 DebugLine *currentLine = m_addressToLineMap[m_pGpsim->picProcessor()->pc->get_value()]; 0565 int currentStackLevel = int(m_pGpsim->picProcessor()->stack->pointer & m_pGpsim->picProcessor()->stack->stack_mask); 0566 0567 bool ontoNextLine = m_pBreakFromOldLine != currentLine; 0568 bool lineBreakpoint = currentLine ? currentLine->isBreakpoint() : false; 0569 bool stackBreakpoint = m_stackLevelLowerBreak >= currentStackLevel; 0570 0571 if (ontoNextLine && (lineBreakpoint || stackBreakpoint)) 0572 m_pGpsim->setRunning(false); 0573 } 0574 0575 int GpsimDebugger::programAddress(const QString &path, int line) 0576 { 0577 for (unsigned i = 0; i < m_addressSize; ++i) { 0578 DebugLine *dl = m_addressToLineMap[i]; 0579 if (!dl || (dl->line() != line) || (dl->fileName() != path)) 0580 continue; 0581 0582 return i; 0583 } 0584 0585 return -1; 0586 } 0587 0588 void GpsimDebugger::stepInto() 0589 { 0590 // I'm not aware of the stack being able to increase in size by more than 0591 // one at a time, so "1" should suffice here...but to be on the safe side, 0592 // make it a nice large number 0593 stackStep(1 << 16); 0594 } 0595 void GpsimDebugger::stepOver() 0596 { 0597 stackStep(0); 0598 } 0599 void GpsimDebugger::stepOut() 0600 { 0601 stackStep(-1); 0602 } 0603 void GpsimDebugger::stackStep(int dl) 0604 { 0605 if (m_pGpsim->isRunning()) 0606 return; 0607 0608 int initialStack = (m_pGpsim->picProcessor()->stack->pointer & m_pGpsim->picProcessor()->stack->stack_mask) + dl; 0609 DebugLine *initialLine = currentDebugLine(); 0610 0611 if (initialStack < 0) 0612 initialStack = 0; 0613 0614 // Reset any previous stackStep, and step 0615 m_pBreakFromOldLine = nullptr; 0616 m_stackLevelLowerBreak = -1; 0617 m_pGpsim->picProcessor()->step_one(false); 0618 0619 int currentStack = m_pGpsim->picProcessor()->stack->pointer & m_pGpsim->picProcessor()->stack->stack_mask; 0620 DebugLine *currentLine = currentDebugLine(); 0621 0622 if ((initialStack >= currentStack) && (initialLine != currentLine)) 0623 emitLineReached(); 0624 0625 else { 0626 // Looks like we stepped into something or haven't gone onto the next 0627 // instruction, wait until we step back out.... 0628 m_stackLevelLowerBreak = initialStack; 0629 m_pBreakFromOldLine = initialLine; 0630 m_pGpsim->setRunning(true); 0631 } 0632 } 0633 // END class Debugger 0634 0635 // BEGIN class RegisterSet 0636 RegisterSet::RegisterSet(pic_processor *picProcessor) 0637 { 0638 unsigned numRegisters = picProcessor->rma.get_size(); 0639 qCDebug(KTL_LOG) << "numRegisters=" << numRegisters; 0640 m_registers.resize(numRegisters /*, nullptr - 2018.06.02 - initialized below */); 0641 for (unsigned i = 0; i < numRegisters; ++i) { 0642 RegisterInfo *info = new RegisterInfo(&picProcessor->rma[i]); 0643 m_registers[i] = info; 0644 m_nameToRegisterMap[info->name()] = info; 0645 qCDebug(KTL_LOG) << " add register info " << info->name() << " at pos " << i << " addr " << info; 0646 } 0647 RegisterInfo *info = new RegisterInfo(picProcessor->Wreg); // is tihs correct for "W" member? TODO 0648 m_registers.append(info); 0649 m_nameToRegisterMap[info->name()] = info; 0650 qCDebug(KTL_LOG) << " add register info " << info->name() << " at end, addr " << info; 0651 qCDebug(KTL_LOG) << " registers.size " << m_registers.size() << " ; numRegisters " << numRegisters; 0652 } 0653 0654 RegisterSet::~RegisterSet() 0655 { 0656 qDeleteAll(m_registers); 0657 } 0658 0659 RegisterInfo *RegisterSet::fromAddress(unsigned address) 0660 { 0661 return (int(address) < m_registers.size()) ? m_registers[address] : nullptr; 0662 } 0663 0664 RegisterInfo *RegisterSet::fromName(const QString &name) 0665 { 0666 // First try the name as case sensitive, then as case insensitive. 0667 if (m_nameToRegisterMap.contains(name)) 0668 return m_nameToRegisterMap[name]; 0669 0670 QString nameLower = name.toLower(); 0671 0672 RegisterInfoMap::iterator end = m_nameToRegisterMap.end(); 0673 for (RegisterInfoMap::iterator it = m_nameToRegisterMap.begin(); it != end; ++it) { 0674 if (it.key().toLower() == nameLower) 0675 return it.value(); 0676 } 0677 0678 return nullptr; 0679 } 0680 0681 void RegisterSet::update() 0682 { 0683 for (int i = 0; i < m_registers.size(); ++i) 0684 m_registers[i]->update(); 0685 } 0686 // END class RegisterSet 0687 0688 // BEGIN class RegisterInfo 0689 RegisterInfo::RegisterInfo(Register *reg) 0690 { 0691 assert(reg); 0692 m_pRegister = reg; 0693 m_type = Invalid; 0694 m_prevEmitValue = 0; 0695 0696 switch (m_pRegister->isa()) { 0697 case Register::GENERIC_REGISTER: 0698 m_type = Generic; 0699 break; 0700 case Register::FILE_REGISTER: 0701 m_type = File; 0702 break; 0703 case Register::SFR_REGISTER: 0704 m_type = SFR; 0705 break; 0706 case Register::BP_REGISTER: 0707 m_type = Breakpoint; 0708 break; 0709 case Register::INVALID_REGISTER: 0710 m_type = Invalid; 0711 break; 0712 } 0713 0714 m_name = QString::fromLatin1(m_pRegister->baseName().c_str()); 0715 } 0716 0717 unsigned RegisterInfo::value() const 0718 { 0719 return m_pRegister->value.data; 0720 } 0721 0722 void RegisterInfo::update() 0723 { 0724 unsigned newValue = value(); 0725 if (newValue != m_prevEmitValue) { 0726 m_prevEmitValue = newValue; 0727 emit valueChanged(newValue); 0728 } 0729 } 0730 0731 QString RegisterInfo::toString(RegisterType type) 0732 { 0733 switch (type) { 0734 case Generic: 0735 return i18n("Generic"); 0736 0737 case File: 0738 return i18n("File"); 0739 0740 case SFR: 0741 return i18n("SFR"); 0742 0743 case Breakpoint: 0744 return i18n("Breakpoint"); 0745 0746 case Invalid: 0747 return i18n("Invalid"); 0748 } 0749 0750 return i18n("Unknown"); 0751 } 0752 // END class RegisterInfo 0753 0754 // BEGIN class DebugLine 0755 DebugLine::DebugLine(const QString &fileName, int line) 0756 : SourceLine(fileName, line) 0757 { 0758 m_bIsBreakpoint = false; 0759 m_bMarkedAsDeleted = false; 0760 } 0761 0762 DebugLine::DebugLine() 0763 : SourceLine() 0764 { 0765 m_bIsBreakpoint = false; 0766 m_bMarkedAsDeleted = false; 0767 } 0768 // END class DebugLine 0769 0770 #include "moc_gpsimprocessor.cpp" 0771 0772 #endif