Micro-instructions... which instructions do we need ? Before the control section can be designed, we need a list of everything that we want to control with a microinstruction.
We start with a short list of pseudo-code that will have to be supported, it tells how the information will flow and what the ALU does:
// Load Instruction Register with next opcode. It would be nice // if it can also be loaded from another source. This micro-instruction must // also specify which microcode page to use for the next opcode. Each microcode // page has room for 256 opcodes of max. 16 microinstructions each. IR <- (PC++) // Instructions with a single operand. // op1 can be LOAD, INC, DEC, SHR dst_reg <- op1 (data_source) // Instructions with two operands. Can use A or T register as first operand. // op2 can be ADD, SUB, ADC, SBC, AND, OR, XOR dst_reg <- op2 (A, data_source) dst_reg <- op2 (T, data_source) // Store instructions. Only A or T can be stored. mem(address) <- A mem(address) <- T
The dst_reg can be A, T, DPH, DPL, PCH. When PCH is written, DPH will be written to PCL
The data_source can be:
- a register (DPH, DPL, PCH, PCL),
- a small constant (CGL)
- a value read from a memory address.
A memory address can be:
- a register stored in memory, addressed by the CGL constant as low byte and a zero as high byte
- a zero page address (for 6502), addressed by the DPL register, with high byte zero
- a full 64k address, provided by DPH and DPL
- the program address, addressed by PCH and PCL. Automatic increment of PCH/PCL after it is used.
The register that is stored in memory sits in a special 64K memory area called SYS. It is addressed by the CGL constant (4 bits). The lower 3 bits specify 8 registers. If the 4th bit is set, it specifies 8 other registers, but in this case there is an extra address bit that is provided by the Z80-exx flipflop. The result is that the upper 8 registers can be swapped for other registers by toggling this flipflop. It implements the alternative register set of the Z80.
The control section has to tell the ALU what it should do:
Two-operand instructions like ADD, SUB, AND, OR, EOR
One-operand instructions like LD, INC, DEC, ASL, LSR, ROL, ROR
But the microinstruction has to specify more:
- which processor flags ( N, Z, C ) to update
- if the internal carry flag (TC, Temporary Carry) must be updated (see below)
- which value to use for the carry-input of the ALU and for the SHR block ( 0, 1, C, TC )
- which condition to use for conditional execution (see below)
The Temporary Carry is a flag that is used for address calculations, in situations where the programmer-visible C flag may not be changed.
The control unit is capable of conditional execution of microinstructions. At each location in the ROM that stores the microinstruction, there are actually two instructions stored. Which of these is executed, is determined by a flag called F. If, for a certain instruction, we do not want it to be conditional, we simply store two identical instructions, so it doesn't matter which one is executed.
This flag F can be modified by the microcode. For example, in a BCS (branch on carry set) instruction, the flag F will first get the same value as the C flag. The following microinstructions will now put the jump-address in the program counter when the F flag is '1'.
Another use is, that the Interrupt-signal can be copied to the F flag at the beginning of the microcode for an instruction. At the end of the microcode sequence, the F flag will then be tested, and if there was an interrupt, the instruction register (IR) will be loaded with the opcode of the instruction that handles the interrupt. (That will probably be an opcode in an other page.)
The F flag can be set to one of the following conditions:
- N flag
- Z flag
- C flag
- TC flag
- databit D0
- databit D7
Using databit D0 or D7 provides a way to do carry handling for shift instructions. D7 is also copied to F to do sign-extension of the offset for a branch (relative jump).
Some special instructions will be required for writing to the video memory, providing fast block-copy instructions, and input/output instructions.
The Z80 has instructions that test, set or reset a bit in a register or memory location. So it will be good if there are some microinstructions to support this. This will be providing a bitmask from a CGL value, and providing RES instructions that reset a bit in the destination byte when the corresponding bit in the bitmask is set.
The provided set of 8 registers and 8 switchable registers might not be enough for some situations. So an extra address bit will be provided that doubles the amount of available registers, but this extra bit can not be used in combination with every microinstruction.
After fiddling around with all the requirements, I found that the number of bits in the microinstruction must be 24.