Close

Dealing with Jumps and Interrupts

A project log for ECM-16/TTL homebrew computer

16 bit Computer made from ttl logic chips

pavelPavel 12/29/2021 at 15:400 Comments

During more rigorous contemplation of interrupt mechanisms, I found out that there needs some adjustments to be done to the Register Transfer Scheme.

Here is the updated one:

The new things added are 32-bit Interrupt Vector register, and a couple of associated selectors.

I think I finally got it about how to implement interrupts. It was quite perplexing, and I thought it should have to be some complex sequence, and I also regarded it as not a pressing issue and haven't given them much thought. Now, really thinking about interrupts, I came up with seemingly good solution -- just use the sequence for Jump to Subroutine, just with some tweaks. Below is more in-depth discussion:

First, the Jump sequences:

Regular Jumps are 2-word loads to PC via MP (+ offset).

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

The regular Jumps are Unconditional Jump, and 8 jumps on different conditions:

jump on Carry, Overflow, Negative, Zero, Not Carry, Not Overflow, Not Negative, and Not Zero.

The Jump to Subroutine is in Jump family, but it has additional steps in sequence:

it is a 2-word store of PC via MP -4 (stack pointer), followed by 2-word load to PC via PC+offset.

Offset source, code and Stack pointer are the same as corresponding parts of regular memory transfer via MP instructions

JSR instr 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-4 // most common MP will be SP
3    Store Mem:MAB <-- PCH;  MAB <-- MAB+2
3*   Store Mem:MAB <-- PCL;   MAB <-- MAB+2
4    Set 2w flag
5    Load MAB <-- PC+offset // offset may be GPR or MDB
6    Load PCH <-- Mem:MAB;   MAB <-- MAB+2
6*   Load PCL <-- Mem:MAB;   MAB <-- MAB+2

In this way the jump (Program Counter load) is preceded by storing the PC value to current stack tip, thus making it possible to return from the subroutine by loading stored PC value from Stack to PC.

Enter Interrupt -- this instruction I thought would be something very special, and quite complex, but, as it looks like right now, turned out not that difficult. It was possible to implement it with special Fetch cycle, which updates the Instruction Register with hardcoded value of one type of JSR, without PC update, and a signal which substitutes address from Memory Pointer with address from Interrupt Vector register.
It can be triggered explicitly, in code (software interrupt), or via hardware. In the last case the interrupt sequence is followed after the last step of currently executing instruction.

The hardcoded JSR used for entering interrupt uses SP_h/SP_l pair of Memory Pointer registers forming the Stack Pointer. In this way, this single instruction enforces the convention of using this memory pointer as the default Stack Pointer.

Discussions