Microcode assembler work

I’ve spent a bit of time over the past couple of months re-implementing the microcode assembler from scratch. The original microcode assembler was thrown together to save me from typing 64 ones and zeroes for every word of microcode (which I was doing until I wrote the assembler), but wasn’t very extensible and over the years had become a mess, was hard to work on, and I was avoiding ever touching it because it seemed to break every time I did. I decided re-implementing it was probably a good idea.

The new microcode assembler acts basically the same, takes the same input files and, eventually, will generate the same output files, but should be easier to maintain and extend. I’ve been trying to avoid the second system effect by keeping scope to just the existing functionality (and removing a couple functions that didn’t end up being as useful as I thought), and once it’s done I’ll look at adding new functionality.

One thing I want to add (and one of the reasons for the re-write) was some optimization, in a lot of cases the first word of an instruction is just a next_addr to the actual routine (e.g. ldi8.al just jumps to ldi8.?l), with the original entry point just serving to fill IR with the correct register information. There’s no reason that the instruction can’t start doing work in the first word/cycle other than because it would make the code much harder to read and duplicate a lot of code, so I want to add an optimization module to the microcode compiler which will take care of shuffling things around to save cycles while not having to do it manually and make code harder to read.

The assembler is mostly working at this point, but the next_addr functionality isn’t quite working right, and while troubleshooting this I think the way I’ve implemented it is not ideal, so I’m re-implementing that and then this mini-project should be done. After that I’ll probably finish the few instructions I have left to implement, then finish interrupt/trap support.