diff --git a/compiler/res/prog8lib/c64utils.p8 b/compiler/res/prog8lib/c64utils.p8 index ad343f150..0683919cd 100644 --- a/compiler/res/prog8lib/c64utils.p8 +++ b/compiler/res/prog8lib/c64utils.p8 @@ -102,7 +102,6 @@ asmsub uword2bcd (uword value @ AY) clobbers(A,Y) { pla ; read status register and #%00000100 sta _had_irqd - sei ; disable interrupts because of bcd math sed ; switch to decimal mode lda #0 ; ensure the result is clear sta bcdbuff+0 @@ -341,6 +340,7 @@ _irq_handler_init dex dex dex + cld rts _irq_handler_end diff --git a/sim65/src/components/Cpu6502.kt b/sim65/src/components/Cpu6502.kt index 36196d08f..8143e6f94 100644 --- a/sim65/src/components/Cpu6502.kt +++ b/sim65/src/components/Cpu6502.kt @@ -702,13 +702,12 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu var lo = (A and 0x0f) + (operand and 0x0f) + if (Status.C) 1 else 0 if (lo and 0xff > 9) lo += 6 var hi = (A shr 4) + (operand shr 4) + if (lo > 15) 1 else 0 + Status.N = (hi and 8) != 0 // strange... other sources say "BCD is never negative on NMOS 6502 (bug)" + Status.V = ((((hi shl 4) xor A) and 0x80) !=0) && ((A xor operand) and 0x80)==0 // strange... other sources say "V is never set in BCD mode" if (hi and 0xff > 9) hi += 6 - val result = lo and 0x0f or (hi shl 4) - A = result and 0xff + A = lo and 0x0f or (hi shl 4) and 0xff Status.C = hi > 15 Status.Z = A == 0 - Status.V = false // BCD never sets overflow flag - Status.N = false // BCD is never negative on NMOS 6502 (bug) } else { // normal add val result = A + operand + if (Status.C) 1 else 0 @@ -990,21 +989,22 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu } private fun iSbc() { - val operand = getFetched() if (Status.D) { - var lo = (A and 0x0f) - (operand and 0x0f) - if (Status.C) 0 else 1 + val operand = getFetched() + var lo: Int + var hi: Int + lo = (A and 0x0f) - (operand and 0x0f) - if (Status.C) 0 else 1 if (lo and 0x10 != 0) lo -= 6 - var hi = (A shr 4) - (operand shr 4) - if (lo and 0x10 != 0) 1 else 0 + hi = (A shr 4) - (operand shr 4) - if (lo and 0x10 != 0) 1 else 0 if (hi and 0x10 != 0) hi -= 6 - val result = lo and 0x0f or ((hi shl 4) and 0xff) - Status.C = hi and 255 < 15 - Status.Z = result == 0 - Status.V = false // BCD never sets overflow flag - Status.N = false // BCD is never negative on NMOS 6502 (bug) - A = result and 255 + A = lo and 0x0f or (hi shl 4) and 0xff + Status.C = hi and 0xff < 15 + Status.V = false // BCD never sets overflow flag + Status.Z = A==0 + Status.N = (A and 0b10000000) != 0 } else { // normal sub - val invertedOperand = operand xor 255 + val invertedOperand = getFetched() xor 255 val result = A + invertedOperand + if (Status.C) 1 else 0 Status.C = result > 255 Status.V = (A xor invertedOperand) and (A xor result) and 0x0080 != 0 diff --git a/sim65/test/TestCommon6502.kt b/sim65/test/TestCommon6502.kt index fcd1b96a6..850cf1bac 100644 --- a/sim65/test/TestCommon6502.kt +++ b/sim65/test/TestCommon6502.kt @@ -505,11 +505,10 @@ abstract class TestCommon6502 { mpu.step() assertEquals(0x0002, mpu.PC) assertEquals(0x80, mpu.A) - assertTrue(mpu.Status.N) - assertTrue(mpu.Status.V) - assertFalse(mpu.Status.Z) assertFalse(mpu.Status.C) - + assertFalse(mpu.Status.Z) + assertTrue(mpu.Status.V) + assertTrue(mpu.Status.N) } @Test @@ -547,14 +546,13 @@ abstract class TestCommon6502 { assertEquals(0x0004, mpu.PC) assertEquals(0x93, mpu.A) assertFalse(mpu.Status.N) - assertTrue(mpu.Status.V) assertFalse(mpu.Status.Z) assertTrue(mpu.Status.C) - - // ADC Absolute, X-Indexed - + assertTrue(mpu.Status.V) } + // ADC Absolute, X-Indexed + @Test fun test_adc_bcd_off_abs_x_carry_clear_in_accumulator_zeroes() { @@ -5696,10 +5694,10 @@ abstract class TestCommon6502 { mpu.step() assertEquals(0x0002, mpu.PC) assertEquals(0x9a, mpu.A) - assertTrue(mpu.Status.N) - assertFalse(mpu.Status.V) assertFalse(mpu.Status.Z) assertTrue(mpu.Status.C) + assertFalse(mpu.Status.V) + assertTrue(mpu.Status.N) } @Test @@ -5715,17 +5713,18 @@ abstract class TestCommon6502 { mpu.step() assertEquals(0x0002, mpu.PC) assertEquals(0x99, mpu.A) - assertTrue(mpu.Status.N) - assertFalse(mpu.Status.V) assertFalse(mpu.Status.Z) assertFalse(mpu.Status.C) + assertFalse(mpu.Status.V) + assertTrue(mpu.Status.N) } @Test fun test_sbc_bcd_on_immediate_20_minus_0a_carry_unset() { mpu.Status.D = true + mpu.Status.C = false mpu.A = 0x20 - // $0000 SBC #$00 + // $0000 SBC #$0a writeMem(memory, 0x0000, listOf(0xe9, 0x0a)) mpu.step() assertEquals(0x0002, mpu.PC)