mirror of
https://github.com/irmen/prog8.git
synced 2024-09-06 12:54:36 +00:00
fixed sbc and adc
This commit is contained in:
parent
b400010426
commit
fec8db6a75
@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/sim65/test/6502_functional_tests" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -34,7 +34,7 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
|
||||
fun hexW(number: Address, allowSingleByte: Boolean = false): String {
|
||||
val msb = number ushr 8
|
||||
val lsb = number and 255
|
||||
val lsb = number and 0xff
|
||||
return if (msb == 0 && allowSingleByte)
|
||||
hexB(lsb)
|
||||
else
|
||||
@ -332,20 +332,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
|
||||
private fun amZpx() {
|
||||
// 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() {
|
||||
// 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() {
|
||||
val relative = readPc()
|
||||
fetchedAddress = if (relative >= 0x80)
|
||||
PC - (256 - relative)
|
||||
else
|
||||
PC + relative
|
||||
fetchedAddress = if (relative >= 0x80) {
|
||||
PC - (256 - relative) and 0xffff
|
||||
} else
|
||||
PC + relative and 0xffff
|
||||
}
|
||||
|
||||
private fun amAbs() {
|
||||
@ -386,8 +386,8 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
private fun amIzx() {
|
||||
// note: not able to fetch an adress which crosses the page boundary
|
||||
fetchedAddress = readPc()
|
||||
val lo = read((fetchedAddress + X) and 255)
|
||||
val hi = read((fetchedAddress + X + 1) and 255)
|
||||
val lo = read((fetchedAddress + X) and 0xff)
|
||||
val hi = read((fetchedAddress + X + 1) and 0xff)
|
||||
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
|
||||
fetchedAddress = readPc()
|
||||
val lo = read(fetchedAddress)
|
||||
val hi = read((fetchedAddress + 1) and 255)
|
||||
fetchedAddress = Y + (lo or (hi shl 8)) and 65535
|
||||
val hi = read((fetchedAddress + 1) and 0xff)
|
||||
fetchedAddress = Y + (lo or (hi shl 8)) and 0xffff
|
||||
}
|
||||
|
||||
private fun getFetched(): Int {
|
||||
return if (currentInstruction.mode == AddrMode.Imm ||
|
||||
private fun getFetched() =
|
||||
if (currentInstruction.mode == AddrMode.Imm ||
|
||||
currentInstruction.mode == AddrMode.Acc ||
|
||||
currentInstruction.mode == AddrMode.Imp)
|
||||
fetchedData
|
||||
else
|
||||
read(fetchedAddress)
|
||||
}
|
||||
|
||||
private fun readPc(): Int = bus.read(PC++).toInt()
|
||||
|
||||
private fun pushStackAddr(address: Address) {
|
||||
val lo = address and 255
|
||||
val lo = address and 0xff
|
||||
val hi = (address ushr 8)
|
||||
pushStack(hi)
|
||||
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
|
||||
// (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)
|
||||
if (tmp > 0x9) tmp += 0x6
|
||||
if (tmp > 9) tmp += 6
|
||||
tmp = if (tmp <= 0x0f) {
|
||||
(tmp and 0xf) + (A and 0xf0) + (operand and 0xf0)
|
||||
} else {
|
||||
(tmp and 0xf) + (A and 0xf0) + (operand and 0xf0) + 0x10
|
||||
}
|
||||
Status.Z = ((A + operand + (if (Status.C) 1 else 0)) and 0xff) == 0
|
||||
Status.N = (tmp and 0b10000000) != 0
|
||||
Status.V = ((A xor tmp) and 0x80) != 0 && ((A xor operand) and 0x80) == 0
|
||||
if (tmp > 0x90) tmp += 0x60
|
||||
Status.C = tmp > 0xf0
|
||||
A = tmp and 255
|
||||
Status.Z = A + operand + (if (Status.C) 1 else 0) and 0xff == 0
|
||||
Status.N = tmp and 0b10000000 != 0
|
||||
Status.V = (A xor tmp) and 0x80 != 0 && (A xor operand) and 0b10000000 == 0
|
||||
if (tmp and 0x1f0 > 0x90) tmp += 0x60
|
||||
Status.C = tmp > 0xf0 // original: (tmp and 0xff0) > 0xf0
|
||||
A = tmp and 0xff
|
||||
} else {
|
||||
// normal add
|
||||
val tmp = operand + A + if (Status.C) 1 else 0
|
||||
Status.N = (tmp and 0b10000000) != 0
|
||||
Status.Z = (tmp and 255) == 0
|
||||
Status.V = ((A xor operand) and 0x80) == 0 && ((A xor tmp) and 0x80) != 0
|
||||
Status.C = tmp > 255
|
||||
A = tmp and 255
|
||||
Status.Z = (tmp and 0xff) == 0
|
||||
Status.V = (A xor operand).inv() and (A xor tmp) and 0b10000000 != 0
|
||||
Status.C = tmp > 0xff
|
||||
A = tmp and 0xff
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,13 +748,13 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
private fun iAsl() {
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
Status.C = (A and 0b10000000) != 0
|
||||
A = (A shl 1) and 255
|
||||
A = (A shl 1) and 0xff
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
} else {
|
||||
val data = read(fetchedAddress)
|
||||
Status.C = (data and 0b10000000) != 0
|
||||
val shifted = (data shl 1) and 255
|
||||
val shifted = (data shl 1) and 0xff
|
||||
write(fetchedAddress, shifted)
|
||||
Status.Z = shifted == 0
|
||||
Status.N = (shifted and 0b10000000) != 0
|
||||
@ -848,20 +847,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
}
|
||||
|
||||
private fun iDec() {
|
||||
val data = (read(fetchedAddress) - 1) and 255
|
||||
val data = (read(fetchedAddress) - 1) and 0xff
|
||||
write(fetchedAddress, data)
|
||||
Status.Z = data == 0
|
||||
Status.N = (data and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iDex() {
|
||||
X = (X - 1) and 255
|
||||
X = (X - 1) and 0xff
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iDey() {
|
||||
Y = (Y - 1) and 255
|
||||
Y = (Y - 1) and 0xff
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
@ -873,20 +872,20 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
}
|
||||
|
||||
private fun iInc() {
|
||||
val data = (read(fetchedAddress) + 1) and 255
|
||||
val data = (read(fetchedAddress) + 1) and 0xff
|
||||
write(fetchedAddress, data)
|
||||
Status.Z = data == 0
|
||||
Status.N = (data and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iInx() {
|
||||
X = (X + 1) and 255
|
||||
X = (X + 1) and 0xff
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iIny() {
|
||||
Y = (Y + 1) and 255
|
||||
Y = (Y + 1) and 0xff
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
@ -968,13 +967,13 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
val oldCarry = Status.C
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
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.N = (A and 0b10000000) != 0
|
||||
} else {
|
||||
val data = read(fetchedAddress)
|
||||
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)
|
||||
Status.Z = shifted == 0
|
||||
Status.N = (shifted and 0b10000000) != 0
|
||||
@ -1011,29 +1010,29 @@ class Cpu6502(private val stopOnBrk: Boolean) : BusComponent(), ICpu {
|
||||
|
||||
private fun iSbc() {
|
||||
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) {
|
||||
// BCD subtract
|
||||
// see http://www.6502.org/tutorials/decimal_mode.html
|
||||
// and http://nesdev.com/6502.txt
|
||||
// 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)
|
||||
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 - 6) and 0xf) or (A and 0xf0) - (operand and 0xf0) - 0x10
|
||||
} else {
|
||||
(tmpA and 0xf) or (A and 0xf0) - (operand and 0xf0)
|
||||
}
|
||||
if ((tmpA and 0x100) != 0) tmpA -= 0x60
|
||||
A = tmpA and 255
|
||||
A = tmpA and 0xff
|
||||
} else {
|
||||
// normal subtract
|
||||
A = tmp and 255
|
||||
A = tmp and 0xff
|
||||
}
|
||||
Status.C = tmp < 0x100
|
||||
Status.Z = (tmp and 255) == 0
|
||||
Status.Z = (tmp and 0xff) == 0
|
||||
Status.N = (tmp and 0b10000000) != 0
|
||||
Status.V = ((A xor tmp) and 0x80) != 0 && ((A xor operand) and 0x80) != 0
|
||||
}
|
||||
|
||||
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.
|
||||
// note that the order is relevant w.r.t. where reads and writes are going.
|
||||
ram.set(0x02, 0)
|
||||
ram.set(0xa002, 0)
|
||||
ram.set(0xa003, 0x80)
|
||||
ram.set(Cpu6502.IRQ_vector, 0x48)
|
||||
ram.set(Cpu6502.IRQ_vector + 1, 0xff)
|
||||
ram.set(Cpu6502.RESET_vector, 0x01)
|
||||
ram.set(Cpu6502.RESET_vector + 1, 0x08)
|
||||
ram.set(0x01fe, 0xff)
|
||||
ram.set(0x01ff, 0x7f)
|
||||
ram.set(0x8000, 2)
|
||||
ram.set(0xa474, 2)
|
||||
ram[0x02] = 0
|
||||
ram[0xa002] = 0
|
||||
ram[0xa003] = 0x80
|
||||
ram[Cpu6502.IRQ_vector] = 0x48
|
||||
ram[Cpu6502.IRQ_vector + 1] = 0xff
|
||||
ram[Cpu6502.RESET_vector] = 0x01
|
||||
ram[Cpu6502.RESET_vector + 1] = 0x08
|
||||
ram[0x01fe] = 0xff
|
||||
ram[0x01ff] = 0x7f
|
||||
ram[0x8000] = 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(ram)
|
||||
}
|
||||
@ -446,11 +452,13 @@ class Test6502TestSuite {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("c64 6510 specific component")
|
||||
fun testCntdef() {
|
||||
runTest("cntdef")
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("c64 6510 specific component")
|
||||
fun testCnto2() {
|
||||
runTest("cnto2")
|
||||
}
|
||||
@ -944,6 +952,7 @@ class Test6502TestSuite {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("c64 specific component")
|
||||
fun testNmi() {
|
||||
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…
Reference in New Issue
Block a user