1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-08-14 18:28:57 +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, private static StatusFlags FlagUpdater_ANDImm(StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) { ref StatusFlags condBranchTakenFlags) {
// AND #00 --> Z=1, else if Z=0 then Z=? // If we LDA #$81, LDX #$00, AND #$01, Z flag is clear (for us, Z=unknown).
// AND #7f --> N=0, else N=prev // AND #00 --> Z=1, else Z=unknown
// AND #7f --> N=0, else N=unknown
if (immVal == 0) { if (immVal == 0) {
flags.Z = 1; // acc is now zero flags.Z = 1; // acc is now zero
} else if (flags.Z == 0) { } else {
flags.Z = TriState16.INDETERMINATE; // acc *might* now be zero flags.Z = TriState16.INDETERMINATE; // may or may not be zero
} }
bool hiBitClear; bool hiBitClear;
if (immVal >= 0) { if (immVal >= 0) {
@ -685,15 +686,20 @@ namespace Asm65 {
} }
if (hiBitClear) { if (hiBitClear) {
flags.N = 0; flags.N = 0;
} else {
flags.N = TriState16.INDETERMINATE;
} }
return flags; return flags;
} }
private static StatusFlags FlagUpdater_ORAImm(StatusFlags flags, int immVal, private static StatusFlags FlagUpdater_ORAImm(StatusFlags flags, int immVal,
ref StatusFlags condBranchTakenFlags) { ref StatusFlags condBranchTakenFlags) {
// ORA #00 --> Z=prev, else Z=0 // If we LDA #$80, LDX #$00, ORA #$00, the N flag will be set (for us, N=unknown).
// ORA #80 --> N=1, else N=prev // ORA #00 --> Z=unknown, else Z=0
// ORA #80 --> N=1, else N=unknown
if (immVal != 0) { 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; bool hiBitSet;
if (immVal >= 0) { if (immVal >= 0) {
@ -706,6 +712,8 @@ namespace Asm65 {
} }
if (hiBitSet) { if (hiBitSet) {
flags.N = 1; flags.N = 1;
} else {
flags.N = TriState16.INDETERMINATE;
} }
return flags; return flags;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -138,14 +138,16 @@ ok_neg
brk $db brk $db
ok_andZ1 ok_andZ1
lda #$00 lda #$00
ldx #$80
and #$ff and #$ff
beq ok_andZ1A beq ok_andZ1A
brk $db bne ok_andZ1A
ok_andZ1A ok_andZ1A
lda #$ff lda #$ff
ldx #$00
and #$7f and #$7f
beq ok_andZ0
bne ok_andZ0 bne ok_andZ0
brk $db
ok_andZ0 ok_andZ0
bpl ok_andN0 bpl ok_andN0
brk $db brk $db
@ -158,17 +160,24 @@ ok_andN1
; check NZ flags set by immediate ORA ; check NZ flags set by immediate ORA
lda #$00 lda #$00
ora #$00 ldx #$80
beq ok_oraZ1 bne :next1
brk $db brk $db
:next1 ora #$00
beq ok_oraZ1
bne ok_oraZ1
ok_oraZ1 ok_oraZ1
ora #$01 ora #$01
bne ok_oraZ0 bne ok_oraZ0
brk $db brk $db
ok_oraZ0 ok_oraZ0
lda #$00 lda #$00
ora #$7f ldx #$80
bpl ok_oraN0 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 brk $db
ok_oraN0 ok_oraN0
ora #$80 ora #$80