fixed sbc and adc

This commit is contained in:
Irmen de Jong 2019-09-08 22:03:16 +02:00
parent b400010426
commit fec8db6a75
7 changed files with 97 additions and 87 deletions

View File

@ -2,5 +2,6 @@
<project version="4"> <project version="4">
<component name="VcsDirectoryMappings"> <component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" /> <mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/sim65/test/6502_functional_tests" vcs="Git" />
</component> </component>
</project> </project>

View File

@ -34,7 +34,7 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
fun hexW(number: Address, allowSingleByte: Boolean = false): String { fun hexW(number: Address, allowSingleByte: Boolean = false): String {
val msb = number ushr 8 val msb = number ushr 8
val lsb = number and 255 val lsb = number and 0xff
return if (msb == 0 && allowSingleByte) return if (msb == 0 && allowSingleByte)
hexB(lsb) hexB(lsb)
else else
@ -332,20 +332,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
private fun amZpx() { private fun amZpx() {
// note: zeropage index will not leave Zp when page boundray is crossed // note: zeropage index will not leave Zp when page boundray is crossed
fetchedAddress = (readPc() + X) and 255 fetchedAddress = (readPc() + X) and 0xff
} }
private fun amZpy() { private fun amZpy() {
// note: zeropage index will not leave Zp when page boundray is crossed // note: zeropage index will not leave Zp when page boundray is crossed
fetchedAddress = (readPc() + Y) and 255 fetchedAddress = (readPc() + Y) and 0xff
} }
private fun amRel() { private fun amRel() {
val relative = readPc() val relative = readPc()
fetchedAddress = if (relative >= 0x80) fetchedAddress = if (relative >= 0x80) {
PC - (256 - relative) PC - (256 - relative) and 0xffff
else } else
PC + relative PC + relative and 0xffff
} }
private fun amAbs() { private fun amAbs() {
@ -386,8 +386,8 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
private fun amIzx() { private fun amIzx() {
// note: not able to fetch an adress which crosses the page boundary // note: not able to fetch an adress which crosses the page boundary
fetchedAddress = readPc() fetchedAddress = readPc()
val lo = read((fetchedAddress + X) and 255) val lo = read((fetchedAddress + X) and 0xff)
val hi = read((fetchedAddress + X + 1) and 255) val hi = read((fetchedAddress + X + 1) and 0xff)
fetchedAddress = lo or (hi shl 8) fetchedAddress = lo or (hi shl 8)
} }
@ -395,23 +395,22 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
// note: not able to fetch an adress which crosses the page boundary // note: not able to fetch an adress which crosses the page boundary
fetchedAddress = readPc() fetchedAddress = readPc()
val lo = read(fetchedAddress) val lo = read(fetchedAddress)
val hi = read((fetchedAddress + 1) and 255) val hi = read((fetchedAddress + 1) and 0xff)
fetchedAddress = Y + (lo or (hi shl 8)) and 65535 fetchedAddress = Y + (lo or (hi shl 8)) and 0xffff
} }
private fun getFetched(): Int { private fun getFetched() =
return if (currentInstruction.mode == AddrMode.Imm || if (currentInstruction.mode == AddrMode.Imm ||
currentInstruction.mode == AddrMode.Acc || currentInstruction.mode == AddrMode.Acc ||
currentInstruction.mode == AddrMode.Imp) currentInstruction.mode == AddrMode.Imp)
fetchedData fetchedData
else else
read(fetchedAddress) read(fetchedAddress)
}
private fun readPc(): Int = bus.read(PC++).toInt() private fun readPc(): Int = bus.read(PC++).toInt()
private fun pushStackAddr(address: Address) { private fun pushStackAddr(address: Address) {
val lo = address and 255 val lo = address and 0xff
val hi = (address ushr 8) val hi = (address ushr 8)
pushStack(hi) pushStack(hi)
pushStack(lo) pushStack(lo)
@ -717,26 +716,26 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
// and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/6510core.c#l598 // and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/6510core.c#l598
// (the implementation below is based on the code used by Vice) // (the implementation below is based on the code used by Vice)
var tmp = (A and 0xf) + (operand and 0xf) + (if (Status.C) 1 else 0) var tmp = (A and 0xf) + (operand and 0xf) + (if (Status.C) 1 else 0)
if (tmp > 0x9) tmp += 0x6 if (tmp > 9) tmp += 6
tmp = if (tmp <= 0x0f) { tmp = if (tmp <= 0x0f) {
(tmp and 0xf) + (A and 0xf0) + (operand and 0xf0) (tmp and 0xf) + (A and 0xf0) + (operand and 0xf0)
} else { } else {
(tmp and 0xf) + (A and 0xf0) + (operand and 0xf0) + 0x10 (tmp and 0xf) + (A and 0xf0) + (operand and 0xf0) + 0x10
} }
Status.Z = ((A + operand + (if (Status.C) 1 else 0)) and 0xff) == 0 Status.Z = A + operand + (if (Status.C) 1 else 0) and 0xff == 0
Status.N = (tmp and 0b10000000) != 0 Status.N = tmp and 0b10000000 != 0
Status.V = ((A xor tmp) and 0x80) != 0 && ((A xor operand) and 0x80) == 0 Status.V = (A xor tmp) and 0x80 != 0 && (A xor operand) and 0b10000000 == 0
if (tmp > 0x90) tmp += 0x60 if (tmp and 0x1f0 > 0x90) tmp += 0x60
Status.C = tmp > 0xf0 Status.C = tmp > 0xf0 // original: (tmp and 0xff0) > 0xf0
A = tmp and 255 A = tmp and 0xff
} else { } else {
// normal add // normal add
val tmp = operand + A + if (Status.C) 1 else 0 val tmp = operand + A + if (Status.C) 1 else 0
Status.N = (tmp and 0b10000000) != 0 Status.N = (tmp and 0b10000000) != 0
Status.Z = (tmp and 255) == 0 Status.Z = (tmp and 0xff) == 0
Status.V = ((A xor operand) and 0x80) == 0 && ((A xor tmp) and 0x80) != 0 Status.V = (A xor operand).inv() and (A xor tmp) and 0b10000000 != 0
Status.C = tmp > 255 Status.C = tmp > 0xff
A = tmp and 255 A = tmp and 0xff
} }
} }
@ -749,13 +748,13 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
private fun iAsl() { private fun iAsl() {
if (currentInstruction.mode == AddrMode.Acc) { if (currentInstruction.mode == AddrMode.Acc) {
Status.C = (A and 0b10000000) != 0 Status.C = (A and 0b10000000) != 0
A = (A shl 1) and 255 A = (A shl 1) and 0xff
Status.Z = A == 0 Status.Z = A == 0
Status.N = (A and 0b10000000) != 0 Status.N = (A and 0b10000000) != 0
} else { } else {
val data = read(fetchedAddress) val data = read(fetchedAddress)
Status.C = (data and 0b10000000) != 0 Status.C = (data and 0b10000000) != 0
val shifted = (data shl 1) and 255 val shifted = (data shl 1) and 0xff
write(fetchedAddress, shifted) write(fetchedAddress, shifted)
Status.Z = shifted == 0 Status.Z = shifted == 0
Status.N = (shifted and 0b10000000) != 0 Status.N = (shifted and 0b10000000) != 0
@ -848,20 +847,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
} }
private fun iDec() { private fun iDec() {
val data = (read(fetchedAddress) - 1) and 255 val data = (read(fetchedAddress) - 1) and 0xff
write(fetchedAddress, data) write(fetchedAddress, data)
Status.Z = data == 0 Status.Z = data == 0
Status.N = (data and 0b10000000) != 0 Status.N = (data and 0b10000000) != 0
} }
private fun iDex() { private fun iDex() {
X = (X - 1) and 255 X = (X - 1) and 0xff
Status.Z = X == 0 Status.Z = X == 0
Status.N = (X and 0b10000000) != 0 Status.N = (X and 0b10000000) != 0
} }
private fun iDey() { private fun iDey() {
Y = (Y - 1) and 255 Y = (Y - 1) and 0xff
Status.Z = Y == 0 Status.Z = Y == 0
Status.N = (Y and 0b10000000) != 0 Status.N = (Y and 0b10000000) != 0
} }
@ -873,20 +872,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
} }
private fun iInc() { private fun iInc() {
val data = (read(fetchedAddress) + 1) and 255 val data = (read(fetchedAddress) + 1) and 0xff
write(fetchedAddress, data) write(fetchedAddress, data)
Status.Z = data == 0 Status.Z = data == 0
Status.N = (data and 0b10000000) != 0 Status.N = (data and 0b10000000) != 0
} }
private fun iInx() { private fun iInx() {
X = (X + 1) and 255 X = (X + 1) and 0xff
Status.Z = X == 0 Status.Z = X == 0
Status.N = (X and 0b10000000) != 0 Status.N = (X and 0b10000000) != 0
} }
private fun iIny() { private fun iIny() {
Y = (Y + 1) and 255 Y = (Y + 1) and 0xff
Status.Z = Y == 0 Status.Z = Y == 0
Status.N = (Y and 0b10000000) != 0 Status.N = (Y and 0b10000000) != 0
} }
@ -968,13 +967,13 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
val oldCarry = Status.C val oldCarry = Status.C
if (currentInstruction.mode == AddrMode.Acc) { if (currentInstruction.mode == AddrMode.Acc) {
Status.C = (A and 0b10000000) != 0 Status.C = (A and 0b10000000) != 0
A = (A shl 1 and 255) or (if (oldCarry) 1 else 0) A = (A shl 1 and 0xff) or (if (oldCarry) 1 else 0)
Status.Z = A == 0 Status.Z = A == 0
Status.N = (A and 0b10000000) != 0 Status.N = (A and 0b10000000) != 0
} else { } else {
val data = read(fetchedAddress) val data = read(fetchedAddress)
Status.C = (data and 0b10000000) != 0 Status.C = (data and 0b10000000) != 0
val shifted = (data shl 1 and 255) or (if (oldCarry) 1 else 0) val shifted = (data shl 1 and 0xff) or (if (oldCarry) 1 else 0)
write(fetchedAddress, shifted) write(fetchedAddress, shifted)
Status.Z = shifted == 0 Status.Z = shifted == 0
Status.N = (shifted and 0b10000000) != 0 Status.N = (shifted and 0b10000000) != 0
@ -1011,29 +1010,29 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
private fun iSbc() { private fun iSbc() {
val operand = getFetched() val operand = getFetched()
val tmp = (A - operand - if (Status.C) 0 else 1) and 65535 val tmp = (A - operand - if (Status.C) 0 else 1) and 0xffff
Status.V = (A xor operand) and (A xor tmp) and 0b10000000 != 0
if (Status.D) { if (Status.D) {
// BCD subtract // BCD subtract
// see http://www.6502.org/tutorials/decimal_mode.html // see http://www.6502.org/tutorials/decimal_mode.html
// and http://nesdev.com/6502.txt // and http://nesdev.com/6502.txt
// and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/6510core.c#l1396 // and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/6510core.c#l1396
// (the implementation below is based on the code used by Vice) // (the implementation below is based on the code used by Vice)
var tmpA = ((A and 0xf) - (operand and 0xf) - if (Status.C) 0 else 1) and 65535 var tmpA = ((A and 0xf) - (operand and 0xf) - if (Status.C) 0 else 1) and 0xffff
tmpA = if ((tmpA and 0x10) != 0) { tmpA = if ((tmpA and 0x10) != 0) {
((tmpA - 6) and 0xf) or (A and 0xf0) - (operand and 0xf0) - 0x10 ((tmpA - 6) and 0xf) or (A and 0xf0) - (operand and 0xf0) - 0x10
} else { } else {
(tmpA and 0xf) or (A and 0xf0) - (operand and 0xf0) (tmpA and 0xf) or (A and 0xf0) - (operand and 0xf0)
} }
if ((tmpA and 0x100) != 0) tmpA -= 0x60 if ((tmpA and 0x100) != 0) tmpA -= 0x60
A = tmpA and 255 A = tmpA and 0xff
} else { } else {
// normal subtract // normal subtract
A = tmp and 255 A = tmp and 0xff
} }
Status.C = tmp < 0x100 Status.C = tmp < 0x100
Status.Z = (tmp and 255) == 0 Status.Z = (tmp and 0xff) == 0
Status.N = (tmp and 0b10000000) != 0 Status.N = (tmp and 0b10000000) != 0
Status.V = ((A xor tmp) and 0x80) != 0 && ((A xor operand) and 0x80) != 0
} }
private fun iSec() { private fun iSec() {

@ -0,0 +1 @@
Subproject commit fe99e5616243a1bdbceaf5907390ce4443de7db0

View File

@ -0,0 +1,29 @@
import org.junit.jupiter.api.Test
import sim65.components.Bus
import sim65.components.Cpu6502
import sim65.components.Ram
import kotlin.test.assertEquals
class Test6502Functional {
@Test
fun testFunctional() {
val cpu = Cpu6502(false)
val bus = Bus()
val ram = Ram(0, 0xffff)
ram.load("test/6502_functional_tests/bin_files/6502_functional_test.bin", 0)
bus.add(cpu)
bus.add(ram)
cpu.reset()
cpu.PC = 0x0400
while(cpu.totalCycles < 50000000) {
cpu.clock()
}
cpu.printState()
val d = cpu.disassemble(ram, cpu.PC-20, cpu.PC+20)
println(d.joinToString ("\n"))
}
}

View File

@ -23,18 +23,24 @@ class Test6502TestSuite {
// create the system bus and add device to it. // create the system bus and add device to it.
// note that the order is relevant w.r.t. where reads and writes are going. // note that the order is relevant w.r.t. where reads and writes are going.
ram.set(0x02, 0) ram[0x02] = 0
ram.set(0xa002, 0) ram[0xa002] = 0
ram.set(0xa003, 0x80) ram[0xa003] = 0x80
ram.set(Cpu6502.IRQ_vector, 0x48) ram[Cpu6502.IRQ_vector] = 0x48
ram.set(Cpu6502.IRQ_vector + 1, 0xff) ram[Cpu6502.IRQ_vector + 1] = 0xff
ram.set(Cpu6502.RESET_vector, 0x01) ram[Cpu6502.RESET_vector] = 0x01
ram.set(Cpu6502.RESET_vector + 1, 0x08) ram[Cpu6502.RESET_vector + 1] = 0x08
ram.set(0x01fe, 0xff) ram[0x01fe] = 0xff
ram.set(0x01ff, 0x7f) ram[0x01ff] = 0x7f
ram.set(0x8000, 2) ram[0x8000] = 2
ram.set(0xa474, 2) ram[0xa474] = 2
// setup the irq/brk routine
for(b in listOf(0x48, 0x8A, 0x48, 0x98, 0x48, 0xBA, 0xBD, 0x04,
0x01, 0x29, 0x10, 0xF0, 0x03, 0x6C, 0x16, 0x03,
0x6C, 0x14, 0x03).withIndex()) {
ram[0xff48+b.index] = b.value.toShort()
}
bus.add(cpu) bus.add(cpu)
bus.add(ram) bus.add(ram)
} }
@ -446,11 +452,13 @@ class Test6502TestSuite {
} }
@Test @Test
@Disabled("c64 6510 specific component")
fun testCntdef() { fun testCntdef() {
runTest("cntdef") runTest("cntdef")
} }
@Test @Test
@Disabled("c64 6510 specific component")
fun testCnto2() { fun testCnto2() {
runTest("cnto2") runTest("cnto2")
} }
@ -944,6 +952,7 @@ class Test6502TestSuite {
} }
@Test @Test
@Disabled("c64 specific component")
fun testNmi() { fun testNmi() {
runTest("nmi") runTest("nmi")
} }

View File

@ -1,29 +0,0 @@
* = $8000
sec
lda #$a0
sta $2000
ldx $2000
txa
tay
iny
sty $2001
ldy #0
loop lda text,y
beq end
sta $d000
inc $d001
iny
jmp loop
end nop
bvs loop
.byte $02 ; invalid opcode
.byte $02 ; invalid opcode
.byte $02 ; invalid opcode
text .enc "screen"
.text "hello!",0
.enc "none"