1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-06-11 17:29:29 +00:00

Fix AND/ORA imm flag updater

The code was making an unwarranted assumption about how the flags
were being set.  For example, ORA #$00 can't know if the previous
contents of the accumulator were nonzero, only that the instruction
hasn't made them nonzero, but instead of marking the Z-flag
"indeterminate" it was leaving the flag in its previous state.  This
produces incorrect results if the previous instruction didn't set
its flags from the accumulator contents, e.g. it was an LDX.

Test 1003-flags-and-branches has been updated to test these states.
This commit is contained in:
Andy McFadden 2020-05-01 17:25:18 -07:00
parent 59b7ec0dea
commit facaa721de
8 changed files with 247 additions and 194 deletions

View File

@ -667,12 +667,13 @@ namespace Asm65 {
}
private static StatusFlags FlagUpdater_ANDImm(StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
// AND #00 --> Z=1, else if Z=0 then Z=?
// AND #7f --> N=0, else N=prev
// If we LDA #$81, LDX #$00, AND #$01, Z flag is clear (for us, Z=unknown).
// AND #00 --> Z=1, else Z=unknown
// AND #7f --> N=0, else N=unknown
if (immVal == 0) {
flags.Z = 1; // acc is now zero
} else if (flags.Z == 0) {
flags.Z = TriState16.INDETERMINATE; // acc *might* now be zero
} else {
flags.Z = TriState16.INDETERMINATE; // may or may not be zero
}
bool hiBitClear;
if (immVal >= 0) {
@ -685,15 +686,20 @@ namespace Asm65 {
}
if (hiBitClear) {
flags.N = 0;
} else {
flags.N = TriState16.INDETERMINATE;
}
return flags;
}
private static StatusFlags FlagUpdater_ORAImm(StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) {
// ORA #00 --> Z=prev, else Z=0
// ORA #80 --> N=1, else N=prev
// If we LDA #$80, LDX #$00, ORA #$00, the N flag will be set (for us, N=unknown).
// ORA #00 --> Z=unknown, else Z=0
// ORA #80 --> N=1, else N=unknown
if (immVal != 0) {
flags.Z = 0;
flags.Z = 0; // acc is now nonzero
} else {
flags.Z = TriState16.INDETERMINATE; // may or may not be zero
}
bool hiBitSet;
if (immVal >= 0) {
@ -706,6 +712,8 @@ namespace Asm65 {
}
if (hiBitSet) {
flags.N = 1;
} else {
flags.N = TriState16.INDETERMINATE;
}
return flags;
}

View File

@ -145,131 +145,140 @@ _L10A3 lda #$ff
.byte $db
_L10AB lda #$00
ldx #$80
and #$ff
beq _L10B3
beq _L10B5
bne _L10B5
_L10B5 lda #$ff
ldx #$00
and #$7f
beq _L10BF
bne _L10BF
_L10BF bpl _L10C3
.byte $00
.byte $db
_L10B3 lda #$ff
and #$7f
bne _L10BB
_L10C3 lda #$ff
and #$80
bmi _L10CB
brk
.byte $db
_L10BB bpl _L10BF
_L10CB lda #$00
ldx #$80
bne _L10D3
.byte $00
.byte $db
_L10BF lda #$ff
and #$80
bmi _L10C7
_L10D3 ora #$00
beq _L10D9
bne _L10D9
_L10D9 ora #$01
bne _L10DF
.byte $00
.byte $db
_L10C7 lda #$00
ora #$00
beq _L10CF
_L10DF lda #$00
ldx #$80
bmi _L10E7
.byte $00
.byte $db
_L10CF ora #$01
bne _L10D5
_L10E7 ora #$7f
bpl _L10EF
bmi _L10EF
.byte $00
.byte $db
_L10D5 lda #$00
ora #$7f
bpl _L10DD
_L10EF ora #$80
bmi _L10F5
.byte $00
.byte $db
_L10DD ora #$80
bmi _L10E3
.byte $00
.byte $db
_L10E3 lda _L10E3
_L10F5 lda _L10F5
sec
ror a
bmi _L10EC
bmi _L10FE
.byte $00
.byte $dc
_L10EC clc
_L10FE clc
ror a
bpl _L10F2
bpl _L1104
.byte $00
.byte $dc
_L10F2 lda #$00
_L1104 lda #$00
sec
rol a
bne _L10FA
bne _L110C
.byte $00
.byte $dc
_L10FA lda #$ff
_L110C lda #$ff
lsr a
bpl _L1101
bpl _L1113
.byte $00
.byte $dd
_L1101 clc
_L1113 clc
php
sec
plp
bcc _L1109
bcc _L111B
.byte $00
.byte $00
_L1109 sec
bcs _L110D
_L111B sec
bcs _L111F
_L110C clc
_L110D lda $33
beq _L110C
bcs _L1115
_L111E clc
_L111F lda $33
beq _L111E
bcs _L1127
lda $44
_L1115 nop
_L1127 nop
rep #$20
.al
sep #$10
jsr _L1131
jsr _L1143
rep #$30
.xl
jsr _L1137
jsr _L1149
sep #$30
.as
.xs
jsr _L1137
jsr _L1149
rep #$20
.al
sep #$10
jsr _L1131
jsr _L1143
sep #$30
.as
rts
.al
_L1131 lda #$1234
_L1143 lda #$1234
ldx #$ff
rts
.as
_L1137 lda #$ff
_L1149 lda #$ff
ldx #$ee
ldy #$dd
rts

View File

@ -140,130 +140,139 @@ L105F sep #$80
dfb $db
:L10AB lda #$00
ldx #$80
and #$ff
beq :L10B3
beq :L10B5
bne :L10B5
:L10B5 lda #$ff
ldx #$00
and #$7f
beq :L10BF
bne :L10BF
:L10BF bpl :L10C3
dfb $00
dfb $db
:L10B3 lda #$ff
and #$7f
bne :L10BB
:L10C3 lda #$ff
and #$80
bmi :L10CB
brk
dfb $db
:L10BB bpl :L10BF
:L10CB lda #$00
ldx #$80
bne :L10D3
dfb $00
dfb $db
:L10BF lda #$ff
and #$80
bmi :L10C7
:L10D3 ora #$00
beq :L10D9
bne :L10D9
:L10D9 ora #$01
bne :L10DF
dfb $00
dfb $db
:L10C7 lda #$00
ora #$00
beq :L10CF
:L10DF lda #$00
ldx #$80
bmi :L10E7
dfb $00
dfb $db
:L10CF ora #$01
bne :L10D5
:L10E7 ora #$7f
bpl :L10EF
bmi :L10EF
dfb $00
dfb $db
:L10D5 lda #$00
ora #$7f
bpl :L10DD
:L10EF ora #$80
bmi :L10F5
dfb $00
dfb $db
:L10DD ora #$80
bmi :L10E3
dfb $00
dfb $db
:L10E3 lda :L10E3
:L10F5 lda :L10F5
sec
ror A
bmi :L10EC
bmi :L10FE
dfb $00
dfb $dc
:L10EC clc
:L10FE clc
ror A
bpl :L10F2
bpl :L1104
dfb $00
dfb $dc
:L10F2 lda #$00
:L1104 lda #$00
sec
rol A
bne :L10FA
bne :L110C
dfb $00
dfb $dc
:L10FA lda #$ff
:L110C lda #$ff
lsr A
bpl :L1101
bpl :L1113
dfb $00
dfb $dd
:L1101 clc
:L1113 clc
php
sec
plp
bcc :L1109
bcc :L111B
dfb $00
dfb $00
:L1109 sec
bcs :L110D
:L111B sec
bcs :L111F
:L110C clc
:L110D lda $33
beq :L110C
bcs :L1115
:L111E clc
:L111F lda $33
beq :L111E
bcs :L1127
lda $44
:L1115 nop
:L1127 nop
rep #$20
mx %01
sep #$10
jsr :L1131
jsr :L1143
rep #$30
mx %00
jsr :L1137
jsr :L1149
sep #$30
mx %11
jsr :L1137
jsr :L1149
rep #$20
mx %01
sep #$10
jsr :L1131
jsr :L1143
sep #$30
mx %11
rts
mx %01
:L1131 lda #$1234
:L1143 lda #$1234
ldx #$ff
rts
mx %11
:L1137 lda #$ff
:L1149 lda #$ff
ldx #$ee
ldy #$dd
rts

View File

@ -145,131 +145,140 @@ L105F sep #$80
!byte $db
@L10AB lda #$00
ldx #$80
and #$ff
beq @L10B3
beq @L10B5
bne @L10B5
@L10B5 lda #$ff
ldx #$00
and #$7f
beq @L10BF
bne @L10BF
@L10BF bpl @L10C3
!byte $00
!byte $db
@L10B3 lda #$ff
and #$7f
bne @L10BB
@L10C3 lda #$ff
and #$80
bmi @L10CB
brk
!byte $db
@L10BB bpl @L10BF
@L10CB lda #$00
ldx #$80
bne @L10D3
!byte $00
!byte $db
@L10BF lda #$ff
and #$80
bmi @L10C7
@L10D3 ora #$00
beq @L10D9
bne @L10D9
@L10D9 ora #$01
bne @L10DF
!byte $00
!byte $db
@L10C7 lda #$00
ora #$00
beq @L10CF
@L10DF lda #$00
ldx #$80
bmi @L10E7
!byte $00
!byte $db
@L10CF ora #$01
bne @L10D5
@L10E7 ora #$7f
bpl @L10EF
bmi @L10EF
!byte $00
!byte $db
@L10D5 lda #$00
ora #$7f
bpl @L10DD
@L10EF ora #$80
bmi @L10F5
!byte $00
!byte $db
@L10DD ora #$80
bmi @L10E3
!byte $00
!byte $db
@L10E3 lda @L10E3
@L10F5 lda @L10F5
sec
ror
bmi @L10EC
bmi @L10FE
!byte $00
!byte $dc
@L10EC clc
@L10FE clc
ror
bpl @L10F2
bpl @L1104
!byte $00
!byte $dc
@L10F2 lda #$00
@L1104 lda #$00
sec
rol
bne @L10FA
bne @L110C
!byte $00
!byte $dc
@L10FA lda #$ff
@L110C lda #$ff
lsr
bpl @L1101
bpl @L1113
!byte $00
!byte $dd
@L1101 clc
@L1113 clc
php
sec
plp
bcc @L1109
bcc @L111B
!byte $00
!byte $00
@L1109 sec
bcs @L110D
@L111B sec
bcs @L111F
@L110C clc
@L110D lda $33
beq @L110C
bcs @L1115
@L111E clc
@L111F lda $33
beq @L111E
bcs @L1127
lda $44
@L1115 nop
@L1127 nop
rep #$20
!al
sep #$10
jsr @L1131
jsr @L1143
rep #$30
!rl
jsr @L1137
jsr @L1149
sep #$30
!as
!rs
jsr @L1137
jsr @L1149
rep #$20
!al
sep #$10
jsr @L1131
jsr @L1143
sep #$30
!as
rts
!al
@L1131 lda #$1234
@L1143 lda #$1234
ldx #$ff
rts
!as
@L1137 lda #$ff
@L1149 lda #$ff
ldx #$ee
ldy #$dd
rts

View File

@ -146,131 +146,140 @@ L105F: sep #$80
.byte $db
@L10AB: lda #$00
ldx #$80
and #$ff
beq @L10B3
beq @L10B5
bne @L10B5
@L10B5: lda #$ff
ldx #$00
and #$7f
beq @L10BF
bne @L10BF
@L10BF: bpl @L10C3
.byte $00
.byte $db
@L10B3: lda #$ff
and #$7f
bne @L10BB
@L10C3: lda #$ff
and #$80
bmi @L10CB
brk
.byte $db
@L10BB: bpl @L10BF
@L10CB: lda #$00
ldx #$80
bne @L10D3
.byte $00
.byte $db
@L10BF: lda #$ff
and #$80
bmi @L10C7
@L10D3: ora #$00
beq @L10D9
bne @L10D9
@L10D9: ora #$01
bne @L10DF
.byte $00
.byte $db
@L10C7: lda #$00
ora #$00
beq @L10CF
@L10DF: lda #$00
ldx #$80
bmi @L10E7
.byte $00
.byte $db
@L10CF: ora #$01
bne @L10D5
@L10E7: ora #$7f
bpl @L10EF
bmi @L10EF
.byte $00
.byte $db
@L10D5: lda #$00
ora #$7f
bpl @L10DD
@L10EF: ora #$80
bmi @L10F5
.byte $00
.byte $db
@L10DD: ora #$80
bmi @L10E3
.byte $00
.byte $db
@L10E3: lda @L10E3
@L10F5: lda @L10F5
sec
ror A
bmi @L10EC
bmi @L10FE
.byte $00
.byte $dc
@L10EC: clc
@L10FE: clc
ror A
bpl @L10F2
bpl @L1104
.byte $00
.byte $dc
@L10F2: lda #$00
@L1104: lda #$00
sec
rol A
bne @L10FA
bne @L110C
.byte $00
.byte $dc
@L10FA: lda #$ff
@L110C: lda #$ff
lsr A
bpl @L1101
bpl @L1113
.byte $00
.byte $dd
@L1101: clc
@L1113: clc
php
sec
plp
bcc @L1109
bcc @L111B
.byte $00
.byte $00
@L1109: sec
bcs @L110D
@L111B: sec
bcs @L111F
@L110C: clc
@L110D: lda $33
beq @L110C
bcs @L1115
@L111E: clc
@L111F: lda $33
beq @L111E
bcs @L1127
lda $44
@L1115: nop
@L1127: nop
rep #$20
.a16
sep #$10
jsr @L1131
jsr @L1143
rep #$30
.i16
jsr @L1137
jsr @L1149
sep #$30
.a8
.i8
jsr @L1137
jsr @L1149
rep #$20
.a16
sep #$10
jsr @L1131
jsr @L1143
sep #$30
.a8
rts
.a16
@L1131: lda #$1234
@L1143: lda #$1234
ldx #$ff
rts
.a8
@L1137: lda #$ff
@L1149: lda #$ff
ldx #$ee
ldy #$dd
rts

View File

@ -1,7 +1,7 @@
# 6502bench SourceGen generated linker script for 1003-flags-and-branches
MEMORY {
MAIN: file=%O, start=%S, size=65536;
# MEM000: file=%O, start=$1000, size=318;
# MEM000: file=%O, start=$1000, size=336;
}
SEGMENTS {
CODE: load=MAIN, type=rw;

View File

@ -138,14 +138,16 @@ ok_neg
brk $db
ok_andZ1
lda #$00
ldx #$80
and #$ff
beq ok_andZ1A
brk $db
bne ok_andZ1A
ok_andZ1A
lda #$ff
ldx #$00
and #$7f
beq ok_andZ0
bne ok_andZ0
brk $db
ok_andZ0
bpl ok_andN0
brk $db
@ -158,17 +160,24 @@ ok_andN1
; check NZ flags set by immediate ORA
lda #$00
ora #$00
beq ok_oraZ1
ldx #$80
bne :next1
brk $db
:next1 ora #$00
beq ok_oraZ1
bne ok_oraZ1
ok_oraZ1
ora #$01
bne ok_oraZ0
brk $db
ok_oraZ0
lda #$00
ora #$7f
bpl ok_oraN0
ldx #$80
bmi :next2
brk $db
:next2 ora #$7f ;N-flag clear, but analyzer doesn't know
bpl ok_oraN0 ;so both of these are considered viable
bmi ok_oraN0
brk $db
ok_oraN0
ora #$80