6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue Nov 12, 2024 9:07 am

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Word Double-decrement
PostPosted: Fri Sep 24, 2021 4:59 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
I recently had a need to decrement words (addresses) by two, which is not quite so simple as decrementing them by one. There's an obvious choice between using SUB or using DEC twice, so I coded up both to see which worked better. (Spoiler: SUB won by a mile.) You can look at the full code and test files if you like but here's the summary:

Code:
;   The byte and cycle counts assume zero page addressing. The first cycle
;   column is for the case where the MSB is not decremented, and the second
;   for the case when it is.
;
                            ; byte and cycle counts assume ZP addressing
                            ; first cycle column is for branch taken

decw_sub:   lda val         ;  2b  2c
            sec             ;  1b  2c
            sbc #2          ;  2b  2c
            sta val         ;  2b  3c
            bcs .done       ;  2b  3c  2c
            dec val+1       ;  2b      5c
.done                       ; ────────────
            rts             ;  9b 12c 16c   TOTALS

decw_dec:   lda val         ;  2b  2c
            bne .nz1        ;  2b  3c 2c        { at least one
            dec val+1       ;         5c          of these two
.nz1        dec val         ;  2b  5c             branches must
            bne .nz2        ;  2b  3c 2c        { be taken
            dec val+1       ;         5c
.nz2        dec val         ;  2b  5c
                            ; ───────────
            rts             ; 10b 18c 22c   TOTALS

The test values (input, output) I used are:
Code:
(0xFFFF, 0xFFFD), (0x8001, 0x7FFF), (0x7000, 0x6FFE), (0x0000, 0xFFFE)


Did I miss any test values that could expose a mistake, incorrect cycle counts, tricks for even faster (or smaller) ways of doing this, or anything else?

I also noticed that we don't seem to have anything in the 6502.org Source Code Repository related to incrementing and decrementing. Maybe it's worth linking from there to the Wikidot page (which I find pretty useful). If someone wants to add any of the above to either, I'm fine with that.

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 24, 2021 6:17 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
LDA val takes three cycles, not two. Your decw_sub is 11 bytes, not nine.

Your decw_dec is 14 bytes, not 10. Here's an untested variation, but I still see no significant reason to choose it over SBC:
Code:
decw_dec:   ldy val         ;  2b  3c
            cpy #2          ;  2b  2c
            dey             ;  1b  2c
            dey             ;  1b  2c
            bcs .nz2        ;  2b  3c  2c
            dec val+1       ;  2b      5c
.nz2:       sty val         ;  2b  3c  3c
                            ; ───────────
            rts             ; 12b 15c 19c   TOTALS
Maybe if you were in decimal mode or wanted to preserve the V flag?

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Fri Sep 24, 2021 9:11 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
barrym95838 wrote:
LDA val takes three cycles, not two.

Ah, of course it does. I'd put a stupid error into the opcode reference I was using. That led me to fix two things, so thanks.

Quote:
Your decw_sub is 11 bytes, not nine.... Your decw_dec is 14 bytes, not 10.

Yeah. Not sure how I decided I could just leave out the byte counts of a couple of instructions.

Quote:
Here's an untested variation....

It's tested now (and works). I dropped it into my code as `decw_dey`. It's a nice optimization, and a good reminder that it's worth remembering registers other than A can also work for small additions and subtractions.

Quote:
Maybe if you were in decimal mode or wanted to preserve the V flag?

Yup. Or if you might be in decimal mode, or you just find it helps a broader optimization to preserve A rather than Y (or X) at that point.

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Thu Nov 11, 2021 6:03 am 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1949
Location: Sacramento, CA, USA
cjs wrote:
Maybe it's worth linking from there to the Wikidot page (which I find pretty useful). If someone wants to add any of the above to either, I'm fine with that.

Done. Well, not exactly. I added our snippets to the wikidot page, where I have editing authority.

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: