BruceMcF Posted July 8, 2020 Share Posted July 8, 2020 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 2 Quote Link to comment Share on other sites More sharing options...
rje Posted August 5, 2020 Share Posted August 5, 2020 (edited) Ed Minchau apparently is working on a set of 16 bit "kernal" ops... I directed him to you on the Facebook page. Edited August 5, 2020 by rje 1 Quote Link to comment Share on other sites More sharing options...
Ed Minchau Posted August 5, 2020 Share Posted August 5, 2020 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. 2 Quote Link to comment Share on other sites More sharing options...
BruceMcF Posted August 15, 2020 Author Share Posted August 15, 2020 (edited) 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 August 15, 2020 by BruceMcF 2 Quote Link to comment Share on other sites More sharing options...
rje Posted August 18, 2020 Share Posted August 18, 2020 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. Quote Link to comment Share on other sites More sharing options...
BruceMcF Posted August 18, 2020 Author Share Posted August 18, 2020 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. 1 1 Quote Link to comment Share on other sites More sharing options...
BruceMcF Posted August 18, 2020 Author Share Posted August 18, 2020 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 Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 Bruce, I'm going to check out your repo. I just spent an evening porting in SWEET16 to the cc65 assembler, but I haven't tested it out. I juggled the memory load address so that it loads at $0443 -- that makes sure the last 250 bytes begin right on $0500. For your amusement. https://github.com/bobbyjim/x16-sweet16 Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 Wow, I just read your repo README, and I'm impressed. Totally going to check out your implementation. Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 SweetCX16.asm line 72 should be $0400, not $04000, yes? Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 (edited) 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 January 4 by rje Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 (edited) 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? Edited January 4 by rje 1 Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 (edited) But something goes wrong, and I don't know what it is Edited January 4 by rje 1 Quote Link to comment Share on other sites More sharing options...
BruceMcF Posted January 4 Author Share Posted January 4 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. 1 Quote Link to comment Share on other sites More sharing options...
rje Posted January 4 Share Posted January 4 And I am woefully inadequate at testing ML. Hopefully working on SweeterX16 will improve my meager skills there. 1 Quote Link to comment Share on other sites More sharing options...
rje Posted January 7 Share Posted January 7 I see exactly where I went wrong. The start address should be loaded into the accumulator, shouldn't it? Duh! My brain. Quote Link to comment Share on other sites More sharing options...
rje Posted January 7 Share Posted January 7 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? Quote Link to comment Share on other sites More sharing options...
Ed Minchau Posted January 8 Share Posted January 8 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. 1 Quote Link to comment Share on other sites More sharing options...
rje Posted January 9 Share Posted January 9 (edited) 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 January 9 by rje 1 Quote Link to comment Share on other sites More sharing options...
Ed Minchau Posted January 9 Share Posted January 9 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. Quote Link to comment Share on other sites More sharing options...
BruceMcF Posted January 9 Author Share Posted January 9 (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 January 9 by BruceMcF 1 Quote Link to comment Share on other sites More sharing options...
rje Posted January 10 Share Posted January 10 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. Quote Link to comment Share on other sites More sharing options...
Ed Minchau Posted January 10 Share Posted January 10 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. 1 Quote Link to comment Share on other sites More sharing options...
rje Posted January 10 Share Posted January 10 (edited) 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 January 10 by rje Quote Link to comment Share on other sites More sharing options...
BruceMcF Posted January 10 Author Share Posted January 10 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. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.