Word Double-decrement

Building your first 6502-based project? We'll help you get started here.
Post Reply
User avatar
cjs
Posts: 759
Joined: 01 Dec 2018
Location: Tokyo, Japan
Contact:

Word Double-decrement

Post by cjs »

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: Select all

;   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: Select all

(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
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Word Double-decrement

Post by barrym95838 »

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: Select all

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)
User avatar
cjs
Posts: 759
Joined: 01 Dec 2018
Location: Tokyo, Japan
Contact:

Re: Word Double-decrement

Post by cjs »

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
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: Word Double-decrement

Post by barrym95838 »

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)
Post Reply