Thanks for all the information. I'll add it to my possible future projects stack (which is quite large at the moment, so perhaps some pruning is in order.)
It's interesting that you mention an AVR Emulator, as I spent quite a bit of time writing one in Java some time back. It was originally intended as a way to simulate and debug code in my ATTiny10IDE project, as there are no hardware debug features on the ATTiny10. However, there are so many special cases to test and verify that I put it on the back burner.
But, now that I understand how debugWire works, I think it may be possible to use my debugger code as a way to verify simulated code. One of the key features of debugWire is the ability to send an arbitrary opcode to the target device and execute it. In fact, this is how many of the higher level operations are implemented in my debugger. For example, the command to set and clear bits in I/O registers (IOxx.0=b) is implemented by dynamically generating an "sbi/cbi addr,bit" instruction and then using a special debugWire command to execute it, like this:
// Set or clear bit in I/O address 0x00 - 0x1F by generating and executing an "sbi" or "cbi" instruction
void setClrIOBit (byte addr, byte bit, boolean set) {
// Generate an "sbi/cbi addr,bit" instruction
byte cmd[] = {0x64, 0xD2, set ? 0x9A : 0x98, ((addr & 0x1F) << 3) + (bit & 0x7), 0x23}; // 1001 10x0 aaaa abbb
sendCmd(cmd, sizeof(cmd));
}
So, in similar fashion, I could use this feature to "shadow" execute all the same code the emulator processes, read back the state of the target machine after execution and then compare this to the state computed by the emulator. Of course, this still leave another, rather daunting problem, which is to generate test code that will exercise all the possible states that need to be tested.
Wayne