With my new rudimentary assembler, I wrote a series of test routines for the instructions used in CPU. This is a great help for the debugging the simulation in systematic way, and using them, to date, I tested all instruction types except Jumps and Miscellaneous.
During the testing several wiring bugs were found and fixed.
As I started to test the Jumps, I found that I thought out them in an erroneous way.
The way I designed the microinstruction sequence, the jump address is being loaded from memory, which is not how it should work:
-
Old (wrong) Jump instruction sequence:
0 Fetch1 // load IR <-- Mem:PC; PC <-- PC+2
0' (Fetch2) // load MDB <-- Mem:PC; PC <-- PC+2
1 Set 2w flag
2 Load MAB <-- MP+offset // offset may be GPR or MDB
3 Load PCH <-- Mem:MAB; load MAB <-- MAB+2
3* Load PCL <-- Mem:MAB; load MAB <-- MAB+2
This sequence is loading direct address for jump from somewhere in memory.
How should jumps work:
The way jumps should work is by loading the address from some Memory Pointer pair, with possible offset, into PC pair. This can be readily done using Address Arithmetic instruction for unconditional jumps. But for conditional jumps, there need to be a special kind of instruction anyway, one that encodes condition. When using the PC as base address, such jumps facilitate position independence of the piece of code.
So, the jump instructions have quite a lot in common with Address Arithmetic instructions while also having some resemblance to Indirect Memory Accesses, but not almost identical to the latter, as I thought earlier.
If there is a need to load direct jump address from memory (i.e. in case of returning from subroutine), it can be done with 2-word load via address pointer into the PCH and PCL registers.
-
Here is revised sequence for regular jumps:
0 Fetch1 // load IR <-- Mem:PC; PC <-- PC+2
0' (Fetch2) // load MDB <-- Mem:PC; PC <-- PC+2
1 Load PC <-- MP+offset // offset may be GPR or MDB. The offset is signed value.
-
Sequence for Jump to Subroutine:
This is a jump combined together with storing of current PC value to memory, at address pointed by Stack Pointer (with some offset).
The store part has the same microinstruction sequence as regular indirect store with pre-increment, only difference is that it is hardwired to store the PCH/PCL pair, and pre-increment is always -4. The base pointer can be any of the four memory pointers, but convention is to use the second one (PC). The following jump part is the regular unconditional jump. This combination makes possible to store the address which when loaded into PC again allows the program readily proceed with execution without further modification of PC value.
-
mnemonic for Jump to Subroutine instr.
JSR (SP) [offset]
The offset is distance in bytes from current PC to start of subroutine, it is used in later, "jump" part of sequence.
-
0 Fetch1 // load IR <-- Mem:PC; PC <-- PC+2
0' (Fetch2) // load MDB <-- Mem:PC; PC <-- PC+2
1 Set 2w flag
2 Load MAB <-- SP-4, Load SP <-- SP-4 // most common MP will be SP
3 Store Mem:MAB <-- PCH; MAB <-- MAB+2
3* Store Mem:MAB <-- PCL; MAB <-- MAB+2
4 Load PC <-- PC+offset // offset may be GPR or MDB. The offset is signed value.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.