mirror of
https://github.com/irmen/prog8.git
synced 2025-02-18 05:30:34 +00:00
fixed sbc and adc
This commit is contained in:
parent
b400010426
commit
fec8db6a75
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@ -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>
|
@ -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() {
|
||||||
|
1
sim65/test/6502_functional_tests
Submodule
1
sim65/test/6502_functional_tests
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit fe99e5616243a1bdbceaf5907390ce4443de7db0
|
29
sim65/test/Test6502Functional.kt
Normal file
29
sim65/test/Test6502Functional.kt
Normal 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"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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"
|
|
Loading…
x
Reference in New Issue
Block a user