From facaa721dee38c2b8c9287e7d7f4036e70bbb62f Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Fri, 1 May 2020 17:25:18 -0700 Subject: [PATCH] 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. --- Asm65/OpDef.cs | 22 ++-- SourceGen/SGTestData/1003-flags-and-branches | Bin 318 -> 336 bytes .../Expected/1003-flags-and-branches_64tass.S | 99 ++++++++++-------- .../1003-flags-and-branches_Merlin32.S | 99 ++++++++++-------- .../Expected/1003-flags-and-branches_acme.S | 99 ++++++++++-------- .../Expected/1003-flags-and-branches_cc65.S | 99 ++++++++++-------- .../Expected/1003-flags-and-branches_cc65.cfg | 2 +- .../Source/1003-flags-and-branches.S | 21 ++-- 8 files changed, 247 insertions(+), 194 deletions(-) diff --git a/Asm65/OpDef.cs b/Asm65/OpDef.cs index 9447324..0c271f5 100644 --- a/Asm65/OpDef.cs +++ b/Asm65/OpDef.cs @@ -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; } diff --git a/SourceGen/SGTestData/1003-flags-and-branches b/SourceGen/SGTestData/1003-flags-and-branches index 0f2797dc315d6eb3b8bbe92c638ad687f9fb91f0..6528821b7a25de66ba87f6873b2c02889bcb7ff7 100644 GIT binary patch delta 120 zcmdnTbb)EYTCYV7n*TpAU0_)Ge-VRbJ%}a1#Bh7%f6WF15Y4ct;R2B6WB|!w2x`RS_{qpAD9?!ul%oBe*s7fK-diiAew=b0VK!C2$BKv>Or!cV7axACw@0m mHWWN$pkOZe2t*uGcqE`;2xKR$G!a_#KVjwnMei2eO#lGuW+-C- diff --git a/SourceGen/SGTestData/Expected/1003-flags-and-branches_64tass.S b/SourceGen/SGTestData/Expected/1003-flags-and-branches_64tass.S index e87ab2f..fe05151 100644 --- a/SourceGen/SGTestData/Expected/1003-flags-and-branches_64tass.S +++ b/SourceGen/SGTestData/Expected/1003-flags-and-branches_64tass.S @@ -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 diff --git a/SourceGen/SGTestData/Expected/1003-flags-and-branches_Merlin32.S b/SourceGen/SGTestData/Expected/1003-flags-and-branches_Merlin32.S index d8ea883..6d138eb 100644 --- a/SourceGen/SGTestData/Expected/1003-flags-and-branches_Merlin32.S +++ b/SourceGen/SGTestData/Expected/1003-flags-and-branches_Merlin32.S @@ -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 diff --git a/SourceGen/SGTestData/Expected/1003-flags-and-branches_acme.S b/SourceGen/SGTestData/Expected/1003-flags-and-branches_acme.S index 545263c..667f994 100644 --- a/SourceGen/SGTestData/Expected/1003-flags-and-branches_acme.S +++ b/SourceGen/SGTestData/Expected/1003-flags-and-branches_acme.S @@ -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 diff --git a/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.S b/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.S index f65691e..389f4d5 100644 --- a/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.S +++ b/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.S @@ -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 diff --git a/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.cfg b/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.cfg index c1cdbb0..8375593 100644 --- a/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.cfg +++ b/SourceGen/SGTestData/Expected/1003-flags-and-branches_cc65.cfg @@ -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; diff --git a/SourceGen/SGTestData/Source/1003-flags-and-branches.S b/SourceGen/SGTestData/Source/1003-flags-and-branches.S index 26ba38d..7449c81 100644 --- a/SourceGen/SGTestData/Source/1003-flags-and-branches.S +++ b/SourceGen/SGTestData/Source/1003-flags-and-branches.S @@ -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