if (mode == 10) {
cpu.triggBreakpoint();
}
} else {
if (length > 1) {
Memory mem = cpu.getMemory();
for (int i = address; i < address + length; i++) {
context.out.print(Utils.toString(mem.get(i, AccessMode.BYTE), Utils.BYTE, mode));
}
context.out.println();
} else {
context.out.print(Utils.toString(data, Utils.BYTE, mode));
}
}
}
@Override
public void notifyReadBefore(int addr, AccessMode mode, AccessType type) {
cpuAction(AccessType.READ, addr, cpu.getMemory().get(addr, mode));
}
@Override
public void notifyWriteBefore(int dstAddress, int data, AccessMode mode) {
cpuAction(AccessType.WRITE, dstAddress, data);
}
};
for (int i = 0; i < length; i++) {
cpu.addWatchPoint(address + i, monitor);
}
if (length > 1) {
context.err.println("Watch set at $" + cpu.getAddressAsString(address) + " - $" + cpu.getAddressAsString(address + length - 1));
} else {
context.err.println("Watch set at $" + cpu.getAddressAsString(address));
}
return 0;
}
public void stopCommand(CommandContext context) {
for (int i = 0; i < length; i++) {
cpu.removeWatchPoint(address + i, monitor);
}
context.exit(0);
}
});
ch.registerCommand("watchreg",
new BasicAsyncCommand("add a write watch to a given register", "<register> [int]") {
int watchMode = 0;
int register = 0;
RegisterMonitor monitor;
public int executeCommand(final CommandContext context) {
register = context.getArgumentAsRegister(0);
if (register < 0) {
return -1;
}
if (context.getArgumentCount() > 1) {
String modeStr = context.getArgument(1);
if ("int".equals(modeStr)) {
watchMode = 1;
} else {
context.err.println("illegal argument: " + modeStr);
return -1;
}
}
monitor = new RegisterMonitor.Adapter() {
@Override
public void notifyWriteBefore(int register, int data, AccessMode mode) {
if (watchMode == 0) {
int pc = cpu.getPC();
String adrStr = getRegisterName(register);
String pcStr = getSymOrAddrELF(cpu, getELF(), pc);
context.out.println("*** Write from " + pcStr +
": " + adrStr + " = " + data);
} else {
context.out.println(data);
}
}
};
cpu.addRegisterWriteMonitor(register, monitor);
context.err.println("Watch set for register " + getRegisterName(register));
return 0;
}
public void stopCommand(CommandContext context) {
cpu.removeRegisterWriteMonitor(register, monitor);
}
});
// ch.registerCommand("clear", new BasicCommand("clear a breakpoint or watch from a given address or symbol", "<address or symbol>") {
// public int executeCommand(final CommandContext context) {
// int baddr = context.getArgumentAsAddress(0);
// cpu.setBreakPoint(baddr, null);
// return 0;
// }
// });
ch.registerCommand("symbol", new BasicCommand("list matching symbols", "<regexp>") {
public int executeCommand(final CommandContext context) {
String regExp = context.getArgument(0);
MapEntry[] entries = context.getMapTable().getEntries(regExp);
if (entries.length == 0) {
context.err.println("Could not find any symbols matching '" + regExp + '\'');
} else {
for (MapEntry mapEntry : entries) {
int address = mapEntry.getAddress();
String file = mapEntry.getFile();
if (file == null) {
file = "(unspecified)";
}
context.out.println(" " + mapEntry.getName() + " at $"
+ cpu.getAddressAsString(address) + " ($"
+ Utils.hex8(cpu.getMemory().get(address, AccessMode.BYTE))
+ ' ' + Utils.hex8(cpu.getMemory().get(address + 1, AccessMode.BYTE)) + ") "
+ mapEntry.getType() + " in file " + file);
}
}
return 0;
}
});
ch.registerCommand("debug", new BasicCommand("set debug to on or off", "[0/1]") {
public int executeCommand(final CommandContext context) {
if (context.getArgumentCount() > 0) {
cpu.setDebug(context.getArgumentAsBoolean(0));
}
context.out.println("Debug is set to " + cpu.getDebug());
return 0;
}
});
ch.registerCommand("line", new BasicCommand("print line number of address/symbol", "<address or symbol>") {
public int executeCommand(final CommandContext context) {
int adr = context.getArgumentAsAddress(0);
DebugInfo di = getELF().getDebugInfo(adr);
if (di == null) {
/* quick hack to test next address too... - since something seems to be off by one sometimes... */
di = getELF().getDebugInfo(adr + 1);
}
if (di != null) {
di.getLine();
context.out.println(di);
} else {
context.err.println("No line number found for: " + context.getArgument(0));
}
return 0;
}
});
if (node != null) {
ch.registerCommand("stop", new BasicCommand("stop the CPU", "") {
public int executeCommand(CommandContext context) {
if (!cpu.isRunning()) {
context.err.println("CPU is not running");
return 1;
}
node.stop();
context.out.println("CPU stopped at: $" + cpu.getAddressAsString(cpu.getPC()));
return 0;
}
});
ch.registerCommand("start", new BasicCommand("start the CPU", "") {
public int executeCommand(CommandContext context) {
if (cpu.isRunning()) {
context.err.println("cpu already running");
return 1;
}
node.start();
return 0;
}
});
ch.registerCommand("throw", new BasicCommand("throw an Emulation Exception", "[message]") {
public int executeCommand(CommandContext context) {
final String msg = context.getArgumentCount() > 0 ? context.getArgument(0) : "by request";
cpu.scheduleCycleEvent(new TimeEvent(0, "EmulationException") {
@Override public void execute(long t) {
throw new EmulationException(msg);
}}, cpu.cycles);
return 0;
}
});
ch.registerCommand("step", new BasicCommand("single step the CPU", "[number of instructions]") {
public int executeCommand(CommandContext context) {
int nr = context.getArgumentCount() > 0 ? context.getArgumentAsInt(0) : 1;
long cyc = cpu.cycles;
if (cpu.isRunning()) {
context.err.println("Can not single step when emulation is running.");
return -1;
}
try {
node.step(nr);
} catch (Exception e) {
e.printStackTrace(context.out);
}
context.out.println("CPU stepped to: $" + cpu.getAddressAsString(cpu.getPC()) +
" in " + (cpu.cycles - cyc) + " cycles (" + cpu.cycles + ")");
return 0;
}
});
ch.registerCommand("stepmicro", new BasicCommand("single the CPU specified no micros", "<micro skip> <micro step>") {
public int executeCommand(CommandContext context) {
long cyc = cpu.cycles;
if (cpu.isRunning()) {
context.err.println("Can not single step when emulation is running.");
return -1;
}
long nxt = 0;
try {
nxt = cpu.stepMicros(context.getArgumentAsLong(0), context.getArgumentAsLong(1));
} catch (Exception e) {
e.printStackTrace(context.out);
}
context.out.println("CPU stepped to: $" + cpu.getAddressAsString(cpu.getPC()) +
" in " + (cpu.cycles - cyc) + " cycles (" + cpu.cycles + ") - next exec time: " + nxt);
return 0;
}
});
ch.registerCommand("stack", new BasicCommand("show stack info", "") {
public int executeCommand(CommandContext context) {
int stackEnd = context.getMapTable().heapStartAddress;
int stackStart = context.getMapTable().stackStartAddress;
int current = cpu.getSP();
context.out.println("Current stack: $" + cpu.getAddressAsString(current) + " (" + (stackStart - current) + " used of " + (stackStart - stackEnd) + ')');
return 0;
}
});
ch.registerCommand("print", new BasicCommand("print value of an address or symbol", "<address or symbol>") {
public int executeCommand(CommandContext context) {
int adr = context.getArgumentAsAddress(0);
if (adr >= 0) {
int value = cpu.memory[adr];
if (adr >= 0x100 && adr + 1 < cpu.MAX_MEM) {
value |= cpu.memory[adr + 1] << 8;
}
context.out.println(context.getArgument(0) + " = $" + Utils.hex16(value));
return 0;
}
context.err.println("unknown symbol: " + context.getArgument(0));
return 1;
}
});
ch.registerCommand("printreg", new BasicCommand("print value of an register", "[register]") {
public int executeCommand(CommandContext context) {
if (context.getArgumentCount() > 0) {
for (int i = 0, n = context.getArgumentCount(); i < n; i++) {
int register = context.getArgumentAsRegister(i);
if (i > 0) {
context.out.print((i % 6) == 0 ? "\n" : " ");
}
if (register >= 0) {
context.out.print(getRegisterName(i) + "=$" + Utils.hex(cpu.getRegister(register), 4));
} else {
context.out.print(context.getArgument(i) + "=<not a register>");
}
}
} else {
for (int i = 0; i < 16; i++) {
if (i > 0) {
context.out.print((i % 6) == 0 ? "\n" : " ");
}
context.out.print(getRegisterName(i) + "=$" + Utils.hex(cpu.getRegister(i), 4));
}
}
context.out.println();
return 0;
}
});
ch.registerCommand("reset", new BasicCommand("reset the CPU", "") {
public int executeCommand(CommandContext context) {
cpu.reset();
return 0;
}
});
ch.registerCommand("time", new BasicCommand("print the elapse time and cycles", "") {
public int executeCommand(CommandContext context) {
long time = (long)cpu.getTimeMillis();
long wallDiff = System.currentTimeMillis() - lastWall;
context.out.println("Emulated time elapsed: " + time + "(ms) since last: " + (time - lastCall) + " ms" + " wallTime: " +
wallDiff + " ms speed factor: " +
(wallDiff == 0 ? "N/A" : "" + (time - lastCall) / wallDiff));
lastCall = time;
lastWall = System.currentTimeMillis();
return 0;
}
});
ch.registerCommand("mem", new BasicCommand("dump memory", "<start address> <num_entries> [type] [hex|char|dis]") {
public int executeCommand(final CommandContext context) {
int start = context.getArgumentAsAddress(0);
if (start < 0) {
context.err.println("Illegal start address: "
+ context.getArgument(0));
return 1;
}
int count = context.getArgumentAsInt(1);
int mode = Utils.DEC;
int type = Utils.UBYTE;
boolean signed = false;
if (context.getArgumentCount() > 2) {
int pos = 2;
int acount = context.getArgumentCount();
if (acount > 4) acount = 4;
while (pos < acount) {
String tS = context.getArgument(pos++);
if ("ubyte".equals(tS)) {
} else if ("byte".equals(tS)) {
type = Utils.BYTE;
} else if ("word".equals(tS)) {
type = Utils.WORD;
} else if ("uword".equals(tS)) {
type = Utils.UWORD;
} else if ("hex".equals(tS)) {
mode = Utils.HEX;
} else if ("char".equals(tS)) {
mode = Utils.ASCII;
type = Utils.BYTE;
} else if ("dis".equals(tS)) {
mode = Utils.DIS_ASM;
type = Utils.WORD;
}
}
}
// Does not yet handle signed data...
DisAsm disAsm = cpu.getDisAsm();
for (int i = 0; i < count; i++) {
if (mode == Utils.DIS_ASM) {
DbgInstruction dbg = disAsm.disassemble(start, cpu.memory, cpu.reg, new DbgInstruction(),
0);
String fkn;
if ((fkn = dbg.getFunction()) != null) {
context.out.println("//// " + fkn);
}
context.out.println(dbg.getASMLine(false));
start += dbg.getSize();
} else {
int data = 0;
data = cpu.memory[start++];
if (Utils.size(type) == 2) {
data = data + (cpu.memory[start++] << 8);
}
context.out.print((mode != Utils.ASCII ? " " : "") +
Utils.toString(data, type, mode));
}
}
context.out.println();
return 0;
}
});
ch.registerCommand("mset", new BasicCommand("set memory", "<address> [type] <value> [value ...]") {
public int executeCommand(final CommandContext context) {
int count = context.getArgumentCount();
int adr = context.getArgumentAsAddress(0);
String arg2 = context.getArgument(1);
int type = Utils.BYTE;
int mode = Utils.DEC;
boolean typeRead = false;
if (count > 2) {
if ("char".equals(arg2)) {
mode = Utils.ASCII;
typeRead = true;
}
if ("word".equals(arg2)) {
type = Utils.WORD;
typeRead = true;
}
}
for (int i = typeRead ? 2 : 1; i < count; i++) {
if (mode == Utils.DEC) {
int val = context.getArgumentAsInt(i);
AccessMode accessMode = Utils.size(type) == 2 || val > 0xff ? AccessMode.WORD : AccessMode.BYTE;
try {
cpu.getMemory().set(adr, val, accessMode);
adr += accessMode.bytes;
} catch (EmulationException e) {
e.printStackTrace(context.out);
}
} else if (mode == Utils.ASCII) {
String data = context.getArgument(i);
Memory mem = cpu.getMemory();
for (int j = 0; j < data.length(); j++) {
mem.set(adr++, data.charAt(j), AccessMode.BYTE);
}
}
}
return 0;
}});