mirror of
https://github.com/irmen/ksim65.git
synced 2025-04-20 13:40:24 +00:00
starting 65C02
This commit is contained in:
parent
0b7e91fc5c
commit
d191b757c6
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ build/
|
||||
.idea/workspace.xml
|
||||
.idea/misc.xml
|
||||
.idea/discord.xml
|
||||
.attach_pid*
|
||||
|
@ -16,27 +16,6 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
const val RESET_vector = 0xfffc
|
||||
const val IRQ_vector = 0xfffe
|
||||
const val resetCycles = 8
|
||||
|
||||
fun hexW(number: Address, allowSingleByte: Boolean = false): String {
|
||||
val msb = number ushr 8
|
||||
val lsb = number and 0xff
|
||||
return if (msb == 0 && allowSingleByte)
|
||||
hexB(lsb)
|
||||
else
|
||||
hexB(msb) + hexB(
|
||||
lsb
|
||||
)
|
||||
}
|
||||
|
||||
private const val hexdigits = "0123456789abcdef"
|
||||
|
||||
fun hexB(number: Short): String = hexB(number.toInt())
|
||||
|
||||
fun hexB(number: Int): String {
|
||||
val loNibble = number and 15
|
||||
val hiNibble = number ushr 4
|
||||
return hexdigits[hiNibble].toString() + hexdigits[loNibble]
|
||||
}
|
||||
}
|
||||
|
||||
enum class AddrMode {
|
||||
@ -113,7 +92,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
private lateinit var currentInstruction: Instruction
|
||||
|
||||
// has an interrupt been requested?
|
||||
private var pendingInterrupt: Pair<Boolean, BusComponent>? = null
|
||||
protected var pendingInterrupt: Pair<Boolean, BusComponent>? = null
|
||||
|
||||
// data byte from the instruction (only set when addr.mode is Accumulator, Immediate or Implied)
|
||||
private var fetchedData: Int = 0
|
||||
@ -127,6 +106,26 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
breakpoints[address] = action
|
||||
}
|
||||
|
||||
internal fun hexW(number: Address, allowSingleByte: Boolean = false): String {
|
||||
val msb = number ushr 8
|
||||
val lsb = number and 0xff
|
||||
return if (msb == 0 && allowSingleByte)
|
||||
hexB(lsb)
|
||||
else
|
||||
hexB(msb) + hexB(
|
||||
lsb
|
||||
)
|
||||
}
|
||||
|
||||
internal fun hexB(number: Short): String = hexB(number.toInt())
|
||||
|
||||
internal fun hexB(number: Int): String {
|
||||
val hexdigits = "0123456789abcdef"
|
||||
val loNibble = number and 15
|
||||
val hiNibble = number ushr 4
|
||||
return hexdigits[hiNibble].toString() + hexdigits[loNibble]
|
||||
}
|
||||
|
||||
fun disassemble(component: MemoryComponent, from: Address, to: Address) =
|
||||
disassemble(component.cloneContents(), component.startAddress, from, to)
|
||||
|
||||
@ -357,12 +356,12 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
pushStack(status.asByte().toInt())
|
||||
}
|
||||
|
||||
private fun pushStack(data: Int) {
|
||||
protected fun pushStack(data: Int) {
|
||||
write(SP or 0x0100, data)
|
||||
SP = (SP - 1) and 0xff
|
||||
}
|
||||
|
||||
private fun popStack(): Int {
|
||||
protected fun popStack(): Int {
|
||||
SP = (SP + 1) and 0xff
|
||||
return read(SP or 0x0100)
|
||||
}
|
||||
@ -374,7 +373,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
|
||||
private fun read(address: Address): Int = bus.read(address).toInt()
|
||||
private fun readWord(address: Address): Int = bus.read(address).toInt() or (bus.read(address + 1).toInt() shl 8)
|
||||
protected fun readWord(address: Address): Int = bus.read(address).toInt() or (bus.read(address + 1).toInt() shl 8)
|
||||
private fun write(address: Address, data: Int) = bus.write(address, data.toShort())
|
||||
|
||||
// opcodes table from http://www.oxyron.de/html/opcodes02.html
|
||||
@ -711,7 +710,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun dispatchOpcode(opcode: Int) {
|
||||
protected open fun dispatchOpcode(opcode: Int) {
|
||||
when (opcode) {
|
||||
0x00 -> iBrk()
|
||||
0x01 -> iOra()
|
||||
@ -976,7 +975,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
|
||||
// official instructions
|
||||
|
||||
private fun iAdc() {
|
||||
protected fun iAdc() {
|
||||
val operand = getFetched()
|
||||
if (Status.D) {
|
||||
// BCD add
|
||||
@ -1008,13 +1007,13 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun iAnd() {
|
||||
protected fun iAnd() {
|
||||
A = A and getFetched()
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iAsl() {
|
||||
protected fun iAsl() {
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
Status.C = (A and 0b10000000) != 0
|
||||
A = (A shl 1) and 0xff
|
||||
@ -1030,38 +1029,38 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun iBcc() {
|
||||
protected fun iBcc() {
|
||||
if (!Status.C) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBcs() {
|
||||
protected fun iBcs() {
|
||||
if (Status.C) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBeq() {
|
||||
protected fun iBeq() {
|
||||
if (Status.Z) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBit() {
|
||||
protected fun iBit() {
|
||||
val operand = getFetched()
|
||||
Status.Z = (A and operand) == 0
|
||||
Status.V = (operand and 0b01000000) != 0
|
||||
Status.N = (operand and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iBmi() {
|
||||
protected fun iBmi() {
|
||||
if (Status.N) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBne() {
|
||||
protected fun iBne() {
|
||||
if (!Status.Z) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBpl() {
|
||||
protected fun iBpl() {
|
||||
if (!Status.N) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBrk() {
|
||||
protected fun iBrk() {
|
||||
// handle BRK ('software interrupt') or a real hardware IRQ
|
||||
val interrupt = pendingInterrupt
|
||||
val nmi = interrupt?.first == true
|
||||
@ -1079,123 +1078,123 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
pendingInterrupt = null
|
||||
}
|
||||
|
||||
private fun iBvc() {
|
||||
protected fun iBvc() {
|
||||
if (!Status.V) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iBvs() {
|
||||
protected fun iBvs() {
|
||||
if (Status.V) PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iClc() {
|
||||
protected fun iClc() {
|
||||
Status.C = false
|
||||
}
|
||||
|
||||
private fun iCld() {
|
||||
protected fun iCld() {
|
||||
Status.D = false
|
||||
}
|
||||
|
||||
private fun iCli() {
|
||||
protected fun iCli() {
|
||||
Status.I = false
|
||||
}
|
||||
|
||||
private fun iClv() {
|
||||
protected fun iClv() {
|
||||
Status.V = false
|
||||
}
|
||||
|
||||
private fun iCmp() {
|
||||
protected fun iCmp() {
|
||||
val fetched = getFetched()
|
||||
Status.C = A >= fetched
|
||||
Status.Z = A == fetched
|
||||
Status.N = ((A - fetched) and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iCpx() {
|
||||
protected fun iCpx() {
|
||||
val fetched = getFetched()
|
||||
Status.C = X >= fetched
|
||||
Status.Z = X == fetched
|
||||
Status.N = ((X - fetched) and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iCpy() {
|
||||
protected fun iCpy() {
|
||||
val fetched = getFetched()
|
||||
Status.C = Y >= fetched
|
||||
Status.Z = Y == fetched
|
||||
Status.N = ((Y - fetched) and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iDec() {
|
||||
protected fun iDec() {
|
||||
val data = (read(fetchedAddress) - 1) and 0xff
|
||||
write(fetchedAddress, data)
|
||||
Status.Z = data == 0
|
||||
Status.N = (data and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iDex() {
|
||||
protected fun iDex() {
|
||||
X = (X - 1) and 0xff
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iDey() {
|
||||
protected fun iDey() {
|
||||
Y = (Y - 1) and 0xff
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iEor() {
|
||||
protected fun iEor() {
|
||||
A = A xor getFetched()
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iInc() {
|
||||
protected fun iInc() {
|
||||
val data = (read(fetchedAddress) + 1) and 0xff
|
||||
write(fetchedAddress, data)
|
||||
Status.Z = data == 0
|
||||
Status.N = (data and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iInx() {
|
||||
protected fun iInx() {
|
||||
X = (X + 1) and 0xff
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iIny() {
|
||||
protected fun iIny() {
|
||||
Y = (Y + 1) and 0xff
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iJmp() {
|
||||
protected fun iJmp() {
|
||||
PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iJsr() {
|
||||
protected fun iJsr() {
|
||||
pushStackAddr(PC - 1)
|
||||
PC = fetchedAddress
|
||||
}
|
||||
|
||||
private fun iLda() {
|
||||
protected fun iLda() {
|
||||
A = getFetched()
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iLdx() {
|
||||
protected fun iLdx() {
|
||||
X = getFetched()
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iLdy() {
|
||||
protected fun iLdy() {
|
||||
Y = getFetched()
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iLsr() {
|
||||
protected fun iLsr() {
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
Status.C = (A and 1) == 1
|
||||
A = A ushr 1
|
||||
@ -1211,37 +1210,37 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun iNop() {}
|
||||
protected fun iNop() {}
|
||||
|
||||
private fun iOra() {
|
||||
protected fun iOra() {
|
||||
A = A or getFetched()
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iPha() {
|
||||
protected fun iPha() {
|
||||
pushStack(A)
|
||||
}
|
||||
|
||||
private fun iPhp() {
|
||||
protected fun iPhp() {
|
||||
val origBreakflag = Status.B
|
||||
Status.B = true
|
||||
pushStack(Status)
|
||||
Status.B = origBreakflag
|
||||
}
|
||||
|
||||
private fun iPla() {
|
||||
protected fun iPla() {
|
||||
A = popStack()
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iPlp() {
|
||||
protected fun iPlp() {
|
||||
Status.fromByte(popStack())
|
||||
Status.B = true // break is always 1 except when pushing on stack
|
||||
}
|
||||
|
||||
private fun iRol() {
|
||||
protected fun iRol() {
|
||||
val oldCarry = Status.C
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
Status.C = (A and 0b10000000) != 0
|
||||
@ -1258,7 +1257,7 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun iRor() {
|
||||
protected fun iRor() {
|
||||
val oldCarry = Status.C
|
||||
if (currentInstruction.mode == AddrMode.Acc) {
|
||||
Status.C = (A and 1) == 1
|
||||
@ -1275,18 +1274,18 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun iRti() {
|
||||
protected fun iRti() {
|
||||
Status.fromByte(popStack())
|
||||
Status.B = true // break is always 1 except when pushing on stack
|
||||
PC = popStackAddr()
|
||||
}
|
||||
|
||||
private fun iRts() {
|
||||
protected fun iRts() {
|
||||
PC = popStackAddr()
|
||||
PC = (PC + 1) and 0xffff
|
||||
}
|
||||
|
||||
private fun iSbc() {
|
||||
protected fun iSbc() {
|
||||
val operand = getFetched()
|
||||
val tmp = (A - operand - if (Status.C) 0 else 1) and 0xffff
|
||||
Status.V = (A xor operand) and (A xor tmp) and 0b10000000 != 0
|
||||
@ -1313,65 +1312,65 @@ open class Cpu6502(private val stopOnBrk: Boolean) : BusComponent() {
|
||||
Status.N = (tmp and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iSec() {
|
||||
protected fun iSec() {
|
||||
Status.C = true
|
||||
}
|
||||
|
||||
private fun iSed() {
|
||||
protected fun iSed() {
|
||||
Status.D = true
|
||||
}
|
||||
|
||||
private fun iSei() {
|
||||
protected fun iSei() {
|
||||
Status.I = true
|
||||
}
|
||||
|
||||
private fun iSta() {
|
||||
protected fun iSta() {
|
||||
write(fetchedAddress, A)
|
||||
}
|
||||
|
||||
private fun iStx() {
|
||||
protected fun iStx() {
|
||||
write(fetchedAddress, X)
|
||||
}
|
||||
|
||||
private fun iSty() {
|
||||
protected fun iSty() {
|
||||
write(fetchedAddress, Y)
|
||||
}
|
||||
|
||||
private fun iTax() {
|
||||
protected fun iTax() {
|
||||
X = A
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iTay() {
|
||||
protected fun iTay() {
|
||||
Y = A
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iTsx() {
|
||||
protected fun iTsx() {
|
||||
X = SP
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iTxa() {
|
||||
protected fun iTxa() {
|
||||
A = X
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iTxs() {
|
||||
protected fun iTxs() {
|
||||
SP = X
|
||||
}
|
||||
|
||||
private fun iTya() {
|
||||
protected fun iTya() {
|
||||
A = Y
|
||||
Status.Z = A == 0
|
||||
Status.N = (A and 0b10000000) != 0
|
||||
}
|
||||
|
||||
// unofficial/illegal instructions
|
||||
// unofficial/illegal 6502 instructions
|
||||
|
||||
private fun iAhx() {
|
||||
TODO("ahx - ('illegal' instruction)")
|
||||
|
@ -2,9 +2,495 @@ package razorvine.ksim65.components
|
||||
|
||||
class Cpu65C02(stopOnBrk: Boolean) : Cpu6502(stopOnBrk) {
|
||||
|
||||
enum class Wait {
|
||||
Normal,
|
||||
Waiting,
|
||||
Stopped
|
||||
}
|
||||
|
||||
val waiting: Boolean = false
|
||||
var waiting: Wait = Wait.Normal
|
||||
|
||||
// TODO implement this CPU type 65C02, and re-enable the unit tests for that
|
||||
|
||||
companion object {
|
||||
const val NMI_vector = Cpu6502.NMI_vector
|
||||
const val RESET_vector = Cpu6502.RESET_vector
|
||||
const val IRQ_vector = Cpu6502.NMI_vector
|
||||
const val resetCycles = Cpu6502.resetCycles
|
||||
}
|
||||
|
||||
override fun clock() {
|
||||
when(waiting) {
|
||||
Wait.Normal -> super.clock()
|
||||
Wait.Waiting -> {
|
||||
if(pendingInterrupt!=null) {
|
||||
// continue execution after hardware interrupt
|
||||
waiting = Wait.Normal
|
||||
instrCycles = 1
|
||||
}
|
||||
}
|
||||
Wait.Stopped -> {
|
||||
if(pendingInterrupt!=null) {
|
||||
// jump to reset vector after hardware interrupt
|
||||
PC = readWord(RESET_vector)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// opcode list: http://www.oxyron.de/html/opcodesc02.html
|
||||
override fun dispatchOpcode(opcode: Int) {
|
||||
when (opcode) {
|
||||
0x00 -> iBrk()
|
||||
0x01 -> iOra()
|
||||
0x02 -> iNop()
|
||||
0x03 -> iNop()
|
||||
0x04 -> iTsb()
|
||||
0x05 -> iOra()
|
||||
0x06 -> iAsl()
|
||||
0x07 -> iRmb0()
|
||||
0x08 -> iPhp()
|
||||
0x09 -> iOra()
|
||||
0x0a -> iAsl()
|
||||
0x0b -> iNop()
|
||||
0x0c -> iTsb()
|
||||
0x0d -> iOra()
|
||||
0x0e -> iAsl()
|
||||
0x0f -> iBrr0()
|
||||
|
||||
0x10 -> iBpl()
|
||||
0x11 -> iOra()
|
||||
0x12 -> iOra()
|
||||
0x13 -> iNop()
|
||||
0x14 -> iTrb()
|
||||
0x15 -> iOra()
|
||||
0x16 -> iAsl()
|
||||
0x17 -> iRmb1()
|
||||
0x18 -> iClc()
|
||||
0x19 -> iOra()
|
||||
0x1a -> iInc()
|
||||
0x1b -> iNop()
|
||||
0x1c -> iTrb()
|
||||
0x1d -> iOra()
|
||||
0x1e -> iAsl()
|
||||
0x1f -> iBrr1()
|
||||
|
||||
0x20 -> iJsr()
|
||||
0x21 -> iAnd()
|
||||
0x22 -> iNop()
|
||||
0x23 -> iNop()
|
||||
0x24 -> iBit()
|
||||
0x25 -> iAnd()
|
||||
0x26 -> iRol()
|
||||
0x27 -> iRmb2()
|
||||
0x28 -> iPlp()
|
||||
0x29 -> iAnd()
|
||||
0x2a -> iRol()
|
||||
0x2b -> iNop()
|
||||
0x2c -> iBit()
|
||||
0x2d -> iAnd()
|
||||
0x2e -> iRol()
|
||||
0x2f -> iBrr2()
|
||||
|
||||
0x30 -> iBmi()
|
||||
0x31 -> iAnd()
|
||||
0x32 -> iAnd()
|
||||
0x33 -> iNop()
|
||||
0x34 -> iBit()
|
||||
0x35 -> iAnd()
|
||||
0x36 -> iRol()
|
||||
0x37 -> iRmb3()
|
||||
0x38 -> iSec()
|
||||
0x39 -> iAnd()
|
||||
0x3a -> iDec()
|
||||
0x3b -> iNop()
|
||||
0x3c -> iBit()
|
||||
0x3d -> iAnd()
|
||||
0x3e -> iRol()
|
||||
0x3f -> iBrr3()
|
||||
|
||||
0x40 -> iRti()
|
||||
0x41 -> iEor()
|
||||
0x42 -> iNop()
|
||||
0x43 -> iNop()
|
||||
0x44 -> iNop()
|
||||
0x45 -> iEor()
|
||||
0x46 -> iLsr()
|
||||
0x47 -> iRmb4()
|
||||
0x48 -> iPha()
|
||||
0x49 -> iEor()
|
||||
0x4a -> iLsr()
|
||||
0x4b -> iNop()
|
||||
0x4c -> iJmp()
|
||||
0x4d -> iEor()
|
||||
0x4e -> iLsr()
|
||||
0x4f -> iBrr4()
|
||||
|
||||
0x50 -> iBvc()
|
||||
0x51 -> iEor()
|
||||
0x52 -> iEor()
|
||||
0x53 -> iNop()
|
||||
0x54 -> iNop()
|
||||
0x55 -> iEor()
|
||||
0x56 -> iLsr()
|
||||
0x57 -> iRmb5()
|
||||
0x58 -> iCli()
|
||||
0x59 -> iEor()
|
||||
0x5a -> iPhy()
|
||||
0x5b -> iNop()
|
||||
0x5c -> iNop()
|
||||
0x5d -> iEor()
|
||||
0x5e -> iLsr()
|
||||
0x5f -> iBrr5()
|
||||
|
||||
0x60 -> iRts()
|
||||
0x61 -> iAdc()
|
||||
0x62 -> iNop()
|
||||
0x63 -> iNop()
|
||||
0x64 -> iStz()
|
||||
0x65 -> iAdc()
|
||||
0x66 -> iRor()
|
||||
0x67 -> iRmb6()
|
||||
0x68 -> iPla()
|
||||
0x69 -> iAdc()
|
||||
0x6a -> iRor()
|
||||
0x6b -> iNop()
|
||||
0x6c -> iJmp()
|
||||
0x6d -> iAdc()
|
||||
0x6e -> iRor()
|
||||
0x6f -> iBrr6()
|
||||
|
||||
0x70 -> iBvs()
|
||||
0x71 -> iAdc()
|
||||
0x72 -> iAdc()
|
||||
0x73 -> iNop()
|
||||
0x74 -> iStz()
|
||||
0x75 -> iAdc()
|
||||
0x76 -> iRor()
|
||||
0x77 -> iRmb7()
|
||||
0x78 -> iSei()
|
||||
0x79 -> iAdc()
|
||||
0x7a -> iPly()
|
||||
0x7b -> iNop()
|
||||
0x7c -> iJmp()
|
||||
0x7d -> iAdc()
|
||||
0x7e -> iRor()
|
||||
0x7f -> iBrr7()
|
||||
|
||||
0x80 -> iBra()
|
||||
0x81 -> iSta()
|
||||
0x82 -> iNop()
|
||||
0x83 -> iNop()
|
||||
0x84 -> iSty()
|
||||
0x85 -> iSta()
|
||||
0x86 -> iStx()
|
||||
0x87 -> iSmb0()
|
||||
0x88 -> iDey()
|
||||
0x89 -> iBit()
|
||||
0x8a -> iTxa()
|
||||
0x8b -> iNop()
|
||||
0x8c -> iSty()
|
||||
0x8d -> iSta()
|
||||
0x8e -> iStx()
|
||||
0x8f -> iBbs0()
|
||||
|
||||
0x90 -> iBcc()
|
||||
0x91 -> iSta()
|
||||
0x92 -> iSta()
|
||||
0x93 -> iNop()
|
||||
0x94 -> iSty()
|
||||
0x95 -> iSta()
|
||||
0x96 -> iStx()
|
||||
0x97 -> iSmb1()
|
||||
0x98 -> iTya()
|
||||
0x99 -> iSta()
|
||||
0x9a -> iTxs()
|
||||
0x9b -> iNop()
|
||||
0x9c -> iStz()
|
||||
0x9d -> iSta()
|
||||
0x9e -> iStz()
|
||||
0x9f -> iBbs1()
|
||||
|
||||
0xa0 -> iLdy()
|
||||
0xa1 -> iLda()
|
||||
0xa2 -> iLdx()
|
||||
0xa3 -> iNop()
|
||||
0xa4 -> iLdy()
|
||||
0xa5 -> iLda()
|
||||
0xa6 -> iLdx()
|
||||
0xa7 -> iSmb2()
|
||||
0xa8 -> iTay()
|
||||
0xa9 -> iLda()
|
||||
0xaa -> iTax()
|
||||
0xab -> iNop()
|
||||
0xac -> iLdy()
|
||||
0xad -> iLda()
|
||||
0xae -> iLdx()
|
||||
0xaf -> iBbs2()
|
||||
|
||||
0xb0 -> iBcs()
|
||||
0xb1 -> iLda()
|
||||
0xb2 -> iLda()
|
||||
0xb3 -> iNop()
|
||||
0xb4 -> iLdy()
|
||||
0xb5 -> iLda()
|
||||
0xb6 -> iLdx()
|
||||
0xb7 -> iSmb3()
|
||||
0xb8 -> iClv()
|
||||
0xb9 -> iLda()
|
||||
0xba -> iTsx()
|
||||
0xbb -> iNop()
|
||||
0xbc -> iLdy()
|
||||
0xbd -> iLda()
|
||||
0xbe -> iLdx()
|
||||
0xbf -> iBbs3()
|
||||
|
||||
0xc0 -> iCpy()
|
||||
0xc1 -> iCmp()
|
||||
0xc2 -> iNop()
|
||||
0xc3 -> iNop()
|
||||
0xc4 -> iCpy()
|
||||
0xc5 -> iCmp()
|
||||
0xc6 -> iDec()
|
||||
0xc7 -> iSmb4()
|
||||
0xc8 -> iIny()
|
||||
0xc9 -> iCmp()
|
||||
0xca -> iDex()
|
||||
0xcb -> iWai()
|
||||
0xcc -> iCpy()
|
||||
0xcd -> iCmp()
|
||||
0xce -> iDec()
|
||||
0xcf -> iBbs4()
|
||||
|
||||
0xd0 -> iBne()
|
||||
0xd1 -> iCmp()
|
||||
0xd2 -> iCmp()
|
||||
0xd3 -> iNop()
|
||||
0xd4 -> iNop()
|
||||
0xd5 -> iCmp()
|
||||
0xd6 -> iDec()
|
||||
0xd7 -> iSmb5()
|
||||
0xd8 -> iCld()
|
||||
0xd9 -> iCmp()
|
||||
0xda -> iPhx()
|
||||
0xdb -> iStp()
|
||||
0xdc -> iNop()
|
||||
0xdd -> iCmp()
|
||||
0xde -> iDec()
|
||||
0xdf -> iBbs5()
|
||||
|
||||
0xe0 -> iCpx()
|
||||
0xe1 -> iSbc()
|
||||
0xe2 -> iNop()
|
||||
0xe3 -> iNop()
|
||||
0xe4 -> iCpx()
|
||||
0xe5 -> iSbc()
|
||||
0xe6 -> iInc()
|
||||
0xe7 -> iSmb6()
|
||||
0xe8 -> iInx()
|
||||
0xe9 -> iSbc()
|
||||
0xea -> iNop()
|
||||
0xeb -> iNop()
|
||||
0xec -> iCpx()
|
||||
0xed -> iSbc()
|
||||
0xee -> iInc()
|
||||
0xef -> iBbs6()
|
||||
|
||||
0xf0 -> iBeq()
|
||||
0xf1 -> iSbc()
|
||||
0xf2 -> iSbc()
|
||||
0xf3 -> iNop()
|
||||
0xf4 -> iNop()
|
||||
0xf5 -> iSbc()
|
||||
0xf6 -> iInc()
|
||||
0xf7 -> iSmb7()
|
||||
0xf8 -> iSed()
|
||||
0xf9 -> iSbc()
|
||||
0xfa -> iPlx()
|
||||
0xfb -> iNop()
|
||||
0xfc -> iNop()
|
||||
0xfd -> iSbc()
|
||||
0xfe -> iInc()
|
||||
0xff -> iBbs7()
|
||||
else -> { /* can't occur */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun iBra() {
|
||||
TODO("bra")
|
||||
}
|
||||
|
||||
private fun iTrb() {
|
||||
TODO("trb")
|
||||
}
|
||||
|
||||
private fun iTsb() {
|
||||
TODO("tsb")
|
||||
}
|
||||
|
||||
private fun iStz() {
|
||||
TODO("stz")
|
||||
}
|
||||
|
||||
private fun iWai() {
|
||||
waiting = Wait.Waiting
|
||||
PC--
|
||||
}
|
||||
|
||||
private fun iStp() {
|
||||
waiting = Wait.Stopped
|
||||
PC--
|
||||
}
|
||||
|
||||
private fun iPhx() {
|
||||
pushStack(X)
|
||||
}
|
||||
|
||||
private fun iPlx() {
|
||||
X = popStack()
|
||||
Status.Z = X == 0
|
||||
Status.N = (X and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iPhy() {
|
||||
pushStack(Y)
|
||||
}
|
||||
|
||||
private fun iPly() {
|
||||
Y = popStack()
|
||||
Status.Z = Y == 0
|
||||
Status.N = (Y and 0b10000000) != 0
|
||||
}
|
||||
|
||||
private fun iBrr0() {
|
||||
TODO("brr0")
|
||||
val x = hexB(2)
|
||||
val y = hexW(2)
|
||||
val z = hexB(3.toShort())
|
||||
}
|
||||
|
||||
private fun iBrr1() {
|
||||
TODO("brr1")
|
||||
}
|
||||
|
||||
private fun iBrr2() {
|
||||
TODO("brr2")
|
||||
}
|
||||
|
||||
private fun iBrr3() {
|
||||
TODO("brr3")
|
||||
}
|
||||
|
||||
private fun iBrr4() {
|
||||
TODO("brr4")
|
||||
}
|
||||
|
||||
private fun iBrr5() {
|
||||
TODO("brr5")
|
||||
}
|
||||
|
||||
private fun iBrr6() {
|
||||
TODO("brr6")
|
||||
}
|
||||
|
||||
private fun iBrr7() {
|
||||
TODO("brr7")
|
||||
}
|
||||
|
||||
private fun iBbs0() {
|
||||
TODO("bbs0")
|
||||
}
|
||||
|
||||
private fun iBbs1() {
|
||||
TODO("bbs1")
|
||||
}
|
||||
|
||||
private fun iBbs2() {
|
||||
TODO("bbs2")
|
||||
}
|
||||
|
||||
private fun iBbs3() {
|
||||
TODO("bbs3")
|
||||
}
|
||||
|
||||
private fun iBbs4() {
|
||||
TODO("bbs4")
|
||||
}
|
||||
|
||||
private fun iBbs5() {
|
||||
TODO("bbs5")
|
||||
}
|
||||
|
||||
private fun iBbs6() {
|
||||
TODO("bbs6")
|
||||
}
|
||||
|
||||
private fun iBbs7() {
|
||||
TODO("bbs7")
|
||||
}
|
||||
|
||||
private fun iSmb0() {
|
||||
TODO("smb0")
|
||||
}
|
||||
|
||||
private fun iSmb1() {
|
||||
TODO("smb1")
|
||||
}
|
||||
|
||||
private fun iSmb2() {
|
||||
TODO("smb2")
|
||||
}
|
||||
|
||||
private fun iSmb3() {
|
||||
TODO("sm30")
|
||||
}
|
||||
|
||||
private fun iSmb4() {
|
||||
TODO("smb4")
|
||||
}
|
||||
|
||||
private fun iSmb5() {
|
||||
TODO("smb5")
|
||||
}
|
||||
|
||||
private fun iSmb6() {
|
||||
TODO("smb6")
|
||||
}
|
||||
|
||||
private fun iSmb7() {
|
||||
TODO("smb7")
|
||||
}
|
||||
|
||||
private fun iRmb0() {
|
||||
TODO("rmb0")
|
||||
}
|
||||
|
||||
private fun iRmb1() {
|
||||
TODO("rmb1")
|
||||
}
|
||||
|
||||
private fun iRmb2() {
|
||||
TODO("rmb2")
|
||||
}
|
||||
|
||||
private fun iRmb3() {
|
||||
TODO("rmb3")
|
||||
}
|
||||
|
||||
private fun iRmb4() {
|
||||
TODO("rmb4")
|
||||
}
|
||||
|
||||
private fun iRmb5() {
|
||||
TODO("rmb5")
|
||||
}
|
||||
|
||||
private fun iRmb6() {
|
||||
TODO("rmb6")
|
||||
}
|
||||
|
||||
private fun iRmb7() {
|
||||
TODO("rmb7")
|
||||
}
|
||||
}
|
||||
|
@ -88,9 +88,9 @@ class Test6502CpuBasics {
|
||||
val actualA = ram[0x00fd]
|
||||
val predictedF = ram[0x00fe]
|
||||
val actualF = ram[0x00ff]
|
||||
println("BCD TEST: FAIL!! code=${Cpu6502.hexB(code)} value1=${Cpu6502.hexB(v1)} value2=${Cpu6502.hexB(v2)}")
|
||||
println(" predictedA=${Cpu6502.hexB(predictedA)}")
|
||||
println(" actualA=${Cpu6502.hexB(actualA)}")
|
||||
println("BCD TEST: FAIL!! code=${cpu.hexB(code)} value1=${cpu.hexB(v1)} value2=${cpu.hexB(v2)}")
|
||||
println(" predictedA=${cpu.hexB(predictedA)}")
|
||||
println(" actualA=${cpu.hexB(actualA)}")
|
||||
println(" predictedF=${predictedF.toString(2).padStart(8,'0')}")
|
||||
println(" actualF=${actualF.toString(2).padStart(8,'0')}")
|
||||
fail("BCD test failed")
|
||||
|
@ -1,5 +1,4 @@
|
||||
import razorvine.ksim65.components.Cpu65C02
|
||||
import org.junit.jupiter.api.Disabled
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import kotlin.test.*
|
||||
|
||||
@ -39,7 +38,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
|
||||
@Disabled("there is no 65C02 cpu implementation at this time") // TODO create a 65c02 cpu and enable this again
|
||||
class Test65C02 : TestCommon6502() {
|
||||
// CMOS 65C02 Tests
|
||||
override fun createCpu() = Cpu65C02(false)
|
||||
@ -1536,13 +1534,13 @@ class Test65C02 : TestCommon6502() {
|
||||
@Test
|
||||
fun test_wai_sets_waiting() {
|
||||
mpu as Cpu65C02
|
||||
assertFalse(mpu.waiting)
|
||||
assertEquals(Cpu65C02.Wait.Normal, mpu.waiting)
|
||||
// $0240 WAI
|
||||
memory[0x0204] = 0xcb
|
||||
mpu.PC = 0x0204
|
||||
mpu.step()
|
||||
assertTrue(mpu.waiting)
|
||||
assertEquals(Cpu65C02.Wait.Waiting, mpu.waiting)
|
||||
assertEquals(0x0205, mpu.PC)
|
||||
assertEquals(3, mpu.totalCycles)
|
||||
assertEquals(3 + Cpu65C02.resetCycles, mpu.totalCycles.toInt())
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user