Sweet 16 (The 6502 Dream Machine) Ported to the VIC-20

  /     /   Assembly     Commodore     Programming     Retro     VIC-20    

Sweet 16 was created by Steve Wozniak to reduce code size and make it easier to handle 16-bit pointers and arithmetic for his Apple Integer BASIC. He wrote it around 1977 and referred to it in an article as The 6502 Dream Machine. I have ported this to the Commodore VIC-20 so that we can play with it on the Vic.

Outline of Sweet 16

Sweet 16 is described as a pseudo-machine interpreter, which is probably a better description than a virtual machine because it shares native memory for storage and is designed to switch back and forth between itself and native 6502 code. The pseudo-machine has sixteen 16-bit registers with five of them having a defined function.

  • R0   Accumulator
  • R12 Subroutine return stack pointer
  • R13 Comparison instruction results
  • R14 Status register
  • R15 Program counter

To execute Sweet 16 code you JSR to an address within it which will save the registers and status then execute the following bytes in memory as Sweet 16 code until it reaches the Sweet 16 RTN instruction which will restore the registers and status and continue executing the native 6502 that follows it.

The code is pretty compact and only takes around 300 bytes, it could have been made a little more compact and faster but it had to reside in ROM and therefore couldn't use self-modifying code.

Instruction Set

Register Operations Nonregister Operations
00RTNReturn to 6502 mode
1nSET RnConstant set 01BR eaBranch always
2nLD RnLoad 02BNC eaBranch if No Carry
3nST RnStore 03BC eaBranch if Carry
4nLD @RnLoad indirect 04BP eaBranch if Plus
5nST @RnStore indirect 05BM eaBranch if Minus
6nLDD @RnLoad double indirect 06BZ eaBranch if Zero
7nSTD @RnStore double indirect 07BNZ eaBranch if NonZero
8nPOP @RnPop indirect 08BM1 eaBranch if Minus 1
9nSTP @RnStore Pop indirect 09BNM1 eaBranch if Not Minus 1
AnADD RnAdd 0ABKBreak
BnSUB RnSubtract 0BRSReturn from Subroutine
CnPOPD @RnPop double indirect 0CBS eaBranch to Subroutine
DnCPR RnCompare 0DUnassigned
EnINR RnIncrement 0EUnassigned
FnDCR RnDecrement 0FUnassigned

There is an implicit Accumulator argument for most of the Register Operations and the Branch instructions all use relative addressing. The instruction set is well thought out with the ability to use 8-bit bytes or 16-bit words and helpfully instructions like the indirect instructions increment/decrement the register being used before/after use as appropriate. For a full description of the instructions take a look at the Byte Magazine Volume 02 Number 11 - November 1977 article.

Porting Sweet 16 to the Commodore VIC-20

The original Sweet 16 source code has been published a number of times including in Byte Magazine Volume 02 Number 11 - November 1977. In this article Steve Wozniak encourages users to modify Sweet 16 and even to port it to other processors, so hopefully he won't mind its being ported to the Vic. However, despite this and the fact that the code is widely available, it is still probably under copyright and therefore the port relies on patching the original source code rather than supplying a complete version.

I can't claim too much credit for porting it as beyond deciding on a suitable location for the registers in the zero page and aligning the code so that part of it fits into a single page, the majority of the work was converting the code to assemble using the XA assembler. Sweet16 needs 32 bytes in zero page for the registers, so I chose locations $2B-$4A. This will stop Basic programs from working, unless you save and restore those locations when needed, but does allow the Basic SYS command to still execute machine code.

I have uploaded the patch and test program to github: sweet16_vic20. Full instructions for patching, assembling and running the code are provided in the README.

Example Code

Below are a few examples to show what Sweet 16 looks like in use.

Memory Region Copy

Copying a string to a new location with Sweet 16.

DST         = $02BC                   ; Destination for memory copy
LEN         = $0005                   ; Length of memory to copy

copyHello   jsr  SW16                 ; Execute following Sweet 16 code
            .byt $11, <hello, >hello  ; SET  R1   Source Address
            .byt $12, <DST, >DST      ; SET  R2   Destination Address
            .byt $13, <LEN, >LEN      ; SET  R3   Length
            .byt $41                  ; LD   @R1
            .byt $52                  ; ST   @R2
            .byt $F3                  ; DCR  R3
            .byt $07, $FB             ; BNZ  -4
            .byt $00                  ; RTN

hello       .asc "HELLO"              ; String to copy

16-bit Multiplication

Using Sweet 16 to calculate 255*100.

X           = 255                     ; The values to multiply
Y           = 100

mulNums     jsr  SW16                 ; Execute following Sweet 16 code
            .byt $10 : .word 0000     ; SET  R0   sum
            .byt $11 : .word X        ; SET  R1   x
            .byt $12 : .word Y        ; SET  R2   y
            .byt $13 : .word result   ; SET  R3   result
            .byt $F2                  ; DCR  R2
            .byt $05, $03             ; BM 3
            .byt $A1                  ; ADD  R1
            .byt $01, $FA             ; BR   -5
            .byt $73                  ; STD  @R3
            .byt $00                  ; RTN

result      .word $0000               ; The result of the multiplication

Two's Complement

Getting the two's complement of a number by using Sweet 16 to load the value, then returning to 6502 code to call a routine to one's complement the value, then finally going back to Sweet 16 to add one to the value.

A           = $0010                   ; The value to two's complement

negate      jsr  SW16                 ; Execute following Sweet 16 code
            .byt $11 : .word A        ; SET  R1   a
            .byt $13 : .word result   ; SET  R3   result
            .byt $21                  ; LD   R1
            .byt $73                  ; STD  @R3
            .byt $00                  ; RTN
            jsr  notRes               ; One's complement RESULT
            jsr  SW16                 ; Continue executing Sweet 16 code
            .byt $C3                  ; POPD @R3
            .byt $E0                  ; INR  R0
            .byt $73                  ; STD  @R3
            .byt $00                  ; RTN

            ; One's complement RESULT
notRes      lda  result
            eor  #$FF
            sta  result
            lda  result+1
            eor  #$FF
            sta  result+1

result      .word $0000               ; The result of the operation

Video Demonstrating Sweet 16

You can see Sweet 16 running on the Vic in the following video:

Creative Commons License
Sweet 16 (The 6502 Dream Machine) Ported to the VIC-20 by Lawrence Woodman is licensed under a Creative Commons Attribution 4.0 International License.

Share This Post


Sign up to get new articles straight to your inbox.

Delivered by FeedBurner

Related Articles

Position Independent Code (6502) on the Commodore VIC-20

If we are writing 6502 machine code and want to to create a routine or program that can be placed in any location then we have to create Position Independent Code (PIC) or make the code relocatable. H...   Read More

Adding Basic Stubs to Assembly Language on the Commodore VIC-20

To make machine language programs more friendly it's nice to add a Basic stub which contains a line with a SYS statement to start the code. This is easy to do on the VIC-20 and the process gives you a...   Read More

Hand Assembling to Machine Code on the Commodore VIC-20

I quite enjoy designing machine language routines on paper and then hand assembling them. For many people this would have been their only option until they got a more advanced machine language monitor...   Read More

Creating a TTY Simulator in Assembly Language on the VIC-20

The Vicmon machine language cartridge is an excellent tool for exploring the Vic-20. This article and its associated video will show you how to use it to create a simple program that will change the n...   Read More

Beginning Assembly Programming on the Commodore VIC-20

The Commodore Vic-20 is a great machine to learn an assembly language on. It was released in 1981 and was the first computer to sell one million units, which contributes to its popularity today. The ...   Read More