The Sorbus Computer:
Monitor Command Prompt

The MCP is not an environment to act as a standard computer. It is intended as a system to take a look at the CPU which is as deep as possible without emulating it. So dumping of registers for example is not possible. (In theory it is using a trick, but this needs to be implemented, yet.)


Examples

Here are some examples how you can see what the CPU does during every single clock cycle. Please note, that writing to that stack will happen at different addresses within the $0100-$01ff area, as the stackpointer is not initialized.

Commands used:

s <cycles>
let the CPU run for <cycles> cycles / steps. The parameter is decimal.
f <start> <end> <value>
fill the memory from <start> to <end> with the value <value>. All parameter are hexadecimal.
reset <cycles>
pull the reset line to low for <cycles> cycles. The parameter is decimal.
: <start> <value> (<value> ...)
pull the reset line to low for <cycles> cycles. The parameter is decimal.

Commands are case sensitive, hexadecimal numbers are not.

Output:

Let's use a fictional example to explain the output:
100:fffc r 00 R  >
From left to right:
100:
number of cycles left to run: if number > 999 then 999 will be displayed.
fffc
current state of address-bus → address being accessed.
r
data is being read. (Only other value here would be "w" for write.)
00
current state of data-bus → value being read or written.
R
other CPU lines being triggered by pulling low: R=reset (triggered in this case), others are (not triggered here): N=nmi, I=irq.
>
the monitor command prompt, you can type while the CPU is running.

Lesson 1: reset and NOP

This lesson will run on 6502, 65C02 and 65816.

Commands to enter:

f 0000 ffff ea
reset 5
s 17

Output:

 16:eaeb r ea R  >
 15:eaec r ea R  >
 14:eaec r ea R  >
 13:eaec r ea R  >
 12:eaec r ea R  >
 11:eaec r ea    >
 10:eaec r ea    >
  9:eaec r ea    >
  8:01f7 r ea    >
  7:01f6 r ea    >
  6:01f5 r ea    >
  5:fffc r ea    >
  4:fffd r ea    >
  3:eaea r ea    >
  2:eaeb r ea    >
  1:eaeb r ea    >
  0:eaec r ea    >

Explanation (hover to show)

During cycles 16-12 the CPU does nothing, since reset is triggered.
During cycles 11-9 the CPU starts running internally.
During cycles 8-6 stack access is happening, because reset is implemented similar to an interrupt.
The behavour until here might differ from chip to chip!
During cycles 5-4 the reset vector is read, low byte first.
During cycles 3-2 a NOP OpCode are processed. Since the OpCode takes two cycles to execute, the CPU triggers a dummy read on the following address. Just in case, there is a parameter for an instruction to fetch.
During cycles 1-0 the next NOP OpCode is processed.

Lesson 2: another kind of NOP

This only run on 65C02. The OpCode used has no equivalent on 6502 and 65816.

Commands to enter:

f 0000 ffff 33
reset 5
s 17

Output:

[...skipping unimportant lines...]
  5:fffc r 33    >
  4:fffd r 33    >
  3:3333 r 33    >
  2:3334 r 33    >
  1:3335 r 33    >
  0:3336 r 33    >

Explanation (hover to show)

During cycles 5-4 the reset vector is read, low byte first.
During cycles 3-0 undocumented OpCodes are processed. This is handles differently on each variant:

Lesson 3: a simple program

If you ran lessons 1 and/or 2, power cycle the Sorbus Computer. This ensures that the program executed will be in memory. This lesson will run on 6502, 65C02 and 65816. Also take a good look at the output of the memory dump. Does that look familiar to you?

Commands to enter:

f 1000 1100 00
: fffc 00 04
reset 5
freq 1000
s 345
freq 5
m 1000

Output:

[...skipping a lot of output...]
  5:0421 r b0    >
  4:0422 r fe    >
  3:0423 r e8    >
  2:0421 r b0    >
  1:0422 r fe    >
  0:0423 r e8    >m 1000
: 1000  00 01 01 02 03 05 08 0d  15 22 37 59 90 e9 00 00
  0:0423 r e8    >

Explanation (hover to show)

The rest of the output show that the program running is in an endless loop. The output is of course the start of the Fibonacci sequence as far as it can be calculated in 8 bits. The code is stopping when the add overflows.

Lesson 4: subroutine

This runs on all CPUs: 65C02, 6502 and 65816. No need to powercycle.

Commands to enter:

: fffc 03 04
reset 5
s 35

Output:

 23:fffc r 03    >
 22:fffd r 04    >
 21:0403 r 4c    >
 20:0404 r 2a    >
 19:0405 r 04    >
 18:042a r 20    >
 17:042b r 57    >
 16:01dc r ea    >
 15:01dc w 04    >
 14:01db w 2c    >
 13:042c r 04    >
 12:0457 r ea    >
 11:0458 r ea    >
 10:0458 r ea    >
  9:0459 r 60    >
  8:0459 r 60    >
  7:045a r 00    >
  6:01da r ea    >
  5:01db r 2c    >
  4:01dc r 04    >
  3:042c r 04    >
  2:042d r 4c    >
  1:042e r 2d    >
  0:042f r 04    >

Explanation (hover to show)

After the reset, the first instruction is a JuMP, so I can easily modify the code without the need to change the start address.
During the cycles 18-13 the CPU executes a Jump to SubRoutine:
18: fetch the JSR OpCode
17: fetch low byte of jump target address
16: dummy read of stack
15: write high byte of return address minus 1 to stack
14: write low byte of return address minus 1 to stack
13: fetch high byte of jump target address and perform jump
The ReTurn from Subroutine starts at cycle 8 (cycle 9 is the dummy read from the NOP OpCode at 10):
8: fetch the RTS OpCode
7: dummy read non-existant parameter
6: dummy read from stack
5: fetch low byte of return address minus 1 from stack
4: fetch high byte of return address minus 1 from stack
3: dummy read from memory to adjust program counter to correct return address and jump back
2-0: endless loop
Interesting how the return address minus one gets written to stack and how it is compensated by the return call. This seems to be caused by the split of reading the low and high bytes of the target address.

Lesson 5: data on stack

This runs on all CPUs: 65C02, 6502 and 65816. No need to powercycle.

Commands to enter:

: FFFC 06 04
reset 5
s 30

Output:

 18:fffc r 06    >
 17:fffd r 04    >
 16:0406 r 4c    >
 15:0407 r 30    >
 14:0408 r 04    >
 13:0430 r a9    >
 12:0431 r 42    >
 11:0432 r 48    >
 10:0433 r 68    >
  9:01f1 w 42    >
  8:0433 r 68    >
  7:0434 r 4c    >
  6:01f0 r ea    >
  5:01f1 r 42    >
  4:0434 r 4c    >
  3:0435 r 34    >
  2:0436 r 04    >
  1:0434 r 4c    >
  0:0435 r 34    >

Explanation (hover to show)

After the reset, the first instruction is a JuMP, so I can easily modify the code without the need to change the start address. Next the accumulator is loaded with a recognizable value ($42).
Push the value on the stack
11: fetch the PHA OpCode
10: dummy argument read
9: push value to the stack
8: fetch the PLA OpCode
7: dummy argument read
6: dummy read from stack to adjust stack pointer
5: pull value from the stack
4-0: endless loop

Lesson 6: interrupt via IRQ line

This runs on all CPUs: 65C02, 6502 and 65816. No need to powercycle.

Commands to enter:

: FFFC 09 04
reset 5
s 30
irq 8
s 36

Output:

 13:0437 r a9    >
 12:0438 r 5d    >
 11:0439 r 8d    >
 10:043a r fe    >
  9:043b r ff    >
  8:fffe w 5d    >
  7:043c r a9    >
  6:043d r 04    >
  5:043e r 8d    >
  4:043f r ff    >
  3:0440 r ff    >
  2:ffff w 04    >
  1:0441 r ea    >
  0:0442 r ea    >irq 8
 35:0442 r ea   I>
 34:0443 r ea   I>
 33:0443 r ea   I>
 32:0444 r 58   I>
 31:0444 r 58   I>
 30:0445 r 4c   I>
 29:0445 r 4c   I>
 28:0446 r 45   I>
 27:0447 r 04    >
 26:0445 r 4c    >
 25:0445 r 4c    >
 24:01eb w 04    >
 23:01ea w 45    >
 22:01e9 w 21    >
 21:fffe r 5d    >
 20:ffff r 04    >
 19:045d r 48    >
 18:045e r ea    >
 17:01e8 w 04    >
 16:045e r ea    >
 15:045f r ea    >
 14:045f r ea    >
 13:0460 r 68    >
 12:0460 r 68    >
 11:0461 r 40    >
 10:01e7 r ea    >
  9:01e8 r 04    >
  8:0461 r 40    >
  7:0462 r 00    >
  6:01e8 r 04    >
  5:01e9 r 21    >
  4:01ea r 45    >
  3:01eb r 04    >
  2:0445 r 4c    >
  1:0446 r 45    >
  0:0447 r 04    >

Explanation (hover to show)

After the reset, the first instruction is a JuMP, so I can easily modify the code without the need to change the start address. After that the IRQ vector gets set up, until "IRQ 9" is entered.
35-30: processing OpCodes NOP, NOP, and CLI (CLear Interrupt disable)
29-27: processing endless loop JuMP, and wait for interrupt to trigger
interrupt is triggered
26-25: two dummy reads: interrupt is triggered while fetching OpCode
24-23: write high byte and low byte of return address to the stack
22: write processor status to stack
21-20: read interrupt vector
19-9: write to and read from stack (like previous example)
8: fetch RTI (ReTurn from Interrupt) OpCode
7: dummy argument read
6: dummy to adjust stack pointer
5: read processor status from stack
4-3: read low byte and high byte of return address from stack
2-0: process endless loop interrupt at 28-26
It is noteworthy, that return address is not "minus one" as in the JSR

Lesson 7: interrput via BRK OpCode

This runs on all CPUs: 65C02, 6502 and 65816. No need to powercycle.

Commands to enter:

: FFFC 0C 04
reset 5
s 54

Output:

 37:0448 r a9    >
 36:0449 r 5d    >
 35:044a r 8d    >
 34:044b r fe    >
 33:044c r ff    >
 32:fffe w 5d    >
 31:044d r a9    >
 30:044e r 04    >
 29:044f r 8d    >
 28:0450 r ff    >
 27:0451 r ff    >
 26:ffff w 04    >
 25:0452 r 00    >
 24:0453 r ea    >
 23:01ee w 04    >
 22:01ed w 54    >
 21:01ec w 35    >
 20:fffe r 5d    >
 19:ffff r 04    >
 18:045d r 48    >
 17:045e r ea    >
 16:01eb w 04    >
 15:045e r ea    >
 14:045f r ea    >
 13:045f r ea    >
 12:0460 r 68    >
 11:0460 r 68    >
 10:0461 r 40    >
  9:01ea r ea    >
  8:01eb r 04    >
  7:0461 r 40    >
  6:0462 r 00    >
  5:01eb r 04    >
  4:01ec r 35    >
  3:01ed r 54    >
  2:01ee r 04    >
  1:0436 r ea    >
  0:0437 r ea    >

Explanation (hover to show)

After the reset, the first instruction is a JuMP, so I can easily modify the code without the need to change the start address. After that the IRQ vector gets set up, and the BRK OpCode is processed.
37-26: set up IRQ vector which is also used for the software interrupt using BRK (BReaK)
25: process BRK Opcode
24: dummy argument read
23-22: write high byte and low byte of return address to the stack
  NOTE: the return address is the one after the dummy read, the documentation states that the BRK OpCode uses two bytes
21: write processor status to stack
20-19: read interrupt vector
18-8: write to and read from stack (like previous example)
7: fetch RTI (ReTurn from Interrupt) OpCode
6: dummy argument read
5: dummy to adjust stack pointer
4: read processor status from stack
3-2: read low byte and high byte of return address from stack
1-0: process the following NOP OpCode

The source code for this example is available at https://github.com/SvOlli/sorbus/blob/master/src/65c02/payload_mcp.s.
Mainpage Topicpage Valid CSS Valid HTML 4.01 Transitional