Added register names to argument processing. This means you can set e.g.

location 80 to the contents of the X register by saying "ram 80 x". This
also means that there's a small conflict: if you're inputting the value
0x0a (decimal 10), you need to either say "0a" or "A". Otherwise the
parser thinks you're talking about the "a" register instead of the hex
number "a".

Added dereference operator to arg processing. This works the same way as
in C: you prefix a "*" to an argument. So "80" means a literal hex 80,
as before, but you can say "*80" to mean "the memory location pointed to
by location 80"... this also works with the registers. Example: if the X
register holds the value ff, you can say "*x" and it will be treated as
the value ff. Unlike C, multiple levels of dereference are not supported.
Also, the result of a dereference is always a byte for now.

Added "eval" command to debugger prompt. This evaluates one or more
arguments (which may hex values or a labels, and may have a * in front)
and prints the results in hex, binary, and decimal, along with the label
that has that value, if any.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@527 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-06-18 17:28:18 +00:00
parent a92a6b0ab8
commit 5378b2c971
5 changed files with 140 additions and 41 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.cxx,v 1.16 2005-06-18 15:45:05 urchlay Exp $
// $Id: Debugger.cxx,v 1.17 2005-06-18 17:28:18 urchlay Exp $
//============================================================================
#include "bspf.hxx"
@ -397,6 +397,31 @@ int Debugger::getPC() {
return myDebugger->pc();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::getA() {
return myDebugger->a();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::getX() {
return myDebugger->x();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::getY() {
return myDebugger->y();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::getS() {
return myDebugger->sp();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::getP() {
return myDebugger->ps();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Debugger::disassemble(int start, int lines) {
char buf[255], bbuf[255];
@ -438,3 +463,8 @@ void Debugger::clearAllBreakPoints() {
breakPoints = new PackedBitArray(0x10000);
mySystem->m6502().setBreakPoints(NULL);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::peek(int addr) {
return mySystem->peek(addr);
}

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: Debugger.hxx,v 1.14 2005-06-18 15:45:05 urchlay Exp $
// $Id: Debugger.hxx,v 1.15 2005-06-18 17:28:18 urchlay Exp $
//============================================================================
#ifndef DEBUGGER_HXX
@ -49,7 +49,7 @@ enum {
for all debugging operations in Stella (parser, 6502 debugger, etc).
@author Stephen Anthony
@version $Id: Debugger.hxx,v 1.14 2005-06-18 15:45:05 urchlay Exp $
@version $Id: Debugger.hxx,v 1.15 2005-06-18 17:28:18 urchlay Exp $
*/
class Debugger : public DialogContainer
{
@ -105,6 +105,27 @@ class Debugger : public DialogContainer
{
return (int) strtoimax(h, NULL, 16);
}
static char *to_bin(int dec, int places, char *buf) {
int bit = 1;
buf[places] = '\0';
while(--places >= 0) {
if(dec & bit)
buf[places] = '1';
else
buf[places] = '0';
bit <<= 1;
}
return buf;
}
static char *to_bin_8(int dec) {
static char buf[9];
return to_bin(dec, 8, buf);
}
static char *to_bin_16(int dec) {
static char buf[17];
return to_bin(dec, 16, buf);
}
void toggleBreakPoint(int bp);
bool breakPoint(int bp);
@ -146,6 +167,12 @@ class Debugger : public DialogContainer
void setS(int sp);
void setPC(int pc);
int getPC();
int getA();
int getX();
int getY();
int getP();
int getS();
int peek(int addr);
void toggleC();
void toggleZ();
void toggleN();

View File

@ -13,12 +13,13 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DebuggerParser.cxx,v 1.12 2005-06-18 15:45:05 urchlay Exp $
// $Id: DebuggerParser.cxx,v 1.13 2005-06-18 17:28:18 urchlay Exp $
//============================================================================
#include "bspf.hxx"
#include "Debugger.hxx"
#include "DebuggerParser.hxx"
#include "D6502.hxx"
#include "EquateList.hxx"
// Constants for argument processing
@ -57,31 +58,45 @@ int DebuggerParser::conv_hex_digit(char d) {
else return -1;
}
// Given a string argument that's either a label or a
// hex value, either dereference the label or convert
// Given a string argument that's either a label,
// hex value, or a register, either dereference the label or convert
// the hex to an int. Returns -1 on error.
int DebuggerParser::decipher_arg(string &arg) {
int DebuggerParser::decipher_arg(string &arg, bool deref) {
const char *a = arg.c_str();
int address = debugger->equateList->getAddress(a);
// cerr << "decipher_arg: equateList->getAddress(" << a << ") == " << address << endl;
if(address >= 0)
return address;
int address;
address = 0;
while(*a != '\0') {
int hex = conv_hex_digit(*a++);
if(hex < 0)
return -1;
// Special cases (registers):
if(arg == "a") address = debugger->getA();
else if(arg == "x") address = debugger->getX();
else if(arg == "y") address = debugger->getY();
else if(arg == "p") address = debugger->getP();
else if(arg == "s") address = debugger->getS();
else if(arg == "pc") address = debugger->getPC();
else { // normal addresses: check for label first
address = debugger->equateList->getAddress(a);
address = (address << 4) + hex;
// if not label, must be hex.
if(address < 0) {
address = 0;
while(*a != '\0') {
int hex = conv_hex_digit(*a++);
if(hex < 0)
return -1;
address = (address << 4) + hex;
}
}
}
// dereference if we're supposed to:
if(deref) address = debugger->peek(address);
return address;
}
bool DebuggerParser::getArgs(const string& command) {
int state = kIN_COMMAND;
int deref = 0;
bool deref = false;
string curArg = "";
argCount = 0;
verb = "";
@ -112,30 +127,21 @@ bool DebuggerParser::getArgs(const string& command) {
state = kIN_ARG_CONT;
// FIXME: actually use this.
if(*c == '*') {
deref = 1;
deref = true;
c++;
} else {
deref = 0;
deref = false;
} // FALL THROUGH!
case kIN_ARG_CONT:
/*if(isxdigit(*c)) {
int dig = conv_hex_digit(*c);
curArg = (curArg << 4) + dig;
*c++;
} else {
args[argCount++] = curArg;
state = kIN_SPACE;
}
break;*/
if(isalpha(*c) || isdigit(*c) || *c == '_') {
curArg += *c++;
// cerr << "curArg: " << curArg << endl;
} else {
args[argCount] = decipher_arg(curArg);
if(args[argCount] < 0)
int a = decipher_arg(curArg, deref);
if(a < 0)
return false;
argCount++;
args[argCount++] = a;
curArg = "";
state = kIN_SPACE;
}
@ -150,7 +156,7 @@ bool DebuggerParser::getArgs(const string& command) {
// pick up last arg, if any:
if(state == kIN_ARG_CONT || state == kIN_ARG_START)
if( (args[argCount++] = decipher_arg(curArg)) < 0)
if( (args[argCount++] = decipher_arg(curArg, deref)) < 0)
return false;
// for(int i=0; i<argCount; i++)
@ -205,6 +211,31 @@ string DebuggerParser::disasm() {
return debugger->disassemble(start, lines);
}
string DebuggerParser::eval() {
char buf[10];
string ret;
for(int i=0; i<argCount; i++) {
char *label = debugger->equates()->getLabel(args[i]);
if(label != NULL) {
ret += label;
ret += ": ";
}
if(args[i] < 0x100) {
ret += Debugger::to_hex_8(args[i]);
ret += " ";
ret += Debugger::to_bin_8(args[i]);
} else {
ret += Debugger::to_hex_16(args[i]);
ret += " ";
ret += Debugger::to_bin_16(args[i]);
}
sprintf(buf, " %d", args[i]);
ret += buf;
if(i != argCount - 1) ret += "\n";
}
return ret;
}
string DebuggerParser::run(const string& command) {
string result;
@ -319,15 +350,23 @@ string DebuggerParser::run(const string& command) {
} else if(subStringMatch(verb, "disasm")) {
return disasm();
} else if(subStringMatch(verb, "frame")) {
/*
// FIXME: make multiple frames work!
int count = 0;
if(argCount != 0) count = args[0];
// FIXME: make multiple frames work!
for(int i=0; i<count; i++)
debugger->nextFrame();
*/
debugger->nextFrame();
return "OK";
} else if(subStringMatch(verb, "clearbreaks")) {
debugger->clearAllBreakPoints();
return "cleared all breakpoints";
} else if(subStringMatch(verb, "eval")) {
if(argCount < 1)
return "one or more arguments required";
else
return eval();
} else if(subStringMatch(verb, "quit") || subStringMatch(verb, "run")) {
debugger->quit();
return "";
@ -336,6 +375,8 @@ string DebuggerParser::run(const string& command) {
// easy to sort - bkw
return
"Commands are case-insensitive and may be abbreviated.\n"
"Arguments are either labels or hex constants, and may be\n"
"prefixed with a * to dereference.\n"
"a xx - Set Accumulator to xx\n"
"break - Set/clear breakpoint at current PC\n"
"break xx - Set/clear breakpoint at address xx\n"
@ -344,19 +385,20 @@ string DebuggerParser::run(const string& command) {
"d - Toggle Decimal Flag\n"
"disasm - Disassemble (from current PC)\n"
"disasm xx - Disassemble (from address xx)\n"
"eval xx - Evaluate expression xx\n"
"frame - Advance to next TIA frame, then break\n"
"listbreaks - List all breakpoints\n"
"loadsym f - Load DASM symbols from file f\n"
"n - Toggle Negative Flag\n"
"pc xx - Set Program Counter to xx\n"
"ram - Show RIOT RAM contents\n"
"ram xx yy - Set RAM location xx to value yy (multiple values may be given)\n"
"ram xx yy - Set RAM location xx to value yy (multiple values allowed)\n"
"reset - Jump to 6502 init vector (does not reset TIA/RIOT)\n"
"run - Exit debugger (back to emulator)\n"
"s xx - Set Stack Pointer to xx\n"
"step - Single-step\n"
"tia - Show TIA register contents\n"
"trace - Single-step treating subroutine calls as one instruction\n"
"trace - Single-step treating subroutine calls as 1 instruction\n"
"v - Toggle Overflow Flag\n"
"x xx - Set X register to xx\n"
"y xx - Set Y register to xx\n"

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: DebuggerParser.hxx,v 1.6 2005-06-17 21:59:53 urchlay Exp $
// $Id: DebuggerParser.hxx,v 1.7 2005-06-18 17:28:18 urchlay Exp $
//============================================================================
#ifndef DEBUGGER_PARSER_HXX
@ -38,12 +38,12 @@ class DebuggerParser
private:
int DebuggerParser::conv_hex_digit(char d);
bool DebuggerParser::subStringMatch(const string& needle, const string& haystack);
int decipher_arg(string &arg);
int decipher_arg(string &arg, bool deref);
string disasm();
string listBreaks();
string eval();
Debugger* debugger;
EquateList *equateList;
bool done;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: EquateList.cxx,v 1.7 2005-06-16 02:16:26 urchlay Exp $
// $Id: EquateList.cxx,v 1.8 2005-06-18 17:28:18 urchlay Exp $
//============================================================================
#include <string>
@ -120,7 +120,7 @@ int EquateList::calcSize() {
char *EquateList::getLabel(int addr) {
// cerr << "getLabel(" << addr << ")" << endl;
for(int i=0; ourVcsEquates[i].label != NULL; i++) {
// cerr << "Checking ourVcsEquates[" << i << "] (" << ourVcsEquates[i].label << endl;
// cerr << "Checking ourVcsEquates[" << i << "] (" << ourVcsEquates[i].label << ")" << endl;
if(ourVcsEquates[i].address == addr) {
// cerr << "Found label " << ourVcsEquates[i].label << endl;
return ourVcsEquates[i].label;