diff --git a/Monitor/TFLMonitor.cpp b/Monitor/TFLMonitor.cpp index b4fb1d9e..73159f66 100644 --- a/Monitor/TFLMonitor.cpp +++ b/Monitor/TFLMonitor.cpp @@ -30,6 +30,7 @@ #include "Emulator/TInterruptManager.h" #include +#include #include #include #include @@ -38,6 +39,98 @@ #include #include +// Random Note: +// NewtonScript: get next bytecode: ldrb r0, [r6], #1 @ 0x002EE1D8 + +class TFLTerminal : public Fl_Terminal +{ + std::vector history; + std::vector future; + std::string cmd; + +public: + TFLTerminal(int x, int y, int w, int h, const char* l = nullptr) : + Fl_Terminal(x, y, w, h, l) { } + int + handle(int e) FL_OVERRIDE + { + char c; + switch (e) + { + case FL_KEYBOARD: + c = Fl::event_text()[0]; + if (c < 127 && c > 31 && isprint(c) && !Fl::event_command()) + { + cmd += Fl::event_text(); + this->printf("%s", Fl::event_text()); + } else if (Fl::event_key() == FL_Enter) + { + do_callback(); + history.push_back(cmd); + future.clear(); + cmd.clear(); + this->printf("\n"); + } else if (Fl::event_key() == FL_Escape) + { + cursor_left((int) cmd.length()); + this->printf("\033[K"); + cmd.clear(); + } else if (Fl::event_key() == FL_Up) + { + if (!history.empty()) + { + if (!cmd.empty()) + future.push_back(cmd); + cursor_left((int) cmd.length()); + this->printf("\033[K"); + cmd = history.back(); + history.pop_back(); + this->printf("%s", cmd.c_str()); + } + } else if (Fl::event_key() == FL_Down) + { + if (!cmd.empty()) + history.push_back(cmd); + cursor_left((int) cmd.length()); + this->printf("\033[K"); + if (future.empty()) + { + cmd.clear(); + } else + { + cmd = future.back(); + future.pop_back(); + } + this->printf("%s", cmd.c_str()); + } else if (Fl::event_key() == FL_BackSpace) + { + if (!cmd.empty()) + { + cmd.pop_back(); + this->printf("\033[1D\033[K"); + } + } else if (Fl::event_key() == 'v' && Fl::event_command()) + { + Fl::paste(*this); + } else + { + return Fl_Terminal::handle(e); + } + return 1; + case FL_PASTE: + cmd += Fl::event_text(); + this->printf("%s", Fl::event_text()); + return 1; + } + return Fl_Terminal::handle(e); + } + const char* + value() + { + return cmd.c_str(); + } +}; + TFLMonitor::TFLMonitor(TBufferLog* inLog, TEmulator* inEmulator, TSymbolList* inSymbolList, @@ -197,176 +290,463 @@ TFLMonitor::DrawScreenHalted() mwTerminal->printf("-------------------------------------------------------------------------------\n"); - char theInstr[512]; - theInstr[0] = 0; + if (realPC == 0x002EE1D8) + { + // byte code interpreter: TInterpreter::FastRun1() + // r4 = FastRunState, r4 + 0x01c points to the literals slot array + // +0 0x00: pointer to current byte code + // +4 0x04: ref ref to function name? + // +12 0x0C: ref to function name? + // +16 0x10: ref to binary class + // +20 0x14: Magic Pointer @287 + // +24 0x18: ref to function frame + // +28 0x1c: pointer array of literals (first literal is function name?) + // +32 0x20: start address of byte code + // + // r5 = this (TInterpreter*) + // r6 points to the current instruction + // r7 points one after the top element on the stack, stack is growing up + // mwTerminal->printf("%s%.8X Memory Error [%.8X]\n", + // TMonitor::FormatNSRef(char* buffer, size_t bufferSize, KUInt32 inRef, int indent, int maxDepth) - char theSymbol[512]; - char theComment[512]; - int theOffset; - char theLine[768]; + // struct VMState + // { + // Ref pc; // +00 - int + // Ref func; // +04 - frame + // Ref locals; // +08 - array + // Ref impl; // +0C - frame + // Ref rcvr; // +10 - frame + // Ref stackFrame; // +14 - int stack index + flags + // }; - if (mSymbolList) - { - // Get the symbol. - mSymbolList->GetNearestSymbolByAddress( - realPC, - theSymbol, - theComment, - &theOffset); - mwTerminal->printf("%s+%X\n", theSymbol, theOffset); + // Locals index: + // ■ _nextArgFrame + // ■ _parent + // ■ _implementor + // ■ arguments, from left to right + // ■ local variables + + int indexLines; + char theLiteral[200]; + char theLine[16384]; // 768, but we have an overflow error that we need to find! + VAddr ip = mProcessor->GetRegister(6); + VAddr state = mProcessor->GetRegister(4); + VAddr bc_start = 0; + mMemory->Read(state + 0x20, bc_start); + // VAddr interpreter = mProcessor->GetRegister(6); + for (indexLines = 0; indexLines < 5; indexLines++) + { + VAddr oip = ip; + KUInt8 a = 0; + if (mMemory->ReadB(ip++, a)) + { + mwTerminal->printf("%s%.8X Memory Error [%.8X]\n", + kEraseLine, + (unsigned int) ip, + (unsigned int) mMemory->GetFaultStatusRegister()); + } else + { + KUInt16 b = a & 7; + KSInt16 sb = 0; + if (b == 7) + { + KUInt8 ah, al; + mMemory->ReadB(ip++, ah); + mMemory->ReadB(ip++, al); + b = (ah << 8) | al; + sb = (ah << 8) | al; + } + mwTerminal->printf("%.8X%5d: ", (unsigned int) oip, oip - bc_start); + switch (a & ~7) + { + case 0000: + switch (b) + { + case 0: + mwTerminal->printf("%03o pop (%s)\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "x"); + break; + case 1: + mwTerminal->printf("%03o dup (%s)\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "x"); + break; + case 2: + mwTerminal->printf("%03o return\n", a); + break; + case 3: + mwTerminal->printf("%03o push-self\n", a); + break; + case 4: + mwTerminal->printf("%03o set-lex-scope %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "func"); + break; + case 5: + mwTerminal->printf("%03o iter-next %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "iter"); + break; + case 6: + mwTerminal->printf("%03o iter-done %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "iter"); + break; + case 7: + mwTerminal->printf("%03o pop-handler\n", a); + break; + default: + mwTerminal->printf("%03o \n", a); + break; + } + break; + case 0030: + mwTerminal->printf("%03o %6d push %s\n", a, b, FormatNSLiteral(theLine, 767, b)); + break; + case 0040: + FormatNSRef(theLine, 767, sb, 0, 1); + mwTerminal->printf("%03o %6d push-constant %s\n", a, b, theLine); + break; + case 0050: + mwTerminal->printf("%03o %6d call %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 1) : "..."); + break; + case 0060: + mwTerminal->printf("%03o %6d invoke %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 1) : "..."); + break; + case 0070: + mwTerminal->printf("%03o %6d send %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 2) : "recvr name"); + break; + case 0100: + mwTerminal->printf("%03o %6d send-if-defined %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 2) : "recvr name"); + break; + case 0110: + mwTerminal->printf("%03o %6d resend %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 1) : "..."); + break; + case 0120: + mwTerminal->printf("%03o %6d resend-if-defined %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 1) : "..."); + break; + case 0130: + mwTerminal->printf("%03o %6d branch %d\n", a, b, b); + break; + case 0140: + mwTerminal->printf("%03o %6d branch-if-true %d (%s)\n", a, b, b, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "bool"); + break; + case 0150: + mwTerminal->printf("%03o %6d branch-if-false %d (%s)\n", a, b, b, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "bool"); + break; + case 0160: + mwTerminal->printf("%03o %6d find-var %s\n", a, b, FormatNSLiteral(theLine, 767, b)); + break; + case 0170: + mwTerminal->printf("%03o %6d get-var local%04d\n", a, b, b); + break; // TODO: locals array [b] + case 0200: + mwTerminal->printf("%03o %6d make-frame %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 1) : "map val1 val2 valN"); + break; // TODO: val1 val2 valN map + case 0210: + if (b == 0xffff) + mwTerminal->printf("%03o %6d make-array-with-size %s\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, 1, 1) : "class size"); + else + mwTerminal->printf("%03o %6d make-array\n", a, b, indexLines == 0 ? FormatNSCallArgs(theLine, 767, b, 1) : "class val1 val2 valN"); + break; + case 0220: + switch (b) + { + case 0: + mwTerminal->printf("%03o get-path %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "object pathExpr"); + break; + case 1: + mwTerminal->printf("%03o get-path-no-nil %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "object pathExpr"); + break; + default: + mwTerminal->printf("%03o \n", a); + break; + } + break; + case 0230: + switch (b) + { + case 0: + mwTerminal->printf("%03o set-path %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 3) : "object pathExpr value"); + break; + case 1: + mwTerminal->printf("%03o set-path-and-push %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 3) : "object pathExpr value"); + break; + default: + mwTerminal->printf("%03o \n", a); + break; + } + break; + case 0240: + mwTerminal->printf("%03o %6d set-var local%04d %s\n", a, b, b, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "value"); + break; // TODO: locals array [b] + case 0250: + mwTerminal->printf("%03o %6d find-and-set-var %s %s\n", a, b, FormatNSLiteral(theLiteral, 199, b), indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "value"); + break; // TODO: literals array [b] + case 0260: + mwTerminal->printf("%03o %6d incr-var local%04d %s\n", a, b, b, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "addend"); + break; // TODO: locals array [b] + case 0270: + mwTerminal->printf("%03o %6d branch-if-loop-not-done %d %s\n", a, b, b, indexLines == 0 ? FormatNSValueStack(theLine, 767, 3) : "incr index limit"); + break; + case 0300: + switch (b) + { + case 0: + mwTerminal->printf("%03o add %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 1: + mwTerminal->printf("%03o subtract %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 2: + mwTerminal->printf("%03o aref %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "object index"); + break; + case 3: + mwTerminal->printf("%03o set-aref %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 3) : "object index element"); + break; + case 4: + mwTerminal->printf("%03o equals %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 5: + mwTerminal->printf("%03o not %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "x"); + break; + case 6: + mwTerminal->printf("%03o not-equals %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 7: + mwTerminal->printf("%03o mul %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 8: + mwTerminal->printf("%03o divide %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 9: + mwTerminal->printf("%03o div %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 10: + mwTerminal->printf("%03o less-than %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 11: + mwTerminal->printf("%03o greater-than %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 12: + mwTerminal->printf("%03o greater-or-equal %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 13: + mwTerminal->printf("%03o less-or-equal %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 14: + mwTerminal->printf("%03o bit-and %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 15: + mwTerminal->printf("%03o bit-or %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 16: + mwTerminal->printf("%03o bit-not %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "x y"); + break; + case 17: + mwTerminal->printf("%03o new-iter %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "object deeply"); + break; + case 18: + mwTerminal->printf("%03o length %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "object"); + break; + case 19: + mwTerminal->printf("%03o clone %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "object"); + break; + case 20: + mwTerminal->printf("%03o set-class %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "object class"); + break; + case 21: + mwTerminal->printf("%03o add-array-slot %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "array object"); + break; + case 22: + mwTerminal->printf("%03o stringer %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "array"); + break; + case 23: + mwTerminal->printf("%03o has-path %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2) : "object pathExpr"); + break; + case 24: + mwTerminal->printf("%03o class-of %s\n", a, indexLines == 0 ? FormatNSValueStack(theLine, 767, 1) : "object"); + break; + default: + mwTerminal->printf("%03o %6d freq-func #\n", a, b); + break; + } + break; + case 0310: + mwTerminal->printf("%03o %6d new-handlers %s\n", a, b, indexLines == 0 ? FormatNSValueStack(theLine, 767, 2 * b) : "sym1 pc1 ..."); + break; + default: + mwTerminal->printf("%03o \n", a); + break; + } + } + if ((a == 0002) || ((a & ~7) == 0130)) + break; // branch or return + } } else { - theSymbol[0] = '\0'; - theComment[0] = '\0'; - theLine[0] = '\0'; - theOffset = 0; - mwTerminal->printf("%X\n", realPC); - } + char theInstr[512]; + theInstr[0] = 0; - KUInt32 instruction; + char theSymbol[512]; + char theComment[512]; + int theOffset; + char theLine[768]; - // Write 5 lines. - int indexLines; - for (indexLines = 0; indexLines < 20; indexLines += 4) - { - if (mMemory->Read( - (TMemory::VAddr) realPC + indexLines, instruction)) + if (mSymbolList) { - mwTerminal->printf( - "%.8X Memory Error [%.8X]\n", - (unsigned int) realPC + indexLines, - (unsigned int) mMemory->GetFaultStatusRegister()); + // Get the symbol. + mSymbolList->GetNearestSymbolByAddress( + realPC, + theSymbol, + theComment, + &theOffset); + mwTerminal->printf("%s+%X\n", theSymbol, theOffset); } else { - bool instIsBP = false; - if ((instruction & 0xFFF000F0) == 0xE1200070) + theSymbol[0] = '\0'; + theComment[0] = '\0'; + theLine[0] = '\0'; + theOffset = 0; + mwTerminal->printf("%X\n", realPC); + } + + KUInt32 instruction; + + // Write 5 lines. + int indexLines; + for (indexLines = 0; indexLines < 20; indexLines += 4) + { + if (mMemory->Read( + (TMemory::VAddr) realPC + indexLines, instruction)) { - if (!mMemory->ReadBreakpoint( - (TMemory::VAddr) realPC + indexLines, instruction)) - { - instIsBP = true; - } - } - UDisasm::Disasm( - theInstr, - sizeof(theInstr), - realPC + indexLines, - instruction, - mSymbolList); - - char status[32]; - status[0] = '\0'; - if (indexLines == 0) + mwTerminal->printf( + "%.8X Memory Error [%.8X]\n", + (unsigned int) realPC + indexLines, + (unsigned int) mMemory->GetFaultStatusRegister()); + } else { - if (instruction >> 28 != 0xE) + bool instIsBP = false; + if ((instruction & 0xFFF000F0) == 0xE1200070) { - KUInt32 skip = 0; - switch (instruction >> 28) + if (!mMemory->ReadBreakpoint( + (TMemory::VAddr) realPC + indexLines, instruction)) { - // 0000 = EQ - Z set (equal) - case 0x0: - skip = !(theCPSR & TARMProcessor::kPSR_ZBit); - break; - - // 0001 = NE - Z clear (not equal) - case 0x1: - skip = theCPSR & TARMProcessor::kPSR_ZBit; - break; - // 0010 = CS - C set (unsigned higher or same) - case 0x2: - skip = !(theCPSR & TARMProcessor::kPSR_CBit); - break; - - // 0011 = CC - C clear (unsigned lower) - case 0x3: - skip = theCPSR & TARMProcessor::kPSR_CBit; - break; - - // 0100 = MI - N set (negative) - case 0x4: - skip = !(theCPSR & TARMProcessor::kPSR_NBit); - break; - - // 0101 = PL - N clear (positive or zero) - case 0x5: - skip = theCPSR & TARMProcessor::kPSR_NBit; - break; - - // 0110 = VS - V set (overflow) - case 0x6: - skip = !(theCPSR & TARMProcessor::kPSR_VBit); - break; - - // 0111 = VC - V clear (no overflow) - case 0x7: - skip = theCPSR & TARMProcessor::kPSR_VBit; - break; - - // 1000 = HI - C set and Z clear (unsigned higher) - case 0x8: - skip = !(theCPSR & TARMProcessor::kPSR_CBit) - || (theCPSR & TARMProcessor::kPSR_ZBit); - break; - - // 1001 = LS - C clear or Z set (unsigned lower or same) - case 0x9: - skip = (theCPSR & TARMProcessor::kPSR_CBit) - && !(theCPSR & TARMProcessor::kPSR_ZBit); - break; - - // 1010 = GE - N set and V set, or N clear and V clear (greater or equal) - case 0xA: - skip = ((theCPSR & TARMProcessor::kPSR_NBit) != 0) - != ((theCPSR & TARMProcessor::kPSR_VBit) != 0); - break; - - // 1011 = LT - N set and V clear, or N clear and V set (less than) - case 0xB: - skip = ((theCPSR & TARMProcessor::kPSR_NBit) != 0) - == ((theCPSR & TARMProcessor::kPSR_VBit) != 0); - break; - - // 1100 = GT - Z clear, and either N set and V set, or N clear and V clear (greater than) - case 0xC: - skip = (theCPSR & TARMProcessor::kPSR_ZBit) || (((theCPSR & TARMProcessor::kPSR_NBit) != 0) != ((theCPSR & TARMProcessor::kPSR_VBit) != 0)); - break; - - // 1101 = LE - Z set, or N set and V clear, or N clear and V set (less than or equal) - case 0xD: - skip = (!(theCPSR & TARMProcessor::kPSR_ZBit)) - && (((theCPSR & TARMProcessor::kPSR_NBit) != 0) - == ((theCPSR & TARMProcessor::kPSR_VBit) != 0)); - break; - - // 1111 = NV - never - case 0xF: - default: - skip = 1; + instIsBP = true; } + } + UDisasm::Disasm( + theInstr, + sizeof(theInstr), + realPC + indexLines, + instruction, + mSymbolList); - if (skip) - { - (void) ::snprintf(status, 31, " (will skip)"); - } else + char status[32]; + status[0] = '\0'; + if (indexLines == 0) + { + if (instruction >> 28 != 0xE) { - (void) ::snprintf(status, 31, " (will do it)"); + KUInt32 skip = 0; + switch (instruction >> 28) + { + // 0000 = EQ - Z set (equal) + case 0x0: + skip = !(theCPSR & TARMProcessor::kPSR_ZBit); + break; + + // 0001 = NE - Z clear (not equal) + case 0x1: + skip = theCPSR & TARMProcessor::kPSR_ZBit; + break; + // 0010 = CS - C set (unsigned higher or same) + case 0x2: + skip = !(theCPSR & TARMProcessor::kPSR_CBit); + break; + + // 0011 = CC - C clear (unsigned lower) + case 0x3: + skip = theCPSR & TARMProcessor::kPSR_CBit; + break; + + // 0100 = MI - N set (negative) + case 0x4: + skip = !(theCPSR & TARMProcessor::kPSR_NBit); + break; + + // 0101 = PL - N clear (positive or zero) + case 0x5: + skip = theCPSR & TARMProcessor::kPSR_NBit; + break; + + // 0110 = VS - V set (overflow) + case 0x6: + skip = !(theCPSR & TARMProcessor::kPSR_VBit); + break; + + // 0111 = VC - V clear (no overflow) + case 0x7: + skip = theCPSR & TARMProcessor::kPSR_VBit; + break; + + // 1000 = HI - C set and Z clear (unsigned higher) + case 0x8: + skip = !(theCPSR & TARMProcessor::kPSR_CBit) + || (theCPSR & TARMProcessor::kPSR_ZBit); + break; + + // 1001 = LS - C clear or Z set (unsigned lower or same) + case 0x9: + skip = (theCPSR & TARMProcessor::kPSR_CBit) + && !(theCPSR & TARMProcessor::kPSR_ZBit); + break; + + // 1010 = GE - N set and V set, or N clear and V clear (greater or equal) + case 0xA: + skip = ((theCPSR & TARMProcessor::kPSR_NBit) != 0) + != ((theCPSR & TARMProcessor::kPSR_VBit) != 0); + break; + + // 1011 = LT - N set and V clear, or N clear and V set (less than) + case 0xB: + skip = ((theCPSR & TARMProcessor::kPSR_NBit) != 0) + == ((theCPSR & TARMProcessor::kPSR_VBit) != 0); + break; + + // 1100 = GT - Z clear, and either N set and V set, or N clear and V clear (greater than) + case 0xC: + skip = (theCPSR & TARMProcessor::kPSR_ZBit) || (((theCPSR & TARMProcessor::kPSR_NBit) != 0) != ((theCPSR & TARMProcessor::kPSR_VBit) != 0)); + break; + + // 1101 = LE - Z set, or N set and V clear, or N clear and V set (less than or equal) + case 0xD: + skip = (!(theCPSR & TARMProcessor::kPSR_ZBit)) + && (((theCPSR & TARMProcessor::kPSR_NBit) != 0) + == ((theCPSR & TARMProcessor::kPSR_VBit) != 0)); + break; + + // 1111 = NV - never + case 0xF: + default: + skip = 1; + } + + if (skip) + { + (void) ::snprintf(status, 31, " (will skip)"); + } else + { + (void) ::snprintf(status, 31, " (will do it)"); + } } } + if (instIsBP) + { + (void) ::snprintf(theLine, sizeof(theLine), "%.8X * %s", + (unsigned int) realPC + indexLines, + theInstr); + } else + { + (void) ::snprintf(theLine, sizeof(theLine), "%.8X %s", + (unsigned int) realPC + indexLines, + theInstr); + } // if (indexLines == 0) + mwTerminal->printf("%s%s\n", + theLine, + status); } - if (instIsBP) - { - (void) ::snprintf(theLine, sizeof(theLine), "%.8X * %s", - (unsigned int) realPC + indexLines, - theInstr); - } else - { - (void) ::snprintf(theLine, sizeof(theLine), "%.8X %s", - (unsigned int) realPC + indexLines, - theInstr); - } // if (indexLines == 0) - mwTerminal->printf("%s%s\n", - theLine, - status); } } @@ -375,6 +755,72 @@ TFLMonitor::DrawScreenHalted() Fl::unlock(); } +const char* +TFLMonitor::FormatNSCallArgs(char* buffer, size_t size, int nArgs, int nNames) +{ + const char* original_buffer = buffer; + VAddr sp = mProcessor->GetRegister(7); + KUInt32 ref; + int i = 0, n = 0; + + for (i = 0; i < nNames; i++) + { + mMemory->Read(sp - 4 - 4 * i, ref); + n = FormatNSRef(buffer, size, ref, 0, 0); + buffer += n; + size -= n; + if (size <= 1) + break; + *buffer++ = ' '; + buffer[1] = '\0'; + size--; + } + + if ((size > 0) && nNames && nArgs) + { + *buffer++ = ':'; + *buffer++ = ':'; + *buffer++ = ' '; + size -= 3; + } + if (size <= 1) + return original_buffer; + + for (i = nArgs; i > 0; i--) + { + mMemory->Read(sp - 4 * i - 4 * nNames, ref); + n = FormatNSRef(buffer, size, ref, 0, 0); + buffer += n; + size -= n; + if (size <= 1) + break; + *buffer++ = ' '; + buffer[1] = '\0'; + size--; + } + + return original_buffer; +} + +const char* +TFLMonitor::FormatNSValueStack(char* buffer, size_t size, int nArgs) +{ + return FormatNSCallArgs(buffer, size, nArgs, 0); +} + +const char* +TFLMonitor::FormatNSLiteral(char* buffer, size_t size, int index) +{ + const char* original_buffer = buffer; + VAddr state = mProcessor->GetRegister(4); + VAddr literals = 0; + mMemory->Read(state + 0x1c, literals); + KUInt32 ref; + mMemory->Read(literals + 4 * index, ref); + FormatNSRef(buffer, size, ref, 0, 1); + return original_buffer; +} + // -------------------------------------------------------------------------- // // DrawScreenRunning( void ) // -------------------------------------------------------------------------- // @@ -446,25 +892,25 @@ TFLMonitor::Show() // ---- create the monitor window mwWindow = new TFLMonitorWindow(mx, my, mw, mh, "Einstein Monitor"); // ---- terminal window for all text output - mwTerminal = new Fl_Terminal(0, 0, mwWindow->w(), mwWindow->h() - 2 * ch); + mwTerminal = new TFLTerminal(0, 0, mwWindow->w(), mwWindow->h() - 2 * ch); mwTerminal->box(FL_DOWN_BOX); mwTerminal->textfont(FL_COURIER); mwTerminal->textsize(ch); - mwTerminal->display_columns(80); - mwTerminal->display_rows(44); - // mwTerminal->init_tabstops(8); // default is 8 - // mwTerminal->append("\033[3g\033[8G\033H"); // layout does not match well - // mwTerminal->hide_cursor(); - // mwTerminal->color(FL_LIGHT3); - // mwTerminal->textcolor(FL_FOREGROUND_COLOR); - // mwTerminal->cursor_color(FL_BACKGROUND_COLOR); + mwTerminal->callback([](Fl_Widget* w, void* m) { + TFLTerminal* term = static_cast(w); + ((TMonitor*) m)->ExecuteCommand(term->value()); + ((TFLMonitor*) m)->DrawScreen(); + }, + this); mwTerminal->ansi(true); // mwTerminal->stay_at_bottom(true); // --- group all this for perfect resizing Fl_Group* mwToolbar = new Fl_Group(0, mwWindow->h() - 2 * ch, mwWindow->w(), 2 * ch); // --- the stop button stops the emulation + xp += 1 * cw; mwPause = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@||"); - mwPause->tooltip("stop"); + mwPause->tooltip("(Shift F5) stop"); + mwPause->shortcut(FL_SHIFT | (FL_F + 5)); xp += 3 * cw; mwPause->callback([](Fl_Widget*, void* m) { ((TMonitor*) m)->ExecuteCommand("stop"); @@ -474,7 +920,8 @@ TFLMonitor::Show() set_attributes(mwPause); // --- continue running the app mwRun = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@|>"); - mwRun->tooltip("run"); + mwRun->tooltip("(F5) run"); + mwRun->shortcut(FL_F + 5); xp += 3 * cw; mwRun->callback([](Fl_Widget*, void* m) { ((TMonitor*) m)->ExecuteCommand("run"); @@ -485,7 +932,8 @@ TFLMonitor::Show() set_attributes(mwRun); // --- step over mwStepOver = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@3redo"); - mwStepOver->tooltip("trace"); + mwStepOver->tooltip("(F10) trace"); + mwStepOver->shortcut(FL_F + 10); xp += 3 * cw; mwStepOver->callback([](Fl_Widget*, void* m) { ((TMonitor*) m)->ExecuteCommand("trace"); @@ -495,7 +943,8 @@ TFLMonitor::Show() set_attributes(mwStepOver); // --- step into mwStep = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@2->|"); - mwStep->tooltip("step"); + mwStep->tooltip("(F11) step"); + mwStep->shortcut(FL_F + 11); xp += 3 * cw; mwStep->callback([](Fl_Widget*, void* m) { ((TMonitor*) m)->ExecuteCommand("step"); @@ -505,7 +954,8 @@ TFLMonitor::Show() set_attributes(mwStep); // --- leave mwLeave = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@8->|"); - mwLeave->tooltip("return to r14"); + mwLeave->tooltip("(Shift F11) return to r14"); + mwLeave->shortcut(FL_SHIFT | (FL_F + 11)); xp += 3 * cw; mwLeave->callback([](Fl_Widget*, void* m) { ((TMonitor*) m)->ExecuteCommand("mr"); @@ -513,23 +963,36 @@ TFLMonitor::Show() }, this); set_attributes(mwLeave); - // --- enter your commands here - mwInput = new Fl_Input(xp, mwToolbar->y(), mwWindow->w() - xp - 3 * cw, 2 * ch); - mwInput->color(FL_LIGHT3); - mwInput->textfont(mwTerminal->textfont()); - mwInput->textsize(mwTerminal->textsize()); - mwInput->box(FL_BORDER_BOX); - mwInput->when(FL_WHEN_ENTER_KEY_ALWAYS); - mwInput->callback([](Fl_Widget* w, void* m) { - Fl_Input* in = (Fl_Input*) w; - ((TMonitor*) m)->ExecuteCommand(in->value()); + // --- bytecode stop + xp += 1 * cw; + mwBCPause = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@||"); + mwBCPause->tooltip("(Shift F1) BC stop"); + mwBCPause->shortcut(FL_SHIFT | (FL_F + 1)); + xp += 3 * cw; + mwBCPause->callback([](Fl_Widget*, void* m) { + ((TMonitor*) m)->ExecuteCommand(".stop"); + ((TFLMonitor*) m)->DrawScreen(); + }, + this); + set_attributes(mwBCPause); + mwBCPause->labelcolor(FL_BLUE); + // --- bytecode continue + xp += 1 * cw; + mwBCRun = new Fl_Button(xp, mwToolbar->y(), 3 * cw, 2 * ch, "@|>"); + mwBCRun->tooltip("(F1) BC run"); + mwBCRun->shortcut(FL_F + 1); + xp += 3 * cw; + mwBCRun->callback([](Fl_Widget*, void* m) { + ((TMonitor*) m)->ExecuteCommand(".run"); ((TFLMonitor*) m)->DrawScreen(); - in->value(""); - Fl::focus(in); }, this); + set_attributes(mwBCRun); + mwBCRun->labelcolor(FL_BLUE); + // --- resizable part + mwBox = new Fl_Box(xp, mwToolbar->y(), mwWindow->w() - xp - 4 * cw, 2 * ch); // --- help - mwHelp = new Fl_Button(mwWindow->w() - 3 * cw, mwToolbar->y(), 3 * cw, 2 * ch, "?"); + mwHelp = new Fl_Button(mwWindow->w() - 4 * cw, mwToolbar->y(), 3 * cw, 2 * ch, "?"); mwHelp->callback([](Fl_Widget*, void* m) { ((TMonitor*) m)->ExecuteCommand("help"); ((TFLMonitor*) m)->DrawScreen(); @@ -538,11 +1001,11 @@ TFLMonitor::Show() set_attributes(mwHelp); mwHelp->labelcolor(FL_BLACK); // --- set resizing properties - mwToolbar->resizable(mwInput); + mwToolbar->resizable(mwBox); mwToolbar->end(); mwWindow->resizable(mwTerminal); mwWindow->end(); - Fl::focus(mwInput); + Fl::focus(mwTerminal); } DrawScreen(); mwWindow->show(); diff --git a/Monitor/TFLMonitor.h b/Monitor/TFLMonitor.h index 627e9cd1..1cc3aa0c 100644 --- a/Monitor/TFLMonitor.h +++ b/Monitor/TFLMonitor.h @@ -27,10 +27,11 @@ #include #include "Monitor/TMonitor.h" +class TFLTerminal; class Fl_Window; class Fl_Terminal; class Fl_Button; -class Fl_Input; +class Fl_Box; class TFLMonitor : public TMonitor { @@ -63,6 +64,10 @@ class TFLMonitor : public TMonitor /// // void PrintLine(const char* inLine, int type) override; + const char* FormatNSCallArgs(char* buffer, size_t size, int nArgs, int nNames); + const char* FormatNSValueStack(char* buffer, size_t size, int nArgs); + const char* FormatNSLiteral(char* buffer, size_t size, int index); + private: /// /// Draw screen when the emulator is halted. @@ -75,14 +80,16 @@ class TFLMonitor : public TMonitor void DrawScreenRunning(void); Fl_Window* mwWindow = nullptr; - Fl_Terminal* mwTerminal = nullptr; + TFLTerminal* mwTerminal = nullptr; Fl_Button* mwPause = nullptr; Fl_Button* mwRun = nullptr; Fl_Button* mwStepOver = nullptr; Fl_Button* mwStep = nullptr; Fl_Button* mwLeave = nullptr; - Fl_Input* mwInput = nullptr; + Fl_Box* mwBox = nullptr; Fl_Button* mwHelp = nullptr; + Fl_Button* mwBCPause = nullptr; + Fl_Button* mwBCRun = nullptr; }; #endif // T_FL_MONITOR_H diff --git a/Monitor/TMonitor.cpp b/Monitor/TMonitor.cpp index 096d5a44..133f808b 100644 --- a/Monitor/TMonitor.cpp +++ b/Monitor/TMonitor.cpp @@ -111,10 +111,6 @@ TMonitor::TMonitor( mProcessor(inEmulator->GetProcessor()), mInterruptManager(inEmulator->GetInterruptManager()), mLog(inLog), - mHalted(true), - mCommand(kNop), - mFilename(nullptr), - mLastScreenHalted(true), mMonitorStartupScriptPath(strdup(inMonitorStartupScriptPath)) { mMemory = inEmulator->GetMemory(); @@ -531,7 +527,7 @@ TMonitor::Stop() ReleaseMutex(); } -// little helper to return the prinatble version of any character +// little helper to return the printable version of any character static char cc(unsigned int v) { @@ -1343,6 +1339,16 @@ TMonitor::ExecuteCommand(const char* inCommand) } else if (::strcmp(inCommand, "cdr") == 0) { ::chdir(mROMImageDir); + } else if (::strcmp(inCommand, ".stop") == 0) + { // break before byte code grab in TInterpreter::FastRun1() + mMemory->SetBreakpoint(0x002EE1D8, kPermanentBP); + mCommand = kRun; + SignalCondVar(); + } else if (::strcmp(inCommand, ".run") == 0) + { // clear break before byte code grab in TInterpreter::FastRun1() + mMemory->ClearBreakpoint(0x002EE1D8); + mCommand = kRun; + SignalCondVar(); } else if (inCommand[0] == '!') { theResult = ExecuteScript(inCommand + 1); @@ -1667,7 +1673,7 @@ TMonitor::DrawScreenHalted(void) KUInt32 instruction; - // Write 5 lines. + // Write 5 lines in ARM code. int indexLines; for (indexLines = 0; indexLines < 20; indexLines += 4) { @@ -1959,6 +1965,9 @@ TMonitor::PrintNSRef(KUInt32 inRef) int TMonitor::FormatNSRef(char* buffer, size_t bufferSize, KUInt32 inRef, int indent, int maxDepth) { + if (bufferSize <= 0) + return 0; + switch (inRef & 0x3) { case kTagInteger: { @@ -2053,6 +2062,8 @@ TMonitor::FormatNSRef(char* buffer, size_t bufferSize, KUInt32 inRef, int indent int TMonitor::FormatNSFrame(char* buffer, size_t bufferSize, KUInt32 inAddr, unsigned int length, KUInt32 mapRef, int indent, int maxDepth) { + if (bufferSize <= 0) + return 0; KUInt32* flattenMap = (KUInt32*) ::malloc(length * sizeof(KUInt32)); int mapIndex = length; diff --git a/Monitor/TMonitor.h b/Monitor/TMonitor.h index f0bfad7d..614c26d2 100644 --- a/Monitor/TMonitor.h +++ b/Monitor/TMonitor.h @@ -312,7 +312,7 @@ class TMonitor : public TMonitorCore return mEmulator; } -private: +protected: /// /// Run the emulator (handle breakpoint if we're on a BP). /// @@ -377,41 +377,43 @@ class TMonitor : public TMonitorCore /// int FormatNSBinary(char* buffer, size_t bufferSize, KUInt32 addr, unsigned int length, KUInt32 classRef, int indent, int maxDepth); +private: /// /// Constructeur par copie volontairement indisponible. /// /// \param inCopy objet à copier /// - TMonitor(const TMonitor& inCopy); + TMonitor(const TMonitor& inCopy) = delete; /// /// Opérateur d'assignation volontairement indisponible. /// /// \param inCopy objet à copier /// - TMonitor& operator=(const TMonitor& inCopy); + TMonitor& operator=(const TMonitor& inCopy) = delete; +protected: /// \name Variables - TEmulator* mEmulator; ///< Emulator. - TARMProcessor* mProcessor; ///< CPU. - TInterruptManager* mInterruptManager; ///< Interrupt manager. - TBufferLog* mLog; ///< Interface to the log. - Boolean mHalted; ///< If the emulator is halted. - TCondVar* mCondVar = nullptr; - TMutex* mMutex = nullptr; - ECommand mCommand; ///< Next command for the - ///< monitor thread. - char* mFilename; ///< Argument for next command. + TEmulator* mEmulator { nullptr }; ///< Emulator. + TARMProcessor* mProcessor { nullptr }; ///< CPU. + TInterruptManager* mInterruptManager { nullptr }; ///< Interrupt manager. + TBufferLog* mLog { nullptr }; ///< Interface to the log. + Boolean mHalted { false }; ///< If the emulator is halted. + TCondVar* mCondVar { nullptr }; + TMutex* mMutex { nullptr }; + ECommand mCommand { kNop }; ///< Next command for the + ///< monitor thread. + char* mFilename { nullptr }; ///< Argument for next command. #if TARGET_UI_FLTK - // no signalling between monitor and log yet + // no signaling between monitor and log yet #else - int mSocketPair[2]; ///< Socket pair for monitor state changes. + int mSocketPair[2] { -1, -1 }; ///< Socket pair for monitor state changes. #endif - Boolean mLastScreenHalted; ///< If last screen was halted. - char* mMonitorStartupScriptPath; ///< path to monitor startup script file - char* mROMImageDir; /// < path to the ROM file directory + Boolean mLastScreenHalted { true }; ///< If last screen was halted. + char* mMonitorStartupScriptPath { nullptr }; ///< path to monitor startup script file + char* mROMImageDir { nullptr }; /// < path to the ROM file directory - Boolean mRunOnStartup = false; ///< Run the emulation as soon as the monitor starts + Boolean mRunOnStartup { false }; ///< Run the emulation as soon as the monitor starts }; #endif diff --git a/Monitor/TMonitorCore.cpp b/Monitor/TMonitorCore.cpp index 7b068bba..162a743f 100644 --- a/Monitor/TMonitorCore.cpp +++ b/Monitor/TMonitorCore.cpp @@ -45,9 +45,7 @@ #include "Emulator/JIT/JIT.h" TMonitorCore::TMonitorCore(TSymbolList* inSymbolList) : - mMemory(0L), - mSymbolList(inSymbolList), - mDisasm(nullptr) + mSymbolList(inSymbolList) { } diff --git a/Monitor/TMonitorCore.h b/Monitor/TMonitorCore.h index 4571e00b..5f70ffc8 100644 --- a/Monitor/TMonitorCore.h +++ b/Monitor/TMonitorCore.h @@ -83,9 +83,9 @@ class TMonitorCore virtual Boolean ExecuteCommand(const char* inCommand); /// \name Variables - TMemory* mMemory; ///< Memory. - TSymbolList* mSymbolList; ///< List of symbols. - UDisasm* mDisasm; ///< Disassembler + TMemory* mMemory { nullptr }; ///< Memory. + TSymbolList* mSymbolList { nullptr }; ///< List of symbols. + UDisasm* mDisasm { nullptr }; ///< Disassembler }; #endif diff --git a/Toolkit/TToolkit.cpp b/Toolkit/TToolkit.cpp index 7bb5cd07..2165b3ad 100644 --- a/Toolkit/TToolkit.cpp +++ b/Toolkit/TToolkit.cpp @@ -77,8 +77,8 @@ containing an array named 'programCounter'. The array holds one frame per breakpoint. Those frames have the fields: 'programCounter' : checks if the current instruction offset matches - 'instrcutions' : points at the current instructions binary ref(?) and must match - 'disabled' : is TRUE or NIL to disable or anable the breakpoint + 'instructions' : points at the current instructions binary ref(?) and must match + 'disabled' : is TRUE or NIL to disable or enable the breakpoint 'temporary' : the breakpoint is removed from the array when it is hit If breakpoints are enabled, TInterpreter switches to Slow mode. @@ -1097,7 +1097,8 @@ TToolkit::AppBuild() const char* errStr = NewtRefToString(errRef); PrintErr(errStr); } - // PrintErr(mPkgPath); + ::snprintf(buf, sizeof(buf), "Package saved to: %s\n", mPkgPath); + PrintStd(buf); NewtCleanup(); } @@ -1169,7 +1170,7 @@ TToolkit::AppStop() } /** - Send a NewtonScrippt line to Einstein and run it there. + Send a NewtonScript line to Einstein and run it there. \note Running NewtonScript this way is limited to 256 characters. diff --git a/Toolkit/TToolkitScriptExt.cpp b/Toolkit/TToolkitScriptExt.cpp index 6d848525..eaa8c534 100644 --- a/Toolkit/TToolkitScriptExt.cpp +++ b/Toolkit/TToolkitScriptExt.cpp @@ -743,7 +743,7 @@ RegisterToolkitScriptExtensions() NewtObjSetSlot(fltk_obj, NSSYM(filechooser), NewtMakeNativeFunc0((void*) NsFltkFileChooser, 4, false, (char*) "Open a file chooser dialog (message, pattern, filename, relative) => filename or NIL")); NcDefGlobalVar(NSSYM(fltk), fltk); - // the FILE namespace for reading and writing files on the hos machine + // the FILE namespace for reading and writing files on the host machine auto file = NewtMakeFrame(kNewtRefNIL, 0); newtObjRef file_obj = (newtObjRef) NewtRefToPointer(file); NewtObjSetSlot(file_obj, NSSYM(new), NewtMakeNativeFunc0((void*) NsFileNew, 0, false, (char*) "Create a frame to access files on the host machine."));