3 ms·
I have written an emulation for an old microcoded machine. Although the straight-forward implementation was a multiple of times faster than the original machin
by tasty_freeze 8y ago
I have written an emulation for an old microcoded machine. Although the straight-forward implementation was a multiple of times faster than the original machine, I couldn't resist going for a little more performance.
The microinstruction is 23 bits wide (plus one for parity). Rather than doing a lot of masking, shifting, and testing to extract fields (some fields are non-contiguous even), I instead use 64b per microword.
bits [23:0] -- original microinstruction
bits [31:24] -- 8b op-dependent predecode value
bits [39:32] -- 8b interpreter dispatch index
bits [47:40] -- 8b op-dependent predecode value
bits [63:48] -- 16b op-dependent predecode value
There are a few oddball instructions which could use more than the 8b and 16b predecode fields, and instead do the old shift and mask on the raw microword to figure out what is needed.
Overall, it nearly doubled my performance.
- bogomipz 8y ago>"The microinstruction is 23 bits wide (plus one for parity)." I'm curious why does the microinstruction need a parity bit? What happens if the parity is wrong, a machine check exception? >"bits [23:0] -- original microinstruction bits [31:24] -- 8b op-dependent predecode value bits [39:32]" What do the pre-decode bits do exactly? Which microcoded machine was this?
- tasty_freeze 8y agobogomipz -- sorry, I didn't see you replied to this. The machine traps to a parity error handler (one for microcode RAM, and a different one for data ram) and prints out a message indicating the error code and the address being read when it was detected. There are a number of microinstruction formats, and fields aren't always contiguous. Making up an example, say the instruction is "ADD R1,#imm8" to add an 8b immediate to the R1 register. But the 8b immediate value is stored in bits [14:10] and [4:2] of the microword. The straight-forward way would be to write "uint8_t imm = ((instr >> 7) & 0xF8) | ((instr >> 2) & 0x07;" Instead, when the writable control store is written, that quantity is decoded and stored in an 8b aligned predecode field, so getting the value is just "uint8_t imm = instr_struct.imm8;" The machine is the Wang 2200. There were two architectures: the first used a 20b word in ROM, the second used a writable control store so the BASIC could have bug and feature updates by mailing out floppies.