Jump to content

SweetCX16


Recommended Posts

Just a note that my open source implementation of the venerable Sweet16 VM by Woz for the AppleII has a SweetCX16.asm version oriented to the GoldenRAM at $0400-$07FF.

All of my testing was of the C64 version assembled to the C64 $C000-$CFFF Golden Ram location, but if anyone wants to assemble it and run it in the CX16 emulator, I'd welcome feedback ... and bug reports, of course, in case my testing didn't cover as many edge cases as it should have done.

https://github.com/BruceMcF/Sweeter16

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...

Well, what I've come up with is 18 subroutines that handle 16 bit operations much like a Kernal call.  I have set it up so that any two consecutive bytes in zero page can be a 16 bit register.  So, for instance, to add the 16 bit value stored in 3C,3D to the 16 bit value stored in 1A,1B, the syntax would be:

LDX# 3C

LDY# 1A

CLC

JSR ADXY

This adds the values and returns the low byte in X and high byte in Y, and affects the Z,C,N, and V flags the same way that ADC does.

One can also use a sort of immediate mode. For instance, subtracting the hex value $4C1E from the 16 bit value stored in zero page addresses 4E,4F:

LDA# 4E

LDX# 1E

LDY# 4C

SEC

JSRA SBA#

Results stored in X= lo byte Y=high byte, and the Z,C,N, and V flags are affected the same way as with SBC.

 

These subroutines are stored in Golden RAM as part of my upcoming update to my CX16 assembly language editor, but if people want I can post it here too, it's only 350 bytes.

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...

Yes, Sweet 16 was more intended to be used as a sequence of Sweet 16 operations for a set of things involving 16bit values. There's no particular reason they couldn't both be provided .... the 2page version can easily be assembled to any two available pages in Low RAM, including the top half of Golden RAM.

My focus has rather been on getting the first of the series of Forth's up an running ... this version has got a working Interpreter for calculations and just today I got the defining words to work, but it's still buggy, so maybe next week unless I get really lucky and can post the pre-alpha early this week.

Edited by BruceMcF
  • Like 2
Link to comment
Share on other sites

On 8/15/2020 at 5:40 PM, BruceMcF said:

Yes, Sweet 16 was more intended to be used as a sequence of Sweet 16 operations for a set of things involving 16bit values. There's no particular reason they couldn't both be provided .... the 2page version can easily be assembled to any two available pages in Low RAM, including the top half of Golden RAM.

My focus has rather been on getting the first of the series of Forth's up an running ... this version has got a working Interpreter for calculations and just today I got the defining words to work, but it's still buggy, so maybe next week unless I get really lucky and can post the pre-alpha early this week.

Ah Forth!  So please, can someone explain to me why I have such a resistance to the Forth language?  It seems to tick a lot of the boxes for a great 8-bit language.

Link to comment
Share on other sites

A lot has to do with getting a good introduction to the language. A lot of Forth implementers are better at talking to hardware than talking to people.

RPN takes getting used to, for people used to languages that say "do this with these things and this option", a language that just says " do this, now do this, now do this, ..." over and over again takes getting used to

Also, a lot of Forth source is badly laid out, trying to mimic the layout of a C family language instead of respecting what the language is actually doing.

Since my Forth is aligned with Standard Forth, I will include either a link to or PDF of the ANS Version of Starting Forth for people just getting started.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

One cute trick for 16 bit zeropage ops with a dedicated 16bit accumulator in (either zp or elsewhere) is (in Golden RAM)

DO16: STA OPLO : STA OPHI

REPEAT16: LDA D16ACC

OPLO: AND $00,X : STA D16ACC : LDA D16ACC+1

OPHI: AND $01,X : STA D16ACC : RTS

Where you put the address of the low byte in X and the zeropage X-indexed opcode in A and call DO16 ... does AND/ORA/EOR/LDA/STA and with proper setting or clearing of carry SBC and ADC. REPEAT16 when you are doing the same operation again. Only need to do a dedicated 16bit compare to get all 8 fundamental two-input ops.

19 bytes with ZP accumulator and routine in Golden RAM, 23 bytes with accumulator in golden RAM as well.

A second version with zp,X as the accumulator and zp

A second version with (zp),Y as the target address and you have quite a lot of flexibility in very little space.

And if a single accumulator feels a little restrictive:

EX16: LDY $00,X : LDA D16ACC : STY 16ACC : STA $00,X : LDY $01,X : LDA D16ACC+1 : STY D16ACC+1 : STA $01,X : RTS

~~~~~~~~~~~~~

16 bit CMP can be done ...

D16TMP: !byte 0

D16CMP: LDA $00,X : SEC : SBC D16ACC : STA D16TMP : LDA$01,X : SBC D16ACC+1 : BNE + : LDA D16TMP : BPL + : LDA #1

+ RTS

But maybe separate Less Than and Equal tests take about the same space:

D16LESS: LDA $00,X : SEC : SBC D16ACC : LDA $01,X : SBC D16ACC+1 : RTS

D16EQ: LDA $00,X : CMP D16ACC : BNE + : LDA $01,X : CMP D16ACC+1

+ RTS

 

 

 

 

 

Link to comment
Share on other sites

  • 1 year later...

My attempt to modify your source for cc65.

Yes, I know I should FORK your repo and push an update to it and do a merge request... blah blah blah.   My brain is reeling from even considering trying this out in the first place.  Excuses excuses.

I've probably broken it too.  I'll load it and try to poke at it (no pun intended) with the debugger and see what I can try to do.

 

 

SweetCX16.s

SWEETCX16.PRG

build

Edited by rje
Link to comment
Share on other sites

Okay I will start with a SET.  It looks like R1 is safe for this, so I can do SET R1, and let's see, let's give it the value $1541.

I'll use your binary, which loads to $4000, and I'll make sure to load in the data before I load the binary too.

And I'll put the "program" in $0700.

I think that would look something like this:

$0700: $11    ; SET R1
$0701: $41
$0702: $15
$0703: $00    ; RTN
$0704: $02    ; 6502 BRK

Then I poke $00 $07 into R15:

$0020: $00
$0021: $07

Then sys $4000.
Then peek $02 and $03 and hope that $41 and $15 are there?

 

 

 

Screen Shot 2022-01-04 at 12.42.01 PM.png

Edited by rje
  • Like 1
Link to comment
Share on other sites

On 1/4/2022 at 12:40 AM, rje said:

SweetCX16.asm line 72 should be $0400, not $04000, yes?

Yes. That looks like a regression. Back then, I was primarily developing in VICE emulating a 65C02 in a C64, so the $CC00 branch saw more testing.

  • Like 1
Link to comment
Share on other sites

So I was looking at the opcode set for SWEET16, and reading the descriptions, and thinking about SUB versus CPR.

SUB does a twos-complement add.  CPR does a binary subtract.  The code in fact overlaps significantly:

***

SUB:    LDY  $0             ;RESULT TO R0
CPR:    SEC                 ;NOTE Y REG = 13*2 FOR CPR
        LDA  R0L
        SBC  R0L,X
        STA  R0L,Y          ;R0-RX TO RY
        LDA  R0H
        SBC  R0H,X
SUB2:   STA  R0H,Y
        TYA                 ;LAST RESULT REG*2
        ADC  $0             ;CARRY TO LSB
        STA  R14H
        RTS

***

 

So my question is this:  maybe I can free up an opcode slot by not having SUB?  Especially if CPR puts its result in R13, and is therefore accessible as a difference value.

Haven't thought it through fully, but it seems that the two values are related enough.  Of course perhaps Woz did this because there wasn't another op that he wanted badly enough to get rid of SUB?

 

Link to comment
Share on other sites

On 1/6/2022 at 7:20 PM, rje said:

So I was looking at the opcode set for SWEET16, and reading the descriptions, and thinking about SUB versus CPR.

SUB does a twos-complement add.  CPR does a binary subtract.  The code in fact overlaps significantly:

***

SUB:    LDY  $0             ;RESULT TO R0
CPR:    SEC                 ;NOTE Y REG = 13*2 FOR CPR
        LDA  R0L
        SBC  R0L,X
        STA  R0L,Y          ;R0-RX TO RY
        LDA  R0H
        SBC  R0H,X
SUB2:   STA  R0H,Y
        TYA                 ;LAST RESULT REG*2
        ADC  $0             ;CARRY TO LSB
        STA  R14H
        RTS

***

 

So my question is this:  maybe I can free up an opcode slot by not having SUB?  Especially if CPR puts its result in R13, and is therefore accessible as a difference value.

Haven't thought it through fully, but it seems that the two values are related enough.  Of course perhaps Woz did this because there wasn't another op that he wanted badly enough to get rid of SUB?

 

No, there's a transcription error there.  SUB: LDX $0

SUB is used if you want to subtract the register pointed to by Y from R0.  CPR can be used to subtract a register pointed to by Y from a register pointed to by X.  One would be using R0 as the minuend often enough that it's worthwhile to keep those two bytes there.

 

  • Like 1
Link to comment
Share on other sites

On 1/8/2022 at 1:24 AM, Ed Minchau said:

No, there's a transcription error there.  SUB: LDX $0

Wait wait, this is an error?  This is the "source" of the source.  It's wrong?

http://www.6502.org/source/interpreters/sweet16.htm#Sweet_Sixteen_Source_sheldon

Ahhh, it IS a transcription error!

The original was LDY #$0.  Wow!

And here's Woz' article in Byte magazine... the source of that page on 6502.org.  The LDY $#0 is on page 152, about halfway down. 

https://archive.org/details/BYTE_Vol_02-11_1977-11_Sweet_16/page/n153/mode/1up

 

This listing has that line correct.  But, I suppose I have to check the remaining lines for errors!

http://www.easy68k.com/paulrsm/6502/SW16RB.TXT

Edited by rje
  • Like 1
Link to comment
Share on other sites

On 1/8/2022 at 6:19 PM, rje said:

Wait wait, this is an error?  This is the "source" of the source.  It's wrong?

http://www.6502.org/source/interpreters/sweet16.htm#Sweet_Sixteen_Source_sheldon

Ahhh, it IS a transcription error!

The original was LDY #$0.  Wow!

And here's Woz' article in Byte magazine... the source of that page on 6502.org.  The LDY $#0 is on page 152, about halfway down. 

https://archive.org/details/BYTE_Vol_02-11_1977-11_Sweet_16/page/n153/mode/1up

 

This listing has that line correct.  But, I suppose I have to check the remaining lines for errors!

http://www.easy68k.com/paulrsm/6502/SW16RB.TXT

Well now I don't know.  I was looking at the Sweet16.s linked on Tuesday.  Guess I'm going to have to look through everything now too.

Link to comment
Share on other sites

Posted (edited)
On 1/6/2022 at 9:20 PM, rje said:

So I was looking at the opcode set for SWEET16, and reading the descriptions, and thinking about SUB versus CPR.

SUB does a twos-complement add.  CPR does a binary subtract.  The code in fact overlaps significantly:

***

SUB:    LDY  $0             ;RESULT TO R0
CPR:    SEC                 ;NOTE Y REG = 13*2 FOR CPR
        LDA  R0L
        SBC  R0L,X
        STA  R0L,Y          ;R0-RX TO RY
        LDA  R0H
        SBC  R0H,X
SUB2:   STA  R0H,Y
        TYA                 ;LAST RESULT REG*2
        ADC  $0             ;CARRY TO LSB
        STA  R14H
        RTS

***

 

So my question is this:  maybe I can free up an opcode slot by not having SUB?  Especially if CPR puts its result in R13, and is therefore accessible as a difference value.

Haven't thought it through fully, but it seems that the two values are related enough.  Of course perhaps Woz did this because there wasn't another op that he wanted badly enough to get rid of SUB?

Because the purpose of Sweet16 is most often to write very compact "setup" type code ... you are not intended to use Sweet16 inside inner loops executed many times, but in one-off startup processes that would take much more space in 6502 binary code but since its only executed once, using Sweet16 doesn't have much runtime impact.

If you are USING the result of the subtraction, you will typically need the result in the accumulator ... even if you want the result somewhere else, you will need it in the accumulator before "putting it somewhere else", so will have to follow, eg, CPR R5 with LD R13, wasting a byte in your Sweet16 code for every subtract operation.

Plus, what other SINGLE "register" operation do you need? There are already three spare non-register ops, and any of those COULD be implemented with an operand that refers to one register ... or even two registers. For instance, you could SWAP two registers with the source register index in the low nybble of the operand byte and the destination register index in the high nybble, or multiply two registers with the 32bit result replacing the operands in a similar way. Or you could have shift left and shift right with the low nybble giving the register and the high nybble giving the number of shifts, from 0 to 15.

Edit: Actually, I may have convinced myself to substitute the extensions I have in the current source WITH those three ... a register swap and binary shift left and right.

Edited by BruceMcF
  • Like 1
Link to comment
Share on other sites

On 1/9/2022 at 12:12 PM, BruceMcF said:

Edit: Actually, I may have convinced myself to substitute the extensions I have in the current source WITH those three ... a register swap and binary shift left and right.

There ya go. 

Link to comment
Share on other sites

On 1/8/2022 at 6:19 PM, rje said:

Wait wait, this is an error?  This is the "source" of the source.  It's wrong?

http://www.6502.org/source/interpreters/sweet16.htm#Sweet_Sixteen_Source_sheldon

Ahhh, it IS a transcription error!

The original was LDY #$0.  Wow!

And here's Woz' article in Byte magazine... the source of that page on 6502.org.  The LDY $#0 is on page 152, about halfway down. 

https://archive.org/details/BYTE_Vol_02-11_1977-11_Sweet_16/page/n153/mode/1up

 

This listing has that line correct.  But, I suppose I have to check the remaining lines for errors!

http://www.easy68k.com/paulrsm/6502/SW16RB.TXT

Yeah, SUB in the SweetCX16.s file is very different from the other three sources listed.  It's using X and Y differently too.  There are significant differences throughout the code, presumably to take advantage of the 65c02 commands like BRA.

  • Like 1
Link to comment
Share on other sites

On 1/10/2022 at 1:45 AM, Ed Minchau said:

Yeah, SUB in the SweetCX16.s file is very different from the other three sources listed.  It's using X and Y differently too.  There are significant differences throughout the code, presumably to take advantage of the 65c02 commands like BRA.

I would expect that too.  Good!

 

Okay, I've visually checked Woz' article with this file http://www.easy68k.com/paulrsm/6502/SW16RB.TXT and they look the same, excepting context such as start address and the added copyright notice to the URL listing. 

Of course I can't guarantee that I didn't miss something.

 

Edited by rje
Link to comment
Share on other sites

On 1/10/2022 at 2:45 AM, Ed Minchau said:

Yeah, SUB in the SweetCX16.s file is very different from the other three sources listed.  It's using X and Y differently too.  There are significant differences throughout the code, presumably to take advantage of the 65c02 commands like BRA.

There ought to be differences throughout ... it is not attempting to be a port of Woz's code, it is attempting to be an open source VM that executes Sweet16 source, and beyond that is explicitly focusing on using a faster approach routine dispatch.

And in part it is explicitly pursuing a different speed / codesize tradeoff than Woz's Sweet16 because I doubt I could pursue Woz's specific goals and do any better than he did.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use