Extending the Gigatron instruction set
Posted: 14 May 2018, 07:26
One of the nice things about having a CPU built from TTL components is that you don't need to consider it a 'given', but can change the architecture to meet your needs. Want another index register, or a second accumulator? Just grab your soldering iron!
Of course adding new features to the architecture will also require you to add new instructions that can use these features. No use for a register that you cannot load, and store or use for generating addresses. Fortunately the original instruction set of the Gigatron is rather sparse, designed mostly for minimizing decoder logic. So at the expense of some extra logic in the instruction decoder-logic it should be possible to reporpose some of the opcodes that now are duplicats. Of course the more ambitous can also opt for completely redesigning the instruction set.
An extra addressing mode?
In my attempts so far to develop software for the Gigatron, I experience having only a single index register of each type (i.e. for low or high address byte) as a major bottleneck. Even if only to use one of the index registers as 'frame pointer', to indicate (quasi-premanently) a 'page' of local variables for a recursive routine.
The original Gigatron has addressing modes [0,D], [0,X], [Y,D], [Y,X] and [Y,X++]. The latter is a rather specialized mode only available with the OUT destination, aimed at generating video. The other modes using X or Y are only available with the A (accumulator) destination, so that indexed loading of X or Y alsways has to go through A. (Which also is a major annoyance, as it requires storing an reloading of the old A content when the purpose was to store it through the indexed mode.) The mode [0,X] is a bit limited, because it always forces the high address byte to the same value 0. So only 256 bytes of the entire memory can be reached through it. To index other memories that way requires the high byte to be in the (already overloaded) Y register.
The obvious solution in the original Gigatron architecture is to store arrays 'vertically', i.e. use Y instead of X for indexing them, so that the instruction's data field D can be used in [Y,D] to indicate the array, and Y the element in it. Downside is that this only works if the array is smaller than 128 bytes, rather than 256. With 32KB RAM Y is really only a 7-bit register!
This could be solved by replacing the mode [0,X] by [D,X], which is an 'almost backward-compatible' extension, as [0,X] could still be done by specifying D=0 in the opcode. (Only in the rare case that D is used as source for immediate data at the same time, as in STA D, [0,X] this would be imposible.) This enhancement is easy to achieve in hardware, as the second input of the high-byte address multiplexer (AH) is currently not connected (the choice between 0 and Y being made through the output-enable of the multiplexer), andd can be wired to D. Then some logic in the instruction decoder can be addedd for driving the 'select' and 'enable' inputs of this multiplexer in the newly require way.
An alternative use for this second input of AH is to wire it to X, so that a mode [X,D] can be created. From a programming point of view this would be a more useful enhancement. When arrays are stored vertically, the X registers is only rarely used. (Mostly to access large tables through [Y,X], as only few table can ly in the reach of [0,X]), so making it possible to use X as a 'second Y' greatly increases its usefulness.) With two equivalent index registers it becomes easy to shuttle blocks of data between two tables. And for most of the remaining time X can be used to define a 'stack frame' of 256 bytes, as local storage for the current instance of a recursive routine. Mode [X,D] would then be used to access local variable number D, and [0,D] to access global variable number D. This mode is not upward compatible with any of the existing adddressing modes, though. So extensive modification of the instruction decoder would be needed to fit it in the opcode map, if we don't want to sacrifice any of the other modes.
Of course adding new features to the architecture will also require you to add new instructions that can use these features. No use for a register that you cannot load, and store or use for generating addresses. Fortunately the original instruction set of the Gigatron is rather sparse, designed mostly for minimizing decoder logic. So at the expense of some extra logic in the instruction decoder-logic it should be possible to reporpose some of the opcodes that now are duplicats. Of course the more ambitous can also opt for completely redesigning the instruction set.
An extra addressing mode?
In my attempts so far to develop software for the Gigatron, I experience having only a single index register of each type (i.e. for low or high address byte) as a major bottleneck. Even if only to use one of the index registers as 'frame pointer', to indicate (quasi-premanently) a 'page' of local variables for a recursive routine.
The original Gigatron has addressing modes [0,D], [0,X], [Y,D], [Y,X] and [Y,X++]. The latter is a rather specialized mode only available with the OUT destination, aimed at generating video. The other modes using X or Y are only available with the A (accumulator) destination, so that indexed loading of X or Y alsways has to go through A. (Which also is a major annoyance, as it requires storing an reloading of the old A content when the purpose was to store it through the indexed mode.) The mode [0,X] is a bit limited, because it always forces the high address byte to the same value 0. So only 256 bytes of the entire memory can be reached through it. To index other memories that way requires the high byte to be in the (already overloaded) Y register.
The obvious solution in the original Gigatron architecture is to store arrays 'vertically', i.e. use Y instead of X for indexing them, so that the instruction's data field D can be used in [Y,D] to indicate the array, and Y the element in it. Downside is that this only works if the array is smaller than 128 bytes, rather than 256. With 32KB RAM Y is really only a 7-bit register!
This could be solved by replacing the mode [0,X] by [D,X], which is an 'almost backward-compatible' extension, as [0,X] could still be done by specifying D=0 in the opcode. (Only in the rare case that D is used as source for immediate data at the same time, as in STA D, [0,X] this would be imposible.) This enhancement is easy to achieve in hardware, as the second input of the high-byte address multiplexer (AH) is currently not connected (the choice between 0 and Y being made through the output-enable of the multiplexer), andd can be wired to D. Then some logic in the instruction decoder can be addedd for driving the 'select' and 'enable' inputs of this multiplexer in the newly require way.
An alternative use for this second input of AH is to wire it to X, so that a mode [X,D] can be created. From a programming point of view this would be a more useful enhancement. When arrays are stored vertically, the X registers is only rarely used. (Mostly to access large tables through [Y,X], as only few table can ly in the reach of [0,X]), so making it possible to use X as a 'second Y' greatly increases its usefulness.) With two equivalent index registers it becomes easy to shuttle blocks of data between two tables. And for most of the remaining time X can be used to define a 'stack frame' of 256 bytes, as local storage for the current instance of a recursive routine. Mode [X,D] would then be used to access local variable number D, and [0,D] to access global variable number D. This mode is not upward compatible with any of the existing adddressing modes, though. So extensive modification of the instruction decoder would be needed to fit it in the opcode map, if we don't want to sacrifice any of the other modes.