Page 2 of 2

Re: calculating 65c02 instruction size

Posted: Sun Dec 03, 2023 7:21 pm
by tius
Osi wrote:
Hi tius,
to calculate the instruction length for a 6502 CPU, here the code I'm using in one of my programs:
...
Thank you Thomas! I like the aproach with the minimal table.

Re: calculating 65c02 instruction size

Posted: Mon Dec 04, 2023 7:19 pm
by BB8
I think this might be incorrect:
tius wrote:

Code: Select all

instruction_size:
    ldx #3

    eor #$03   
    bit #$03
    beq @one                ; x3, x7, xB, xF
the x7 and xF instructions are wider: BBx (xF) instructions are 3 bytes long, while xMB (x7) are 2 bytes long.

Re: calculating 65c02 instruction size

Posted: Tue Dec 05, 2023 9:20 am
by tius
BB8 wrote:
...
the x7 and xF instructions are wider: BBx (xF) instructions are 3 bytes long, while xMB (x7) are 2 bytes long.
You are right! This has changed with newer 65c02s (see http://www.6502.org/tutorials/65c02opcodes.html):

Code: Select all

      x2:     x3:     x4:     x7:     xB:     xC:     xF:
     -----   -----   -----   -----   -----   -----   -----
0x:  2 2 .   1 1 .   . . .   1 1 a   1 1 .   . . .   1 1 c
1x:  . . .   1 1 .   . . .   1 1 a   1 1 .   . . .   1 1 c
2x:  2 2 .   1 1 .   . . .   1 1 a   1 1 .   . . .   1 1 c
3x:  . . .   1 1 .   . . .   1 1 a   1 1 .   . . .   1 1 c
4x:  2 2 .   1 1 .   2 3 g   1 1 a   1 1 .   . . .   1 1 c
5x:  . . .   1 1 .   2 4 h   1 1 a   1 1 .   3 8 j   1 1 c
6x:  2 2 .   1 1 .   . . .   1 1 a   1 1 .   . . .   1 1 c
7x:  . . .   1 1 .   . . .   1 1 a   1 1 .   . . .   1 1 c
8x:  2 2 .   1 1 .   . . .   1 1 b   1 1 .   . . .   1 1 d
9x:  . . .   1 1 .   . . .   1 1 b   1 1 .   . . .   1 1 d
Ax:  . . .   1 1 .   . . .   1 1 b   1 1 .   . . .   1 1 d
Bx:  . . .   1 1 .   . . .   1 1 b   1 1 .   . . .   1 1 d
Cx:  2 2 .   1 1 .   . . .   1 1 b   1 1 e   . . .   1 1 d
Dx:  . . .   1 1 .   2 4 h   1 1 b   1 1 f   3 4 i   1 1 d
Ex:  2 2 .   1 1 .   . . .   1 1 b   1 1 .   . . .   1 1 d
Fx:  . . .   1 1 .   2 4 h   1 1 b   1 1 .   3 4 i   1 1 d
a) 1-cycle NOP on some older 65C02s; RMB instruction on Rockwell and on modern WDC 65C02s
b) 1-cycle NOP on some older 65C02s; SMB instruction on Rockwell and on modern WDC 65C02s
c) 1-cycle NOP on some older 65C02s; BBR instruction on Rockwell and on modern WDC 65C02s
d) 1-cycle NOP on some older 65C02s; BBS instruction on Rockwell and on modern WDC 65C02s
e) $CB is the WAI instruction on WDC 65C02
f) $DB is the STP instruction on WDC 65C02
g) $44 uses zp address mode to read memory
h) $54, $D4, and $F4 use zp,X address mode to read memory
i) $DC and $FC use absolute address mode to read memory
j) $5C reads from somewhere in the 64K range, using no known address mode
I'm not using these instructions yet, so I didn't notice the error. Thanks for the code review!

Re: calculating 65c02 instruction size

Posted: Sun Aug 11, 2024 6:34 pm
by pdragon
Here's a version similar to Osi's which works for all 256 65c02 instructions. Very slightly shorter and I think a little faster than the original posting in the thread:

Code: Select all

op_length:
        ; given an opcode in A, return its length in Y (stomps A)
                pha
                and #$f
                tay
                lda _lengths,y  ; lookup the length
                bmi _special    ; $x0 and $x9 are special

                ply             ; discard the opcode
                tay             ; return the length
                rts

_lengths:       .byte $80,2,2,1,2,2,2,2, 1,$81,1,1,3,3,3,3

_special:
                ldy #1          ; guess length 1

                ror             ; test bit 0: C=0 means $x0, C=1 means $x9
                pla             ; recover the opcode
                bcs _x9

                ; for $x0 length is two except $20 (3), $40 (1), $60 (1)
                bit #%10011111  ; is opcode 0/20/40/60 ?
                bne _two
                asl             ; test bit 6 by shifting to sign bit
                bmi _one        ; bit 6 set means $40 or $60
                ; otherwise we have  A=$40 if op was $20 and $0 otherwise
                ; shift right twice to reuse bit 4 test
                lsr
                lsr
_x9:
                ; for $x9, bit 4 set means 3 bytes, clear means 2
                and #$10
                beq _two
_three:         iny
_two:           iny
_one:           rts