No instruction set is perfect, and early microprocessor design engineers were working against many constraints: die size, transistor count, process limitations, commercial deadlines and the expectations of their sales and marketing department.
The 6502 was no exception, and it was Chuck Peddle’s vision to make a microprocessor targeted at control applications for a tenth of the cost of the nearest competitor.
This strategy would hopefully lead to volume sales to large manufacturing corporations - including automotive, industrial and process control. In 1974 nobody in the IC design and fabrication industry was thinking about the forthcoming microcomputer revolution.
The upshot of this, was that the 6502 and other 8-bit processors of that era were not well equipped for performing 16-bit math - due to a limitation of 16-bit wide registers. The 6502 was further restricted by a stack pointer that was only 8-bits wide.
The exception perhaps was the 8080 and the forthcoming Z80, where some 16-bit support could be obtained by pairing registers together. Hence the BC, DE, HL register pairs and a 16-bit stack pointer SP, and a few, limited 16-bit instructions to support them, such as LXI (load 16-bit immediate), DAD - 16-bit ADD into the HL register pair and 16-bit increment INX and decrement DCX.
In 1977 Wozniak realised the limitations of the 6502 especially when it came to moving strings or other data around memory when writing BASIC for Apple II.
Chuck Peddle’s design strategy was to encourage the use of zero page memory, with it’s faster addressing time, to compensate for the lack of internal registers. Woz realised the importance of zero page RAM and exploited it to full advantage.
His solution was elegant and compact - create a virtual machine, with a wealth of 16-bit registers created in the first 32 bytes of zeropage RAM and a minimum instruction set to support operations on these 16-bit registers.
Thus was born “Sweet-16” a virtual machine with a 16-bit accumulator R0, and 15 general purpose registers R1 to R15. (Registers R12 to R15 were used as internal Stack Pointer, Program counter etc).
Sweet-16 used an 8-bit instruction format to be compatible (and code-dense) with the 8-bit memory.
Woz chose his instruction coding to be trivial, so that the codes were easy to remember, yet achieve maximum flexibility and to compensate for the limitations of the 6502.
There are 3 unassigned instruction slots, which could be utilised to extend the capabilities.
Instructions were roughly divided into those that worked on a specified register, n and the accumulator R0, and those that did not involve register addressing such as branching:
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)
Needless to say, Sweet-16 was compact and efficient. The complete interepreter is coded into about 230 lines of 6502 assemby, occupying about 300 bytes of ROM space.
Sweet-16 ran at approximately one tenth of the speed of native 6502 code, but it vastly simplified the process of programming within a 16-bit environment.
The few instructions were easy to remember and Sweet-16 instructions could be interspersed within 6502 code.
Parameters could be set up in the zero page registers, and then Sweet-16 execution mode begins with a subroutine call to SW16. All 6502 registers are saved at this time, to be restored when a Sweet-16 RTN instruction returns control to the 6502.
Sweet-16 is a historically significant example of the use of a minimal virtual machine, to create a layer of abstraction above the native assembly language.
It is a forerunner of bytecode, where a few 16-bit operations can be coded into 8-bit instructions in memory, and executed using a simple interpreter.
Full details and a listing of Sweet-16 can be found here: