}
public void setupCommands(ComponentRegistry registry, CommandHandler ch) {
this.registry = registry;
final MSP430 cpu = registry.getComponent(MSP430.class);
final GenericNode node = registry.getComponent(GenericNode.class, "node");
if (cpu != null) {
ch.registerCommand("break", new BasicAsyncCommand("add a breakpoint to a given address or symbol",
"<address or symbol>") {
private int address;
private MemoryMonitor monitor;
public int executeCommand(final CommandContext context) {
address = context.getArgumentAsAddress(0);
if (address < 0) {
context.err.println("unknown symbol: " + context.getArgument(0));
return 1;
}
monitor = new MemoryMonitor.Adapter() {
private long lastCycles = -1;
@Override
public void notifyReadBefore(int address, AccessMode mode, AccessType type) {
if (type == AccessType.EXECUTE && cpu.cycles != lastCycles) {
context.out.println("*** Break at $" + cpu.getAddressAsString(address));
cpu.triggBreakpoint();
lastCycles = cpu.cycles;
}
}
};
cpu.addWatchPoint(address, monitor);
context.err.println("Breakpoint set at $" + cpu.getAddressAsString(address));
return 0;
}
public void stopCommand(CommandContext context) {
cpu.removeWatchPoint(address, monitor);
}
});
ch.registerCommand("watch",
new BasicAsyncCommand("add a write/read watch to a given address or symbol", "<address or symbol> [length] [char | hex | break]") {
int mode = 0;
int address = 0;
int length = 1;
MemoryMonitor monitor;
public int executeCommand(final CommandContext context) {
address = context.getArgumentAsAddress(0);
if (address < 0) {
context.err.println("unknown symbol: " + context.getArgument(0));
return -1;
}
if (context.getArgumentCount() > 1) {
for (int i = 1; i < context.getArgumentCount(); i++) {
String modeStr = context.getArgument(i);
if (Character.isDigit(modeStr.charAt(0))) {
length = Integer.parseInt(modeStr);
} else if ("char".equals(modeStr)) {
mode = Utils.ASCII_UNMODIFIED; // 4
} else if ("break".equals(modeStr)) {
mode = 10;
} else if ("hex".equals(modeStr)) {
mode = Utils.HEX; // 2
}
}
}
if (length < 1) {
context.err.println("please specify a length of at least one byte");
return -1;
}
monitor = new MemoryMonitor.Adapter() {
private void cpuAction(AccessType type, int adr, int data) {
if (mode == 0 || mode == 10) {
int pc = cpu.getPC();
String adrStr = getSymOrAddr(cpu, context, adr);
String pcStr = getSymOrAddrELF(cpu, getELF(), pc);
String op = "op";
if (type == AccessType.READ) {
op = "Read";
} else if (type == AccessType.WRITE){
op = "Write";
}
context.out.println("*** " + op + " from " + pcStr +
": " + adrStr + " = 0x" + Utils.hex(data, 4));
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 + ")");