The inspiration for this project was to design a 16-bit TTL computer loosely based on Steve Wozniak's 16-bit virtual cpu "Sweet-16".
It written in 6502 assembly language to augment the Apple II when performing 16-bit operations. Sweet-16 is well documented here:
Wozniak's Sweet-16 created 16 virtual 16-bit registers within 32 bytes of the 6502 zero page memory.
He implemented a 16-bit virtual machine to manipulate these registers, and handle 16-bit data using a simple instruction set.
The instructions exist as bytecodes which could be interwoven within 6502 assembly language.
The instruction set was not only simple but elegant - and trivial to remember the assembly codes. This got me thinking whether it might be a suitable candidate for a real 16-bit cpu - implemented in TTL hardware.
One major restriction of Sweet-16 compared to other register machines, is that register R0 takes the role of the accumulator AC, and almost all operations involve the accumulator and one other register. It is not possible to do register to register operations - except through the accumulator. This restriction reduces the complexity of the ISA as there is no need for source and destination bit-fields - because the accumulator is usually always the destination. This reduction in complexity is also reflected in the hardware - because there is no need to include hardware to select source and destination registers, or to allow the contents of one register to be moved to another.
This overall simplification gives me a greater confidence that I can actually design and build such a machine - and more to the point implement it in a reasonable number of TTL ICs. I have set a limit of 80 to 100 ICs and this should result in a manageable and more modest design both in hardware and cost.
The first task was to analyse the Sweet-16 instruction set and extract the parts that could be useful to a 16-bit TTL computer.
Wozniak's Sweet-16 Instruction set is summarised in the following table:
Register OPS- 1n SET Rn Constant (Set) 2n LD Rn (Load) 3n ST Rn (Store) 4n LD @Rn (Load Indirect) 5n ST @Rn (Store Indirect) 6n LDD @Rn (Load Double Indirect) 7n STD @Rn (Store Double Indirect) 8n POP @Rn (Pop Indirect) 9n STP @Rn (Store POP Indirect) An ADD Rn (Add) Bn SUB Rn (Sub) Cn POPD @Rn (Pop Double Indirect) Dn CPR Rn (Compare) En INR Rn (Increment) Fn DCR Rn (Decrement) Non-register OPS- 00 RTN (Return to 6502 mode) 01 BR ea (Branch always) 02 BNC ea (Branch if No Carry) 03 BC ea (Branch if Carry) 04 BP ea (Branch if Plus) 05 BM ea (Branch if Minus) 06 BZ ea (Branch if Zero) 07 BNZ ea (Branch if NonZero) 08 BM1 ea (Branch if Minus 1) 09 BNM1 ea (Branch if Not Minus 1) 0A BK (Break) 0B RS (Return from Subroutine) 0C BS ea (Branch to Subroutine) 0D (Unassigned) 0E (Unassigned) 0F (Unassigned)
Sweet-16 forms a reasonable starting point for an ISA, but remember that it was intended for a 16-bit virtual machine running on 8-bit hardware with byte-wide memory.
As I will be using 16-bit wide memory, some of the instructions slots are redundant, and these can be replaced with operations which better match the capabilities of the ALU - for example the inclusion of AND, OR and XOR instructions. I also wish to include instructions that correctly PUSH and POP the accumulator incrementing or decrementing the register that is acting as the stack-pointer.
16-Bit Instruction Word Width
The other major deviation from Woz's bytecode implementation, is that the Instruction Register width is now 16-bits.
I intend to use the upper byte very much as its used in Sweet-16 with 4 bits to define the operation and 4 bits to define the register.
I believe that this makes remembering the assembly code a trivial matter - and I am all for making assembly code more human readable.
This then leaves the lower byte of the instruction as a "payload" byte. This might be used as an 8-bit literal, a small constant, an offset to modify a register or a means of addressing a zero page memory address.
It is the use of this payload byte, which I believe will give the instruction set its flexibility. It will open-up additional addressing modes that were not part of the original Sweet-16 idea.
Zero Page addressing became popular with the advent of the minicomputer in the mid-1960s and the idea was continued with the early microprocessors such as the 6502. The memory locations within the zero page are accessible directly from the address bits encoded into the lower bits of the instruction word, within the one instruction cycle. This meant much faster access - and the zero page was heavily used for holding frequently used variables. Having a rapid access to the zero page locations meant that they were almost treated as pseudo-registers, making up for the lack of real registers in some architectures.
It is intended that Suite-16 will have both a collection of general purpose registers, and a zero page addressing mode to allow for the greatest flexibility from the least hardware.
Addressing memory as 16-bit words may not be the most efficient use of memory - especially where byte, ASCII and text operations are concerned. This will be a limitation of the design, but allowing a simplification to the hardware.
I am planning the means to provide a byte-swap mechanism in hardware - this may improve the flexibility for byte operations.
The non-register operations in Sweet-16 are mainly concerned with program flow and branching. I intend to keep this arrangement - particularly for the first eight of the 0x instructions, 00 to 07. These will be the conditional branch instructions, and can be decoded from the three lower bits. As my ALU is based on that used in the Gigatron TTL computer - the conditional branch mechanism will be virtually identical.
Short branches of up to +/-128 locations of the current PC can be performed by modifying the PC with the signed 8-bit value included in the payload byte. This is fairly standard practice on a number of common processors.
Long branches or calls will pick up the full 16-bit destination address from the next full 16-bit instruction. PC = (PC+1)
This leaves instructions 08 to 0F unassigned and I currently have a plan to use those to operate on the accumulator, such as shift operations, clear and complement accumulator, and a means of handling Input and Output. Other operations such as loading commonly used short constants - such as 0, 1, 2, 4, 8, and -1 (FFFF) will be coded here. These operations are inspired by the OPR instructions in the PDP-8 and the constant generator in the MSP430.
The non-register 0x operations also have the 8-bit payload byte attached to them. This could be also be used for zero page addressing or possibly allowing up to 256 I/O ports communicate with the accumulator.