Alright I have it figured out!
It took me a ton of experimentation to get it to work right, and with only 2 threads, ha!
Most of my bugs were just bad memory management. I had to brush up on Z80 endianness and what not.
@tggzzz pretty much summed up the process perfectly.
I created a thread handler that fires off when my external interrupt goes active, this pushes the current thread's registers to its stack, then saves the thread's stack pointer value inside of the thread's data structure in memory. Next it grabs the next thread's data structure, grabs the next thread's stack pointer value, changes the SP to the new thread's SP value, POP's the registers and then RETs. This pushes the new thread's program counter back to the value it was when running previously.
I created a very basic NEW_THREAD routine that helped stage a couple of test routines (routine0 prints 0 to terminal, and routine1 prints 1). It set the areas of memory where the PC's should be to their routine start addresses, then set each routine's SP 16 bytes back in order to account for the POPs from the thread handler.
It's very rough but it is a proof of concept.
Improvements to be made:
- Remove hard coded 2 thread system, move to dynamic system that uses flags on the thread structure to determine status and act from there
- Create routine for closing threads and freeing up their memory
- Create a way for threads to request more or less stack space when first init'd, right now it's a static amount. This would require my routines or "executables" to follow some kind of standard and have headers similar to ELF... and would also increase the complexity of the routines that handle finding each thread's stack. I'd have to end up using linked lists or something
- MAYBE: Allow some threads to have higher priority (I/O limited threads can be checked less often and core services will be ran more etc)
Threading will be integral to my overall design because I want to create a rudimentary GUI desktop in the future, which is pretty much impossible without threading.
Now that I kind of have my head wrapped around how this works I think I'm going to start actually designing my "kernel".
Maybe that discussion would make for another fun thread?