mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
fixed all instructions except BCD arithmetic
This commit is contained in:
parent
42f8e98cab
commit
900c2aea23
@ -17,8 +17,7 @@ interface ICpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add additional cycles to certain instructions and addressing modes
|
// TODO: add additional cycles to certain instructions and addressing modes
|
||||||
// TODO: test all opcodes and fix bugs
|
// TODO: fix sbc and adc with BCD arithmetic.
|
||||||
|
|
||||||
|
|
||||||
class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu {
|
class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu {
|
||||||
override var tracing: Boolean = false
|
override var tracing: Boolean = false
|
||||||
@ -29,6 +28,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
const val NMI_vector = 0xfffa
|
const val NMI_vector = 0xfffa
|
||||||
const val RESET_vector = 0xfffc
|
const val RESET_vector = 0xfffc
|
||||||
const val IRQ_vector = 0xfffe
|
const val IRQ_vector = 0xfffe
|
||||||
|
const val resetCycles = 8
|
||||||
|
|
||||||
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
|
||||||
@ -241,12 +241,12 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
Y = 0
|
Y = 0
|
||||||
Status.C = false
|
Status.C = false
|
||||||
Status.Z = false
|
Status.Z = false
|
||||||
Status.I = false
|
Status.I = true
|
||||||
Status.D = false
|
Status.D = false
|
||||||
Status.B = false
|
Status.B = false
|
||||||
Status.V = false
|
Status.V = false
|
||||||
Status.N = false
|
Status.N = false
|
||||||
instrCycles = 8
|
instrCycles = resetCycles // a reset takes time as well
|
||||||
currentOpcode = 0
|
currentOpcode = 0
|
||||||
currentInstruction = opcodes[0]
|
currentInstruction = opcodes[0]
|
||||||
waiting = false
|
waiting = false
|
||||||
@ -276,8 +276,9 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
|
|
||||||
override fun step() {
|
override fun step() {
|
||||||
// step a whole instruction
|
// step a whole instruction
|
||||||
while(instrCycles>0) clock() // instruction subcycles
|
while(instrCycles>0) clock() // remaining instruction subcycles from the previous instruction
|
||||||
clock() // the actual instruction execution cycle
|
clock() // the actual instruction execution cycle
|
||||||
|
while(instrCycles>0) clock() // instruction subcycles
|
||||||
}
|
}
|
||||||
|
|
||||||
fun printState() {
|
fun printState() {
|
||||||
@ -324,7 +325,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun amRel() {
|
private fun amRel() {
|
||||||
val relative = readPc().toByte()
|
val relative = readPc()
|
||||||
fetchedAddress = if (relative >= 0x80)
|
fetchedAddress = if (relative >= 0x80)
|
||||||
PC - (256 - relative)
|
PC - (256 - relative)
|
||||||
else
|
else
|
||||||
@ -368,9 +369,9 @@ class Cpu6502(private val illegalInstrsAllowed: 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() + X
|
fetchedAddress = readPc()
|
||||||
val lo = read(fetchedAddress)
|
val lo = read((fetchedAddress + X) and 255)
|
||||||
val hi = read((fetchedAddress + 1) and 255)
|
val hi = read((fetchedAddress + X + 1) and 255)
|
||||||
fetchedAddress = lo or (hi shl 8)
|
fetchedAddress = lo or (hi shl 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +380,16 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
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 255)
|
||||||
fetchedAddress = Y + (lo or (hi shl 8))
|
fetchedAddress = (Y + lo or (hi shl 8)) and 65535
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getFetched(): Int {
|
||||||
|
return 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 readPc(): Int = bus.read(PC++).toInt()
|
||||||
@ -408,7 +418,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
private fun popStackAddr(): Address {
|
private fun popStackAddr(): Address {
|
||||||
val lo = popStack()
|
val lo = popStack()
|
||||||
val hi = popStack()
|
val hi = popStack()
|
||||||
return lo + hi ushr 8
|
return lo or (hi shl 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun read(address: Address): Int = bus.read(address).toInt()
|
private fun read(address: Address): Int = bus.read(address).toInt()
|
||||||
@ -683,11 +693,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
// official instructions
|
// official instructions
|
||||||
|
|
||||||
private fun iAdc() {
|
private fun iAdc() {
|
||||||
val operand = if (currentInstruction.mode == AddrMode.Imm) {
|
val operand = getFetched()
|
||||||
fetchedData
|
|
||||||
} else {
|
|
||||||
read(fetchedAddress)
|
|
||||||
}
|
|
||||||
if (Status.D) {
|
if (Status.D) {
|
||||||
// BCD add
|
// BCD add
|
||||||
var lo = (A and 0x0f) + (operand and 0x0f) + if (Status.C) 1 else 0
|
var lo = (A and 0x0f) + (operand and 0x0f) + if (Status.C) 1 else 0
|
||||||
@ -712,24 +718,24 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iAnd() {
|
private fun iAnd() {
|
||||||
A = A and fetchedData
|
A = A and getFetched()
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) != 0
|
Status.N = (A and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iAsl() {
|
private fun iAsl() {
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
Status.C = (A and 0b10000000) == 1
|
Status.C = (A and 0b10000000) != 0
|
||||||
A = (A shl 1) and 255
|
A = (A shl 1) and 255
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
} else {
|
} else {
|
||||||
val data = read(fetchedAddress)
|
val data = read(fetchedAddress)
|
||||||
Status.C = (data and 0b10000000) == 1
|
Status.C = (data and 0b10000000) != 0
|
||||||
val shifted = (data shl 1) and 255
|
val shifted = (data shl 1) and 255
|
||||||
write(fetchedAddress, shifted)
|
write(fetchedAddress, shifted)
|
||||||
Status.Z = shifted == 0
|
Status.Z = shifted == 0
|
||||||
Status.N = (shifted and 0b10000000) == 1
|
Status.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -746,9 +752,10 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iBit() {
|
private fun iBit() {
|
||||||
Status.Z = (A and fetchedData) == 0
|
val operand = getFetched()
|
||||||
Status.V = (fetchedData and 0b01000000) != 0
|
Status.Z = (A and operand) == 0
|
||||||
Status.N = (fetchedData and 0b10000000) != 0
|
Status.V = (operand and 0b01000000) != 0
|
||||||
|
Status.N = (operand and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBmi() {
|
private fun iBmi() {
|
||||||
@ -765,11 +772,10 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
|
|
||||||
private fun iBrk() {
|
private fun iBrk() {
|
||||||
PC++
|
PC++
|
||||||
Status.I = true
|
|
||||||
Status.B = true
|
|
||||||
pushStackAddr(PC)
|
pushStackAddr(PC)
|
||||||
|
Status.B = true
|
||||||
pushStack(Status)
|
pushStack(Status)
|
||||||
Status.B = false
|
Status.I = true
|
||||||
PC = readWord(IRQ_vector)
|
PC = readWord(IRQ_vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,87 +804,68 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iCmp() {
|
private fun iCmp() {
|
||||||
val fetched =
|
val fetched = getFetched()
|
||||||
if (currentInstruction.mode == AddrMode.Imm) {
|
|
||||||
fetchedData
|
|
||||||
} else {
|
|
||||||
read(fetchedAddress)
|
|
||||||
}
|
|
||||||
Status.C = A >= fetched
|
Status.C = A >= fetched
|
||||||
Status.Z = A == fetched
|
Status.Z = A == fetched
|
||||||
Status.N = ((A - fetched) and 0b10000000) == 1
|
Status.N = ((A - fetched) and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iCpx() {
|
private fun iCpx() {
|
||||||
val fetched =
|
val fetched = getFetched()
|
||||||
if (currentInstruction.mode == AddrMode.Imm) {
|
|
||||||
fetchedData
|
|
||||||
} else {
|
|
||||||
read(fetchedAddress)
|
|
||||||
}
|
|
||||||
Status.C = X >= fetched
|
Status.C = X >= fetched
|
||||||
Status.Z = X == fetched
|
Status.Z = X == fetched
|
||||||
Status.N = ((X - fetched) and 0b10000000) == 1
|
Status.N = ((X - fetched) and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iCpy() {
|
private fun iCpy() {
|
||||||
val fetched =
|
val fetched = getFetched()
|
||||||
if (currentInstruction.mode == AddrMode.Imm) {
|
|
||||||
fetchedData
|
|
||||||
} else {
|
|
||||||
read(fetchedAddress)
|
|
||||||
}
|
|
||||||
Status.C = Y >= fetched
|
Status.C = Y >= fetched
|
||||||
Status.Z = Y == fetched
|
Status.Z = Y == fetched
|
||||||
Status.N = ((Y - fetched) and 0b10000000) == 1
|
Status.N = ((Y - fetched) and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iDec() {
|
private fun iDec() {
|
||||||
val data = (read(fetchedAddress) - 1) and 255
|
val data = (read(fetchedAddress) - 1) and 255
|
||||||
write(fetchedAddress, data)
|
write(fetchedAddress, data)
|
||||||
Status.Z = data == 0
|
Status.Z = data == 0
|
||||||
Status.N = (data and 0b10000000) == 1
|
Status.N = (data and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iDex() {
|
private fun iDex() {
|
||||||
X = (X - 1) and 255
|
X = (X - 1) and 255
|
||||||
Status.Z = X == 0
|
Status.Z = X == 0
|
||||||
Status.N = (X and 0b10000000) == 1
|
Status.N = (X and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iDey() {
|
private fun iDey() {
|
||||||
Y = (Y - 1) and 255
|
Y = (Y - 1) and 255
|
||||||
Status.Z = Y == 0
|
Status.Z = Y == 0
|
||||||
Status.N = (Y and 0b10000000) == 1
|
Status.N = (Y and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iEor() {
|
private fun iEor() {
|
||||||
A = if (currentInstruction.mode == AddrMode.Imm) {
|
A = A xor getFetched()
|
||||||
A xor fetchedData
|
|
||||||
} else {
|
|
||||||
A xor read(fetchedAddress)
|
|
||||||
}
|
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iInc() {
|
private fun iInc() {
|
||||||
val data = (read(fetchedAddress) + 1) and 255
|
val data = (read(fetchedAddress) + 1) and 255
|
||||||
write(fetchedAddress, data)
|
write(fetchedAddress, data)
|
||||||
Status.Z = data == 0
|
Status.Z = data == 0
|
||||||
Status.N = (data and 0b10000000) == 1
|
Status.N = (data and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iInx() {
|
private fun iInx() {
|
||||||
X = (X + 1) and 255
|
X = (X + 1) and 255
|
||||||
Status.Z = X == 0
|
Status.Z = X == 0
|
||||||
Status.N = (X and 0b10000000) == 1
|
Status.N = (X and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iIny() {
|
private fun iIny() {
|
||||||
Y = (Y + 1) and 255
|
Y = (Y + 1) and 255
|
||||||
Status.Z = Y == 0
|
Status.Z = Y == 0
|
||||||
Status.N = (Y and 0b10000000) == 1
|
Status.N = (Y and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iJmp() {
|
private fun iJmp() {
|
||||||
@ -886,35 +873,26 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iJsr() {
|
private fun iJsr() {
|
||||||
pushStackAddr(PC)
|
pushStackAddr(PC-1)
|
||||||
PC = fetchedAddress
|
PC = fetchedAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iLda() {
|
private fun iLda() {
|
||||||
A = if (currentInstruction.mode == AddrMode.Imm)
|
A = getFetched()
|
||||||
fetchedData
|
|
||||||
else
|
|
||||||
read(fetchedAddress)
|
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iLdx() {
|
private fun iLdx() {
|
||||||
X = if (currentInstruction.mode == AddrMode.Imm)
|
X = getFetched()
|
||||||
fetchedData
|
|
||||||
else
|
|
||||||
read(fetchedAddress)
|
|
||||||
Status.Z = X == 0
|
Status.Z = X == 0
|
||||||
Status.N = (X and 0b10000000) == 1
|
Status.N = (X and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iLdy() {
|
private fun iLdy() {
|
||||||
Y = if (currentInstruction.mode == AddrMode.Imm)
|
Y = getFetched()
|
||||||
fetchedData
|
|
||||||
else
|
|
||||||
read(fetchedAddress)
|
|
||||||
Status.Z = Y == 0
|
Status.Z = Y == 0
|
||||||
Status.N = (Y and 0b10000000) == 1
|
Status.N = (Y and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iLsr() {
|
private fun iLsr() {
|
||||||
@ -922,26 +900,23 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
Status.C = (A and 1) == 1
|
Status.C = (A and 1) == 1
|
||||||
A = A ushr 1
|
A = A ushr 1
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
} else {
|
} else {
|
||||||
val data = read(fetchedAddress)
|
val data = read(fetchedAddress)
|
||||||
Status.C = (data and 1) == 1
|
Status.C = (data and 1) == 1
|
||||||
val shifted = data ushr 1
|
val shifted = data ushr 1
|
||||||
write(fetchedAddress, shifted)
|
write(fetchedAddress, shifted)
|
||||||
Status.Z = shifted == 0
|
Status.Z = shifted == 0
|
||||||
Status.N = (shifted and 0b10000000) == 1
|
Status.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iNop() {}
|
private fun iNop() {}
|
||||||
|
|
||||||
private fun iOra() {
|
private fun iOra() {
|
||||||
A = if (currentInstruction.mode == AddrMode.Imm)
|
A = A or getFetched()
|
||||||
A or fetchedData
|
|
||||||
else
|
|
||||||
A or read(fetchedAddress)
|
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPha() {
|
private fun iPha() {
|
||||||
@ -949,33 +924,37 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iPhp() {
|
private fun iPhp() {
|
||||||
|
val origBreakflag = Status.B
|
||||||
|
Status.B = true
|
||||||
pushStack(Status)
|
pushStack(Status)
|
||||||
|
Status.B = origBreakflag
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPla() {
|
private fun iPla() {
|
||||||
A = popStack()
|
A = popStack()
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPlp() {
|
private fun iPlp() {
|
||||||
Status.fromByte(popStack())
|
Status.fromByte(popStack())
|
||||||
|
Status.B = true // break is always 1 except when pushing on stack
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRol() {
|
private fun iRol() {
|
||||||
val oldCarry = Status.C
|
val oldCarry = Status.C
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
Status.C = (A and 0b10000000) == 1
|
Status.C = (A and 0b10000000) != 0
|
||||||
A = (A shl 1) or (if (oldCarry) 1 else 0)
|
A = (A shl 1 and 255) or (if (oldCarry) 1 else 0)
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
} else {
|
} else {
|
||||||
val data = read(fetchedAddress)
|
val data = read(fetchedAddress)
|
||||||
Status.C = (data and 0b10000000) == 1
|
Status.C = (data and 0b10000000) != 0
|
||||||
val shifted = (data shl 1) or (if (oldCarry) 1 else 0) and 255
|
val shifted = (data shl 1 and 255) 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) == 1
|
Status.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -985,38 +964,36 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
Status.C = (A and 1) == 1
|
Status.C = (A and 1) == 1
|
||||||
A = (A ushr 1) or (if (oldCarry) 0b10000000 else 0)
|
A = (A ushr 1) or (if (oldCarry) 0b10000000 else 0)
|
||||||
Status.Z = A == 0
|
Status.Z = A == 0
|
||||||
Status.N = (A and 0b10000000) == 1
|
Status.N = (A and 0b10000000) != 0
|
||||||
} else {
|
} else {
|
||||||
val data = read(fetchedAddress)
|
val data = read(fetchedAddress)
|
||||||
Status.C = (data and 1) == 1
|
Status.C = (data and 1) == 1
|
||||||
val shifted = (data ushr 1) or (if (oldCarry) 0b10000000 else 0)
|
val shifted = (data ushr 1) or (if (oldCarry) 0b10000000 else 0)
|
||||||
write(fetchedAddress, shifted)
|
write(fetchedAddress, shifted)
|
||||||
Status.Z = shifted == 0
|
Status.Z = shifted == 0
|
||||||
Status.N = (shifted and 0b10000000) == 1
|
Status.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRti() {
|
private fun iRti() {
|
||||||
Status.fromByte(popStack())
|
Status.fromByte(popStack())
|
||||||
|
Status.B = true // break is always 1 except when pushing on stack
|
||||||
PC = popStackAddr()
|
PC = popStackAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRts() {
|
private fun iRts() {
|
||||||
PC = popStackAddr()
|
PC = popStackAddr()
|
||||||
|
PC = (PC+1) and 0xffff
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSbc() {
|
private fun iSbc() {
|
||||||
val operand = if (currentInstruction.mode == AddrMode.Imm) {
|
val operand = getFetched()
|
||||||
fetchedData
|
|
||||||
} else {
|
|
||||||
read(fetchedAddress)
|
|
||||||
}
|
|
||||||
if (Status.D) {
|
if (Status.D) {
|
||||||
var lo = (A and 0x0f) - (operand and 0x0f) - if (Status.C) 0 else 1
|
var lo = (A and 0x0f) - (operand and 0x0f) - if (Status.C) 0 else 1
|
||||||
if (lo and 0x10 != 0) lo -= 6
|
if (lo and 0x10 != 0) lo -= 6
|
||||||
var h = (A shr 4) - (operand shr 4) - if (lo and 0x10 != 0) 1 else 0
|
var h = (A shr 4) - (operand shr 4) - if (lo and 0x10 != 0) 1 else 0
|
||||||
if (h and 0x10 != 0) h -= 6
|
if (h and 0x10 != 0) h -= 6
|
||||||
val result = lo and 0x0f or (h shl 4 and 0xff)
|
val result = lo and 0x0f or ((h shl 4) and 0xff)
|
||||||
Status.C = h and 255 < 15
|
Status.C = h and 255 < 15
|
||||||
Status.Z = result == 0
|
Status.Z = result == 0
|
||||||
Status.V = false // BCD never sets overflow flag
|
Status.V = false // BCD never sets overflow flag
|
||||||
@ -1071,7 +1048,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iTsx() {
|
private fun iTsx() {
|
||||||
X = Status.asByte().toInt()
|
X = SP
|
||||||
Status.Z = X == 0
|
Status.Z = X == 0
|
||||||
Status.N = (X and 0b10000000) != 0
|
Status.N = (X and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
@ -1083,7 +1060,7 @@ class Cpu6502(private val illegalInstrsAllowed: Boolean) : BusComponent(), ICpu
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun iTxs() {
|
private fun iTxs() {
|
||||||
Status.fromByte(X)
|
SP = X
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iTya() {
|
private fun iTya() {
|
||||||
|
@ -20,6 +20,10 @@ class Ram(startAddress: Address, endAddress: Address): MemMappedComponent(startA
|
|||||||
|
|
||||||
override fun reset() { memory.fill(0) }
|
override fun reset() { memory.fill(0) }
|
||||||
|
|
||||||
|
fun fill(data: UByte) {
|
||||||
|
memory.fill(data)
|
||||||
|
}
|
||||||
|
|
||||||
fun load(filename: String, address: Address) {
|
fun load(filename: String, address: Address) {
|
||||||
val bytes = File(filename).readBytes()
|
val bytes = File(filename).readBytes()
|
||||||
bytes.forEachIndexed { index, byte ->
|
bytes.forEachIndexed { index, byte ->
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInstance
|
import org.junit.jupiter.api.TestInstance
|
||||||
|
import sim65.components.Cpu6502
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
|
||||||
@ -274,7 +275,7 @@ class Test6502 : TestCommon6502() {
|
|||||||
writeMem(memory, 0, listOf(0x6c, 0xff, 0x00))
|
writeMem(memory, 0, listOf(0x6c, 0xff, 0x00))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x6c00, mpu.PC)
|
assertEquals(0x6c00, mpu.PC)
|
||||||
assertEquals(5, mpu.totalCycles)
|
assertEquals(5+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ORA Indexed, Indirect (Y)
|
// ORA Indexed, Indirect (Y)
|
||||||
|
@ -52,7 +52,11 @@ abstract class TestCommon6502 {
|
|||||||
init {
|
init {
|
||||||
bus.add(mpu)
|
bus.add(mpu)
|
||||||
bus.add(memory)
|
bus.add(memory)
|
||||||
|
memory.fill(0xaa)
|
||||||
|
memory.write(Cpu6502.RESET_vector, 0)
|
||||||
|
memory.write(Cpu6502.RESET_vector+1, 0)
|
||||||
mpu.reset()
|
mpu.reset()
|
||||||
|
mpu.Status.I = false // allow interrupts again
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -79,11 +83,11 @@ abstract class TestCommon6502 {
|
|||||||
fun test_reset_sets_registers_to_initial_states() {
|
fun test_reset_sets_registers_to_initial_states() {
|
||||||
|
|
||||||
mpu.reset()
|
mpu.reset()
|
||||||
assertEquals(0xFF, mpu.SP)
|
assertEquals(0xFD, mpu.SP)
|
||||||
assertEquals(0, mpu.A)
|
assertEquals(0, mpu.A)
|
||||||
assertEquals(0, mpu.X)
|
assertEquals(0, mpu.X)
|
||||||
assertEquals(0, mpu.Y)
|
assertEquals(0, mpu.Y)
|
||||||
assertEquals(Cpu6502.StatusRegister(C = false, Z = false, I = false, D = false, B = true, V = false, N = false), mpu.Status)
|
assertTrue(mpu.Status.I) // the other status flags are undefined after reset
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADC Absolute
|
// ADC Absolute
|
||||||
@ -1339,11 +1343,10 @@ abstract class TestCommon6502 {
|
|||||||
assertTrue(mpu.Status.N)
|
assertTrue(mpu.Status.N)
|
||||||
assertTrue(mpu.Status.V)
|
assertTrue(mpu.Status.V)
|
||||||
assertFalse(mpu.Status.Z)
|
assertFalse(mpu.Status.Z)
|
||||||
|
}
|
||||||
|
|
||||||
// AND (Absolute)
|
// AND (Absolute)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_and_absolute_all_zeros_setting_zero_flag() {
|
fun test_and_absolute_all_zeros_setting_zero_flag() {
|
||||||
|
|
||||||
@ -1371,11 +1374,10 @@ abstract class TestCommon6502 {
|
|||||||
assertEquals(0xAA, mpu.A)
|
assertEquals(0xAA, mpu.A)
|
||||||
assertTrue(mpu.Status.N)
|
assertTrue(mpu.Status.N)
|
||||||
assertFalse(mpu.Status.Z)
|
assertFalse(mpu.Status.Z)
|
||||||
|
}
|
||||||
|
|
||||||
// AND (Absolute)
|
// AND (Absolute)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_and_zp_all_zeros_setting_zero_flag() {
|
fun test_and_zp_all_zeros_setting_zero_flag() {
|
||||||
|
|
||||||
@ -1490,7 +1492,6 @@ abstract class TestCommon6502 {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_and_abs_y_zeros_and_ones_setting_negative_flag() {
|
fun test_and_abs_y_zeros_and_ones_setting_negative_flag() {
|
||||||
|
|
||||||
mpu.A = 0xFF
|
mpu.A = 0xFF
|
||||||
mpu.Y = 0x03
|
mpu.Y = 0x03
|
||||||
// $0000 AND $ABCD,X
|
// $0000 AND $ABCD,X
|
||||||
@ -1501,11 +1502,10 @@ abstract class TestCommon6502 {
|
|||||||
assertEquals(0xAA, mpu.A)
|
assertEquals(0xAA, mpu.A)
|
||||||
assertTrue(mpu.Status.N)
|
assertTrue(mpu.Status.N)
|
||||||
assertFalse(mpu.Status.Z)
|
assertFalse(mpu.Status.Z)
|
||||||
|
}
|
||||||
|
|
||||||
// AND Indirect, Indexed (X)
|
// AND Indirect, Indexed (X)
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_and_ind_indexed_x_all_zeros_setting_zero_flag() {
|
fun test_and_ind_indexed_x_all_zeros_setting_zero_flag() {
|
||||||
|
|
||||||
@ -1950,11 +1950,11 @@ abstract class TestCommon6502 {
|
|||||||
|
|
||||||
mpu.Status.C = false
|
mpu.Status.C = false
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
// $0000 BCC -6
|
// $0000 BCC -6
|
||||||
writeMem(memory, 0x0050, listOf(0x90, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0x90, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1987,11 +1987,11 @@ abstract class TestCommon6502 {
|
|||||||
|
|
||||||
mpu.Status.C = true
|
mpu.Status.C = true
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
// $0000 BCS -6
|
// $0000 BCS -6
|
||||||
writeMem(memory, 0x0050, listOf(0xB0, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0xB0, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2024,11 +2024,11 @@ abstract class TestCommon6502 {
|
|||||||
|
|
||||||
mpu.Status.Z = true
|
mpu.Status.Z = true
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
// $0000 BEQ -6
|
// $0000 BEQ -6
|
||||||
writeMem(memory, 0x0050, listOf(0xF0, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0xF0, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2154,7 +2154,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0xFF
|
mpu.A = 0xFF
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertTrue(mpu.Status.N)
|
assertTrue(mpu.Status.N)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2169,7 +2169,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0xFF
|
mpu.A = 0xFF
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertFalse(mpu.Status.N)
|
assertFalse(mpu.Status.N)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2184,7 +2184,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0xFF
|
mpu.A = 0xFF
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertTrue(mpu.Status.V)
|
assertTrue(mpu.Status.V)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2199,7 +2199,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0xFF
|
mpu.A = 0xFF
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertFalse(mpu.Status.V)
|
assertFalse(mpu.Status.V)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -2214,7 +2214,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0x01
|
mpu.A = 0x01
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertTrue(mpu.Status.Z)
|
assertTrue(mpu.Status.Z)
|
||||||
assertEquals(0x01, mpu.A)
|
assertEquals(0x01, mpu.A)
|
||||||
assertEquals(0x00, memory[0x0010])
|
assertEquals(0x00, memory[0x0010])
|
||||||
@ -2231,7 +2231,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0x01
|
mpu.A = 0x01
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertFalse(mpu.Status.Z) // result of AND is non-zero
|
assertFalse(mpu.Status.Z) // result of AND is non-zero
|
||||||
assertEquals(0x01, mpu.A)
|
assertEquals(0x01, mpu.A)
|
||||||
assertEquals(0x01, memory[0x0010])
|
assertEquals(0x01, memory[0x0010])
|
||||||
@ -2248,7 +2248,7 @@ abstract class TestCommon6502 {
|
|||||||
mpu.A = 0x01
|
mpu.A = 0x01
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0002, mpu.PC)
|
assertEquals(0x0002, mpu.PC)
|
||||||
assertEquals(3, mpu.totalCycles)
|
assertEquals(3+Cpu6502.resetCycles, mpu.totalCycles)
|
||||||
assertTrue(mpu.Status.Z) // result of AND is zero
|
assertTrue(mpu.Status.Z) // result of AND is zero
|
||||||
assertEquals(0x01, mpu.A)
|
assertEquals(0x01, mpu.A)
|
||||||
assertEquals(0x00, memory[0x0010])
|
assertEquals(0x00, memory[0x0010])
|
||||||
@ -2274,10 +2274,10 @@ abstract class TestCommon6502 {
|
|||||||
mpu.Status.N = true
|
mpu.Status.N = true
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
// $0000 BMI -6
|
// $0000 BMI -6
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
writeMem(memory, 0x0050, listOf(0x30, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0x30, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2311,10 +2311,10 @@ abstract class TestCommon6502 {
|
|||||||
mpu.Status.Z = false
|
mpu.Status.Z = false
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
// $0050 BNE -6
|
// $0050 BNE -6
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
writeMem(memory, 0x0050, listOf(0xD0, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0xD0, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2348,10 +2348,10 @@ abstract class TestCommon6502 {
|
|||||||
mpu.Status.N = false
|
mpu.Status.N = false
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
// $0050 BPL -6
|
// $0050 BPL -6
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
writeMem(memory, 0x0050, listOf(0x10, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0x10, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2372,17 +2372,19 @@ abstract class TestCommon6502 {
|
|||||||
fun test_brk_pushes_pc_plus_2_and_status_then_sets_pc_to_irq_vector() {
|
fun test_brk_pushes_pc_plus_2_and_status_then_sets_pc_to_irq_vector() {
|
||||||
|
|
||||||
writeMem(memory, 0xFFFE, listOf(0xCD, 0xAB))
|
writeMem(memory, 0xFFFE, listOf(0xCD, 0xAB))
|
||||||
|
mpu.SP = 0xff
|
||||||
|
mpu.Status.I = false
|
||||||
|
|
||||||
// $C000 BRK
|
// $C000 BRK
|
||||||
memory[0xC000] = 0x00
|
memory[0xC000] = 0x00
|
||||||
mpu.PC = 0xC000
|
mpu.PC = 0xC000
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0xABCD, mpu.PC)
|
assertEquals(0xABCD, mpu.PC)
|
||||||
|
|
||||||
|
assertEquals(0xFC, mpu.SP)
|
||||||
assertEquals(0xC0, memory[0x1FF]) // PCH
|
assertEquals(0xC0, memory[0x1FF]) // PCH
|
||||||
assertEquals(0x02, memory[0x1FE]) // PCL
|
assertEquals(0x02, memory[0x1FE]) // PCL
|
||||||
assertEquals(fBREAK or fUNUSED, memory[0x1FD].toInt()) // Status
|
assertEquals(fBREAK or fUNUSED, memory[0x1FD].toInt(), "Status on stack should have no I flag")
|
||||||
assertEquals(0xFC, mpu.SP)
|
|
||||||
|
|
||||||
assertEquals(fBREAK or fUNUSED or fINTERRUPT, mpu.Status.asByte().toInt())
|
assertEquals(fBREAK or fUNUSED or fINTERRUPT, mpu.Status.asByte().toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2401,11 +2403,11 @@ abstract class TestCommon6502 {
|
|||||||
fun test_bvc_overflow_clear_branches_relative_backward() {
|
fun test_bvc_overflow_clear_branches_relative_backward() {
|
||||||
mpu.Status.V = false
|
mpu.Status.V = false
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
// $0050 BVC -6
|
// $0050 BVC -6
|
||||||
writeMem(memory, 0x0050, listOf(0x50, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0x50, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -2433,11 +2435,11 @@ abstract class TestCommon6502 {
|
|||||||
|
|
||||||
mpu.Status.V = true
|
mpu.Status.V = true
|
||||||
mpu.PC = 0x0050
|
mpu.PC = 0x0050
|
||||||
val rel = (0x06 xor 0xFF + 1) // two's complement of 6
|
val rel = 256 + (-6) // two's complement of 6
|
||||||
// $0050 BVS -6
|
// $0050 BVS -6
|
||||||
writeMem(memory, 0x0050, listOf(0x70, rel.toShort()))
|
writeMem(memory, 0x0050, listOf(0x70, rel.toShort()))
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0052 + rel, mpu.PC)
|
assertEquals(0x0052 - 6, mpu.PC)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3332,18 +3334,16 @@ abstract class TestCommon6502 {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_inx_sets_negative_flag_when_incrementing_above_7F() {
|
fun test_inx_sets_negative_flag_when_incrementing_above_7F() {
|
||||||
|
|
||||||
mpu.X = 0x7f
|
mpu.X = 0x7f
|
||||||
memory[0x0000] = 0xE8 // => INX
|
memory[0x0000] = 0xE8 // => INX
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0001, mpu.PC)
|
assertEquals(0x0001, mpu.PC)
|
||||||
assertEquals(0x80, mpu.X)
|
assertEquals(0x80, mpu.X)
|
||||||
assertTrue(mpu.Status.N)
|
assertTrue(mpu.Status.N)
|
||||||
|
}
|
||||||
|
|
||||||
// INY
|
// INY
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_iny_increments_y() {
|
fun test_iny_increments_y() {
|
||||||
|
|
||||||
@ -3354,7 +3354,6 @@ abstract class TestCommon6502 {
|
|||||||
assertEquals(0x0A, mpu.Y)
|
assertEquals(0x0A, mpu.Y)
|
||||||
assertFalse(mpu.Status.Z)
|
assertFalse(mpu.Status.Z)
|
||||||
assertFalse(mpu.Status.N)
|
assertFalse(mpu.Status.N)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -3412,6 +3411,7 @@ abstract class TestCommon6502 {
|
|||||||
fun test_jsr_pushes_pc_plus_2_and_sets_pc() {
|
fun test_jsr_pushes_pc_plus_2_and_sets_pc() {
|
||||||
|
|
||||||
// $C000 JSR $FFD2
|
// $C000 JSR $FFD2
|
||||||
|
mpu.SP = 0xFF
|
||||||
writeMem(memory, 0xC000, listOf(0x20, 0xD2, 0xFF))
|
writeMem(memory, 0xC000, listOf(0x20, 0xD2, 0xFF))
|
||||||
mpu.PC = 0xC000
|
mpu.PC = 0xC000
|
||||||
mpu.step()
|
mpu.step()
|
||||||
@ -3419,11 +3419,10 @@ abstract class TestCommon6502 {
|
|||||||
assertEquals(0xFD, mpu.SP)
|
assertEquals(0xFD, mpu.SP)
|
||||||
assertEquals(0xC0, memory[0x01FF]) // PCH
|
assertEquals(0xC0, memory[0x01FF]) // PCH
|
||||||
assertEquals(0x02, memory[0x01FE]) // PCL+2
|
assertEquals(0x02, memory[0x01FE]) // PCL+2
|
||||||
|
}
|
||||||
|
|
||||||
// LDA Absolute
|
// LDA Absolute
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_lda_absolute_loads_a_sets_n_flag() {
|
fun test_lda_absolute_loads_a_sets_n_flag() {
|
||||||
|
|
||||||
@ -4604,21 +4603,22 @@ abstract class TestCommon6502 {
|
|||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0001, mpu.PC)
|
assertEquals(0x0001, mpu.PC)
|
||||||
assertEquals(0xAB, mpu.A)
|
assertEquals(0xAB, mpu.A)
|
||||||
assertEquals(0xAB, memory[0x01FF])
|
assertEquals(0xFC, mpu.SP)
|
||||||
assertEquals(0xFE, mpu.SP)
|
assertEquals(0xAB, memory[0x01FD])
|
||||||
}
|
}
|
||||||
|
|
||||||
// PHP
|
// PHP
|
||||||
@Test
|
@Test
|
||||||
fun test_php_pushes_processor_status_and_updates_sp() {
|
fun test_php_pushes_processor_status_and_updates_sp() {
|
||||||
for (flags in 0 until 0x100) {
|
for (flags in 0 until 0x100) {
|
||||||
|
mpu.reset()
|
||||||
mpu.Status.fromByte(flags or fBREAK or fUNUSED)
|
mpu.Status.fromByte(flags or fBREAK or fUNUSED)
|
||||||
// $0000 PHP
|
// $0000 PHP
|
||||||
memory[0x0000] = 0x08
|
memory[0x0000] = 0x08
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0x0001, mpu.PC)
|
assertEquals(0x0001, mpu.PC)
|
||||||
assertEquals((flags or fBREAK or fUNUSED), memory[0x1FF].toInt())
|
assertEquals(0xFC, mpu.SP)
|
||||||
assertEquals(0xFE, mpu.SP)
|
assertEquals((flags or fBREAK or fUNUSED), memory[0x1FD].toInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -4684,7 +4684,6 @@ abstract class TestCommon6502 {
|
|||||||
assertEquals(0x00, mpu.A)
|
assertEquals(0x00, mpu.A)
|
||||||
assertTrue(mpu.Status.Z)
|
assertTrue(mpu.Status.Z)
|
||||||
assertFalse(mpu.Status.N)
|
assertFalse(mpu.Status.N)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -5442,10 +5441,9 @@ abstract class TestCommon6502 {
|
|||||||
mpu.SP = 0xFC
|
mpu.SP = 0xFC
|
||||||
|
|
||||||
mpu.step()
|
mpu.step()
|
||||||
assertEquals(0xC003, mpu.PC)
|
|
||||||
assertEquals(0xFC, mpu.Status.asByte())
|
|
||||||
assertEquals(0xFF, mpu.SP)
|
assertEquals(0xFF, mpu.SP)
|
||||||
|
assertEquals(0xFC, mpu.Status.asByte())
|
||||||
|
assertEquals(0xC003, mpu.PC)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user