diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index 7d74f71..d14c5ad 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -52,6 +52,7 @@ char *cmdStrings[] = { "fill", #if defined(CPU_6502) || defined(CPU_65C02) "go", + "exec", #endif "crc", "copy", @@ -103,6 +104,7 @@ void (*cmdFuncs[])(char *params) = { doCmdFill, #if defined(CPU_6502) || defined(CPU_65C02) doCmdGo, + doCmdExec, #endif doCmdCrc, doCmdCopy, @@ -157,6 +159,7 @@ static const char ARGS12[] PROGMEM = " [ ]"; static const char ARGS13[] PROGMEM = " "; static const char ARGS14[] PROGMEM = "[ ]"; static const char ARGS15[] PROGMEM = "[ ]"; +static const char ARGS16[] PROGMEM = " [ [ ] ]"; static const char * const argsStrings[] PROGMEM = { ARGS00, @@ -175,57 +178,59 @@ static const char * const argsStrings[] PROGMEM = { ARGS13, ARGS14, ARGS15, + ARGS16 }; // Must be kept in step with cmdStrings (just above) static const uint8_t helpMeta[] PROGMEM = { #if defined(COMMAND_HISTORY) - 17, 7, // history + 18, 7, // history #endif - 16, 15, // help + 17, 15, // help 9, 8, // continue - 22, 7, // next - 30, 6, // step - 25, 7, // regs + 23, 7, // next + 31, 6, // step + 26, 7, // regs 12, 10, // dis - 15, 7, // flush + 16, 7, // flush 13, 11, // fill #if defined(CPU_6502) || defined(CPU_65C02) 14, 0, // go + 15, 16, // exec #endif 11, 9, // crc 10, 13, // copy 8, 13, // compare - 21, 1, // mem - 24, 2, // rd - 39, 3, // wr + 22, 1, // mem + 25, 2, // rd + 40, 3, // wr #if defined(CPU_Z80) - 19, 1, // io - 18, 2, // in - 23, 3, // out + 20, 1, // io + 19, 2, // in + 24, 3, // out #endif - 31, 12, // test - 20, 0, // load - 27, 9, // save - 29, 7, // srec - 28, 14, // special - 26, 7, // reset - 32, 6, // trace + 32, 12, // test + 21, 0, // load + 28, 9, // save + 30, 7, // srec + 29, 14, // special + 27, 7, // reset + 33, 6, // trace 1, 7, // blist 6, 4, // breakx - 38, 4, // watchx + 39, 4, // watchx 4, 4, // breakr - 36, 4, // watchr + 37, 4, // watchr 5, 4, // breakw - 37, 4, // watchw + 38, 4, // watchw #if defined(CPU_Z80) 2, 4, // breaki - 33, 4, // watchi + 35, 4, // watchi 3, 4, // breako - 35, 4, // watcho + 36, 4, // watcho #endif 7, 0, // clear - 33, 5, // trigger + 34, 5, // trigger 0, 0 }; @@ -1475,6 +1480,27 @@ void doCmdGo(char *params) { logAddr(); } +void doCmdExec(char *params) { + data_t op1 = 0; + data_t op2 = 0; + data_t op3 = 0; + params = parsehex2(params, &op1); + params = parsehex2(params, &op2); + params = parsehex2(params, &op3); + // Read the current PC value + addr_t addr = hwRead16(OFFSET_IAL); + // Execute the specifed opcode + loadData(op1); + loadAddr(op2 + (op3 << 8)); + hwCmd(CMD_EXEC_GO, 0); + // JMP back to the original PC value + loadData(0x4C); + loadAddr(addr); + hwCmd(CMD_EXEC_GO, 0); + // Log where we are + logAddr(); +} + #endif void doCmdCrc(char *params) { diff --git a/firmware/AtomBusMon.h b/firmware/AtomBusMon.h index 4c5c33b..2775cdf 100644 --- a/firmware/AtomBusMon.h +++ b/firmware/AtomBusMon.h @@ -53,6 +53,7 @@ void doCmdContinue(char *params); void doCmdCopy(char *params); void doCmdCrc(char *params); void doCmdDis(char *params); +void doCmdExec(char *params); void doCmdFlush(char *params); void doCmdFill(char *params); void doCmdGo(char *params); diff --git a/src/BusMonCore.vhd b/src/BusMonCore.vhd index 27ad9aa..dca2574 100644 --- a/src/BusMonCore.vhd +++ b/src/BusMonCore.vhd @@ -450,7 +450,7 @@ begin -- 10101 Read IO and Auto Inc Address -- 10110 Write IO -- 10111 Write IO and Auto Inc Address - -- 11000 Exec Go + -- 11000 Execute 6502 instruction -- 111xx Unused -- 11x1x Unused -- 11xx1 Unused diff --git a/src/MOS6502CpuMonCore.vhd b/src/MOS6502CpuMonCore.vhd index c62c834..2531a66 100644 --- a/src/MOS6502CpuMonCore.vhd +++ b/src/MOS6502CpuMonCore.vhd @@ -114,6 +114,7 @@ architecture behavioral of MOS6502CpuMonCore is signal exec : std_logic; signal exec_held : std_logic; + signal op3 : std_logic; begin @@ -238,6 +239,31 @@ begin Addr_int(15 downto 0) <= std_logic_vector(cpu_addr_us); end generate; +-- 00 IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP, +-- 10 BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMPA, IMP, ABS, ABSX, ABSX, IMP, +-- 20 ABS, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP, +-- 30 BRA, INDY, IND, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABSY, IMPA, IMP, ABSX, ABSX, ABSX, IMP, +-- 40 IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP, +-- 50 BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +-- 60 IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, IND16, ABS, ABS, IMP, +-- 70 BRA, INDY, IND, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, IND1X, ABSX, ABSX, IMP, +-- 80 BRA, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +-- 90 BRA, INDY, IND, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +-- A0 IMM, INDX, IMM, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +-- B0 BRA, INDY, IND, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABSY, IMP, IMP, ABSX, ABSX, ABSY, IMP, +-- C0 IMM, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +-- D0 BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +-- E0 IMM, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +-- F0 BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP + + -- Detect forced opcodes that are 3 bytes long + op3 <= '1' when memory_dout(7 downto 0) = "00100000" else + '1' when memory_dout(4 downto 0) = "11011" else + '1' when memory_dout(3 downto 0) = "1100" else + '1' when memory_dout(3 downto 0) = "1101" else + '1' when memory_dout(3 downto 0) = "1110" else + '0'; + Din_int <= memory_dout( 7 downto 0) when state = idle and Sync_int = '1' and exec_held = '1' else memory_addr( 7 downto 0) when state = exec1 else memory_addr(15 downto 8) when state = exec2 else @@ -303,7 +329,11 @@ begin state <= nop0; -- exec1 is the LSB of a forced JMP when exec1 => - state <= exec2; + if op3 = '1' then + state <= exec2; + else + state <= idle; + end if; -- exec2 is the MSB of a forced JMP when exec2 => state <= idle; @@ -333,7 +363,7 @@ begin -- Data is captured by the bus monitor on the rising edge of cpu_clk -- that sees done = 1. - memory_done <= '1' when state = rd or state = wr or state = exec2 else '0'; + memory_done <= '1' when state = rd or state = wr or (op3 = '0' and state = exec1) or state = exec2 else '0'; memory_din <= Din;