mirror of
https://github.com/irmen/ksim65.git
synced 2024-06-01 21:41:31 +00:00
fixed cycle times, implemented various illegal opcodes. NesTest now runs flawlessly
This commit is contained in:
parent
35cbe4e3ca
commit
5667c00d85
|
@ -7,11 +7,10 @@ import razorvine.ksim65.components.UByte
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 6502 cpu simulation (the NMOS version) including the 'illegal' opcodes.
|
* 6502 cpu simulation (the NMOS version) including the 'illegal' opcodes.
|
||||||
* TODO: actually implement the illegal opcodes, see http://www.ffd2.com/fridge/docs/6502-NMOS.extra.opcodes or https://sourceforge.net/p/moarnes/code/ci/master/tree/src/6502.c
|
|
||||||
*/
|
*/
|
||||||
open class Cpu6502 : BusComponent() {
|
open class Cpu6502 : BusComponent() {
|
||||||
open val name = "6502"
|
open val name = "6502"
|
||||||
var tracing: ((state: String) -> Unit)? = null
|
var tracing: ((state: State) -> Unit)? = null
|
||||||
var totalCycles = 0L
|
var totalCycles = 0L
|
||||||
protected set
|
protected set
|
||||||
private var resetTime = System.nanoTime()
|
private var resetTime = System.nanoTime()
|
||||||
|
@ -165,6 +164,9 @@ open class Cpu6502 : BusComponent() {
|
||||||
*/
|
*/
|
||||||
override fun clock() {
|
override fun clock() {
|
||||||
if (instrCycles == 0) {
|
if (instrCycles == 0) {
|
||||||
|
|
||||||
|
tracing?.invoke(snapshot())
|
||||||
|
|
||||||
if(nmiAsserted || (irqAsserted && !regP.I)) {
|
if(nmiAsserted || (irqAsserted && !regP.I)) {
|
||||||
handleInterrupt()
|
handleInterrupt()
|
||||||
return
|
return
|
||||||
|
@ -176,8 +178,6 @@ open class Cpu6502 : BusComponent() {
|
||||||
currentOpcode = read(regPC)
|
currentOpcode = read(regPC)
|
||||||
currentInstruction = instructions[currentOpcode]
|
currentInstruction = instructions[currentOpcode]
|
||||||
|
|
||||||
// tracing and breakpoint handling
|
|
||||||
tracing?.invoke(snapshot().toString())
|
|
||||||
breakpoints[regPC]?.let {
|
breakpoints[regPC]?.let {
|
||||||
if (breakpoint(it)) return
|
if (breakpoint(it)) return
|
||||||
}
|
}
|
||||||
|
@ -557,7 +557,9 @@ open class Cpu6502 : BusComponent() {
|
||||||
val relative = readPc()
|
val relative = readPc()
|
||||||
fetchedAddress = if (relative >= 0x80) {
|
fetchedAddress = if (relative >= 0x80) {
|
||||||
regPC-(256-relative) and 0xffff
|
regPC-(256-relative) and 0xffff
|
||||||
} else regPC+relative and 0xffff
|
} else {
|
||||||
|
regPC+relative and 0xffff
|
||||||
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
AddrMode.Abs -> {
|
AddrMode.Abs -> {
|
||||||
|
@ -581,6 +583,7 @@ open class Cpu6502 : BusComponent() {
|
||||||
(fetchedAddress and 0xff00) != hi shl 8
|
(fetchedAddress and 0xff00) != hi shl 8
|
||||||
}
|
}
|
||||||
AddrMode.Ind -> {
|
AddrMode.Ind -> {
|
||||||
|
val extraCycle: Boolean
|
||||||
var lo = readPc()
|
var lo = readPc()
|
||||||
var hi = readPc()
|
var hi = readPc()
|
||||||
fetchedAddress = lo or (hi shl 8)
|
fetchedAddress = lo or (hi shl 8)
|
||||||
|
@ -589,13 +592,15 @@ open class Cpu6502 : BusComponent() {
|
||||||
// not able to fetch an address which crosses the page boundary.
|
// not able to fetch an address which crosses the page boundary.
|
||||||
lo = read(fetchedAddress)
|
lo = read(fetchedAddress)
|
||||||
hi = read(fetchedAddress and 0xff00)
|
hi = read(fetchedAddress and 0xff00)
|
||||||
|
extraCycle = true
|
||||||
} else {
|
} else {
|
||||||
// normal behavior
|
// normal behavior
|
||||||
lo = read(fetchedAddress)
|
lo = read(fetchedAddress)
|
||||||
hi = read(fetchedAddress+1)
|
hi = read(fetchedAddress+1)
|
||||||
|
extraCycle = false
|
||||||
}
|
}
|
||||||
fetchedAddress = lo or (hi shl 8)
|
fetchedAddress = lo or (hi shl 8)
|
||||||
false
|
extraCycle
|
||||||
}
|
}
|
||||||
AddrMode.IzX -> {
|
AddrMode.IzX -> {
|
||||||
// note: not able to fetch an address which crosses the (zero)page boundary
|
// note: not able to fetch an address which crosses the (zero)page boundary
|
||||||
|
@ -603,15 +608,17 @@ open class Cpu6502 : BusComponent() {
|
||||||
val lo = read((fetchedAddress+regX) and 0xff)
|
val lo = read((fetchedAddress+regX) and 0xff)
|
||||||
val hi = read((fetchedAddress+regX+1) and 0xff)
|
val hi = read((fetchedAddress+regX+1) and 0xff)
|
||||||
fetchedAddress = lo or (hi shl 8)
|
fetchedAddress = lo or (hi shl 8)
|
||||||
false
|
// if this address is a different page, extra clock cycle:
|
||||||
|
(fetchedAddress and 0xff00) != hi shl 8
|
||||||
}
|
}
|
||||||
AddrMode.IzY -> {
|
AddrMode.IzY -> {
|
||||||
// note: not able to fetch an address which crosses the (zero)page boundary
|
// note: not able to fetch an address which crosses the (zero)page boundary
|
||||||
fetchedAddress = readPc()
|
val fetchedAddress1 = readPc()
|
||||||
val lo = read(fetchedAddress)
|
val lo = read(fetchedAddress1)
|
||||||
val hi = read((fetchedAddress+1) and 0xff)
|
val hi = read((fetchedAddress1+1) and 0xff)
|
||||||
fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff
|
fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff
|
||||||
false
|
// if this address is a different page, extra clock cycle:
|
||||||
|
(fetchedAddress and 0xff00) != hi shl 8
|
||||||
}
|
}
|
||||||
AddrMode.Zpr, AddrMode.Izp, AddrMode.IaX -> {
|
AddrMode.Zpr, AddrMode.Izp, AddrMode.IaX -> {
|
||||||
// addressing mode used by the 65C02 only
|
// addressing mode used by the 65C02 only
|
||||||
|
@ -621,7 +628,7 @@ open class Cpu6502 : BusComponent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun dispatchOpcode(opcode: Int): Boolean {
|
protected open fun dispatchOpcode(opcode: Int): Boolean {
|
||||||
when (opcode) {
|
return when (opcode) {
|
||||||
0x00 -> iBrk()
|
0x00 -> iBrk()
|
||||||
0x01 -> iOra()
|
0x01 -> iOra()
|
||||||
0x02 -> iInvalid()
|
0x02 -> iInvalid()
|
||||||
|
@ -878,15 +885,14 @@ open class Cpu6502 : BusComponent() {
|
||||||
0xfd -> iSbc()
|
0xfd -> iSbc()
|
||||||
0xfe -> iInc()
|
0xfe -> iInc()
|
||||||
0xff -> iIsc()
|
0xff -> iIsc()
|
||||||
else -> { /* can't occur */ }
|
else -> false /* can't occur */
|
||||||
}
|
}
|
||||||
return false // TODO determine if instructions can cause extra clock cycle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// official instructions
|
// official instructions
|
||||||
|
|
||||||
protected open fun iAdc() {
|
protected open fun iAdc(): Boolean {
|
||||||
val operand = getFetched()
|
val operand = getFetched()
|
||||||
if (regP.D) {
|
if (regP.D) {
|
||||||
// BCD add
|
// BCD add
|
||||||
|
@ -916,15 +922,18 @@ open class Cpu6502 : BusComponent() {
|
||||||
regP.C = tmp > 0xff
|
regP.C = tmp > 0xff
|
||||||
regA = tmp and 0xff
|
regA = tmp and 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iAnd() {
|
protected fun iAnd(): Boolean {
|
||||||
regA = regA and getFetched()
|
regA = regA and getFetched()
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iAsl() {
|
protected fun iAsl(): Boolean {
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
regP.C = (regA and 0b10000000) != 0
|
regP.C = (regA and 0b10000000) != 0
|
||||||
regA = (regA shl 1) and 0xff
|
regA = (regA shl 1) and 0xff
|
||||||
|
@ -938,44 +947,82 @@ open class Cpu6502 : BusComponent() {
|
||||||
regP.Z = shifted == 0
|
regP.Z = shifted == 0
|
||||||
regP.N = (shifted and 0b10000000) != 0
|
regP.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBcc() {
|
protected fun iBcc(): Boolean {
|
||||||
if (!regP.C) regPC = fetchedAddress
|
if (!regP.C) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBcs() {
|
protected fun iBcs(): Boolean {
|
||||||
if (regP.C) regPC = fetchedAddress
|
if (regP.C) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBeq() {
|
protected fun iBeq(): Boolean {
|
||||||
if (regP.Z) regPC = fetchedAddress
|
if (regP.Z) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun iBit() {
|
protected open fun iBit(): Boolean {
|
||||||
val operand = getFetched()
|
val operand = getFetched()
|
||||||
regP.Z = (regA and operand) == 0
|
regP.Z = (regA and operand) == 0
|
||||||
regP.V = (operand and 0b01000000) != 0
|
regP.V = (operand and 0b01000000) != 0
|
||||||
regP.N = (operand and 0b10000000) != 0
|
regP.N = (operand and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBmi() {
|
protected fun iBmi(): Boolean {
|
||||||
if (regP.N) regPC = fetchedAddress
|
if (regP.N) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBne() {
|
protected fun iBne(): Boolean {
|
||||||
if (!regP.Z) regPC = fetchedAddress
|
if (!regP.Z) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBpl() {
|
protected fun iBpl(): Boolean {
|
||||||
if (!regP.N) regPC = fetchedAddress
|
if (!regP.N) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun iBrk() {
|
protected open fun iBrk(): Boolean {
|
||||||
// handle BRK ('software interrupt')
|
// handle BRK ('software interrupt')
|
||||||
regPC++
|
regPC++
|
||||||
if(nmiAsserted)
|
if(nmiAsserted)
|
||||||
return // if an NMI occurs during BRK, the BRK won't get executed on 6502 (65C02 fixes this)
|
return false // if an NMI occurs during BRK, the BRK won't get executed on 6502 (65C02 fixes this)
|
||||||
pushStackAddr(regPC)
|
pushStackAddr(regPC)
|
||||||
regP.B = true
|
regP.B = true
|
||||||
pushStack(regP)
|
pushStack(regP)
|
||||||
|
@ -984,6 +1031,7 @@ open class Cpu6502 : BusComponent() {
|
||||||
regPC = readWord(IRQ_vector)
|
regPC = readWord(IRQ_vector)
|
||||||
|
|
||||||
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun handleInterrupt() {
|
protected open fun handleInterrupt() {
|
||||||
|
@ -1008,123 +1056,154 @@ open class Cpu6502 : BusComponent() {
|
||||||
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBvc() {
|
protected fun iBvc(): Boolean {
|
||||||
if (!regP.V) regPC = fetchedAddress
|
if (!regP.V) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iBvs() {
|
protected fun iBvs(): Boolean {
|
||||||
if (regP.V) regPC = fetchedAddress
|
if (regP.V) {
|
||||||
|
if(fetchedAddress and 0xff00 != regPC and 0xff00)
|
||||||
|
instrCycles++
|
||||||
|
regPC = fetchedAddress
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iClc() {
|
protected fun iClc(): Boolean {
|
||||||
regP.C = false
|
regP.C = false
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iCld() {
|
protected fun iCld(): Boolean {
|
||||||
regP.D = false
|
regP.D = false
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iCli() {
|
protected fun iCli(): Boolean {
|
||||||
regP.I = false
|
regP.I = false
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iClv() {
|
protected fun iClv(): Boolean {
|
||||||
regP.V = false
|
regP.V = false
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iCmp() {
|
protected fun iCmp(operandOverride: Int? = null): Boolean {
|
||||||
val fetched = getFetched()
|
val fetched = operandOverride ?: getFetched()
|
||||||
regP.C = regA >= fetched
|
regP.C = regA >= fetched
|
||||||
regP.Z = regA == fetched
|
regP.Z = regA == fetched
|
||||||
regP.N = ((regA-fetched) and 0b10000000) != 0
|
regP.N = ((regA-fetched) and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iCpx() {
|
protected fun iCpx(): Boolean {
|
||||||
val fetched = getFetched()
|
val fetched = getFetched()
|
||||||
regP.C = regX >= fetched
|
regP.C = regX >= fetched
|
||||||
regP.Z = regX == fetched
|
regP.Z = regX == fetched
|
||||||
regP.N = ((regX-fetched) and 0b10000000) != 0
|
regP.N = ((regX-fetched) and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iCpy() {
|
protected fun iCpy(): Boolean {
|
||||||
val fetched = getFetched()
|
val fetched = getFetched()
|
||||||
regP.C = regY >= fetched
|
regP.C = regY >= fetched
|
||||||
regP.Z = regY == fetched
|
regP.Z = regY == fetched
|
||||||
regP.N = ((regY-fetched) and 0b10000000) != 0
|
regP.N = ((regY-fetched) and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun iDec() {
|
protected open fun iDec(): Boolean {
|
||||||
val data = (read(fetchedAddress)-1) and 0xff
|
val data = (read(fetchedAddress)-1) and 0xff
|
||||||
write(fetchedAddress, data)
|
write(fetchedAddress, data)
|
||||||
regP.Z = data == 0
|
regP.Z = data == 0
|
||||||
regP.N = (data and 0b10000000) != 0
|
regP.N = (data and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iDex() {
|
protected fun iDex(): Boolean {
|
||||||
regX = (regX-1) and 0xff
|
regX = (regX-1) and 0xff
|
||||||
regP.Z = regX == 0
|
regP.Z = regX == 0
|
||||||
regP.N = (regX and 0b10000000) != 0
|
regP.N = (regX and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iDey() {
|
protected fun iDey(): Boolean {
|
||||||
regY = (regY-1) and 0xff
|
regY = (regY-1) and 0xff
|
||||||
regP.Z = regY == 0
|
regP.Z = regY == 0
|
||||||
regP.N = (regY and 0b10000000) != 0
|
regP.N = (regY and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iEor() {
|
protected fun iEor(): Boolean {
|
||||||
regA = regA xor getFetched()
|
regA = regA xor getFetched()
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun iInc() {
|
protected open fun iInc(): Boolean {
|
||||||
val data = (read(fetchedAddress)+1) and 0xff
|
val data = (read(fetchedAddress)+1) and 0xff
|
||||||
write(fetchedAddress, data)
|
write(fetchedAddress, data)
|
||||||
regP.Z = data == 0
|
regP.Z = data == 0
|
||||||
regP.N = (data and 0b10000000) != 0
|
regP.N = (data and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iInx() {
|
protected fun iInx(): Boolean {
|
||||||
regX = (regX+1) and 0xff
|
regX = (regX+1) and 0xff
|
||||||
regP.Z = regX == 0
|
regP.Z = regX == 0
|
||||||
regP.N = (regX and 0b10000000) != 0
|
regP.N = (regX and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iIny() {
|
protected fun iIny(): Boolean {
|
||||||
regY = (regY+1) and 0xff
|
regY = (regY+1) and 0xff
|
||||||
regP.Z = regY == 0
|
regP.Z = regY == 0
|
||||||
regP.N = (regY and 0b10000000) != 0
|
regP.N = (regY and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iJmp() {
|
protected fun iJmp(): Boolean {
|
||||||
regPC = fetchedAddress
|
regPC = fetchedAddress
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iJsr() {
|
protected fun iJsr(): Boolean {
|
||||||
pushStackAddr(regPC-1)
|
pushStackAddr(regPC-1)
|
||||||
regPC = fetchedAddress
|
regPC = fetchedAddress
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iLda() {
|
protected fun iLda(): Boolean {
|
||||||
regA = getFetched()
|
regA = getFetched()
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iLdx() {
|
protected fun iLdx(): Boolean {
|
||||||
regX = getFetched()
|
regX = getFetched()
|
||||||
regP.Z = regX == 0
|
regP.Z = regX == 0
|
||||||
regP.N = (regX and 0b10000000) != 0
|
regP.N = (regX and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iLdy() {
|
protected fun iLdy(): Boolean {
|
||||||
regY = getFetched()
|
regY = getFetched()
|
||||||
regP.Z = regY == 0
|
regP.Z = regY == 0
|
||||||
regP.N = (regY and 0b10000000) != 0
|
regP.N = (regY and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iLsr() {
|
protected fun iLsr(): Boolean {
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
regP.C = (regA and 1) == 1
|
regP.C = (regA and 1) == 1
|
||||||
regA = regA ushr 1
|
regA = regA ushr 1
|
||||||
|
@ -1138,39 +1217,47 @@ open class Cpu6502 : BusComponent() {
|
||||||
regP.Z = shifted == 0
|
regP.Z = shifted == 0
|
||||||
regP.N = (shifted and 0b10000000) != 0
|
regP.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iNop() {}
|
protected fun iNop(): Boolean {
|
||||||
|
return currentOpcode in listOf(0x1c, 0x3c, 0x5c, 0x7c, 0xdc, 0xfc)
|
||||||
|
}
|
||||||
|
|
||||||
protected fun iOra() {
|
protected fun iOra(): Boolean {
|
||||||
regA = regA or getFetched()
|
regA = regA or getFetched()
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iPha() {
|
protected fun iPha(): Boolean {
|
||||||
pushStack(regA)
|
pushStack(regA)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iPhp() {
|
protected fun iPhp(): Boolean {
|
||||||
val origBreakflag = regP.B
|
val origBreakflag = regP.B
|
||||||
regP.B = true
|
regP.B = true
|
||||||
pushStack(regP)
|
pushStack(regP)
|
||||||
regP.B = origBreakflag
|
regP.B = origBreakflag
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iPla() {
|
protected fun iPla(): Boolean {
|
||||||
regA = popStack()
|
regA = popStack()
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iPlp() {
|
protected fun iPlp(): Boolean {
|
||||||
regP.fromInt(popStack())
|
regP.fromInt(popStack())
|
||||||
regP.B = true // break is always 1 except when pushing on stack
|
regP.B = false
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iRol() {
|
protected fun iRol(): Boolean {
|
||||||
val oldCarry = regP.C
|
val oldCarry = regP.C
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
regP.C = (regA and 0b10000000) != 0
|
regP.C = (regA and 0b10000000) != 0
|
||||||
|
@ -1185,9 +1272,10 @@ open class Cpu6502 : BusComponent() {
|
||||||
regP.Z = shifted == 0
|
regP.Z = shifted == 0
|
||||||
regP.N = (shifted and 0b10000000) != 0
|
regP.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iRor() {
|
protected fun iRor(): Boolean {
|
||||||
val oldCarry = regP.C
|
val oldCarry = regP.C
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
regP.C = (regA and 1) == 1
|
regP.C = (regA and 1) == 1
|
||||||
|
@ -1202,21 +1290,24 @@ open class Cpu6502 : BusComponent() {
|
||||||
regP.Z = shifted == 0
|
regP.Z = shifted == 0
|
||||||
regP.N = (shifted and 0b10000000) != 0
|
regP.N = (shifted and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iRti() {
|
protected fun iRti(): Boolean {
|
||||||
regP.fromInt(popStack())
|
regP.fromInt(popStack())
|
||||||
regP.B = true // break is always 1 except when pushing on stack
|
regP.B = false
|
||||||
regPC = popStackAddr()
|
regPC = popStackAddr()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iRts() {
|
protected fun iRts(): Boolean {
|
||||||
regPC = popStackAddr()
|
regPC = popStackAddr()
|
||||||
regPC = (regPC+1) and 0xffff
|
regPC = (regPC+1) and 0xffff
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun iSbc() {
|
protected open fun iSbc(operandOverride: Int? = null): Boolean {
|
||||||
val operand = getFetched()
|
val operand = operandOverride ?: getFetched()
|
||||||
val tmp = (regA-operand-if (regP.C) 0 else 1) and 0xffff
|
val tmp = (regA-operand-if (regP.C) 0 else 1) and 0xffff
|
||||||
regP.V = (regA xor operand) and (regA xor tmp) and 0b10000000 != 0
|
regP.V = (regA xor operand) and (regA xor tmp) and 0b10000000 != 0
|
||||||
if (regP.D) {
|
if (regP.D) {
|
||||||
|
@ -1240,142 +1331,205 @@ open class Cpu6502 : BusComponent() {
|
||||||
regP.C = tmp < 0x100
|
regP.C = tmp < 0x100
|
||||||
regP.Z = (tmp and 0xff) == 0
|
regP.Z = (tmp and 0xff) == 0
|
||||||
regP.N = (tmp and 0b10000000) != 0
|
regP.N = (tmp and 0b10000000) != 0
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iSec() {
|
protected fun iSec(): Boolean {
|
||||||
regP.C = true
|
regP.C = true
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iSed() {
|
protected fun iSed(): Boolean {
|
||||||
regP.D = true
|
regP.D = true
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iSei() {
|
protected fun iSei(): Boolean {
|
||||||
regP.I = true
|
regP.I = true
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iSta() {
|
protected fun iSta(): Boolean {
|
||||||
write(fetchedAddress, regA)
|
write(fetchedAddress, regA)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iStx() {
|
protected fun iStx(): Boolean {
|
||||||
write(fetchedAddress, regX)
|
write(fetchedAddress, regX)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iSty() {
|
protected fun iSty(): Boolean {
|
||||||
write(fetchedAddress, regY)
|
write(fetchedAddress, regY)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iTax() {
|
protected fun iTax(): Boolean {
|
||||||
regX = regA
|
regX = regA
|
||||||
regP.Z = regX == 0
|
regP.Z = regX == 0
|
||||||
regP.N = (regX and 0b10000000) != 0
|
regP.N = (regX and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iTay() {
|
protected fun iTay(): Boolean {
|
||||||
regY = regA
|
regY = regA
|
||||||
regP.Z = regY == 0
|
regP.Z = regY == 0
|
||||||
regP.N = (regY and 0b10000000) != 0
|
regP.N = (regY and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iTsx() {
|
protected fun iTsx(): Boolean {
|
||||||
regX = regSP
|
regX = regSP
|
||||||
regP.Z = regX == 0
|
regP.Z = regX == 0
|
||||||
regP.N = (regX and 0b10000000) != 0
|
regP.N = (regX and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iTxa() {
|
protected fun iTxa(): Boolean {
|
||||||
regA = regX
|
regA = regX
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iTxs() {
|
protected fun iTxs(): Boolean {
|
||||||
regSP = regX
|
regSP = regX
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun iTya() {
|
protected fun iTya(): Boolean {
|
||||||
regA = regY
|
regA = regY
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// unofficial/illegal 6502 instructions
|
// unofficial/illegal 6502 instructions
|
||||||
|
// see http://www.ffd2.com/fridge/docs/6502-NMOS.extra.opcodes
|
||||||
|
// or https://github.com/quietust/nintendulator/blob/master/src/CPU.cpp (search for LogBadOps)
|
||||||
|
// TODO: actually implement the illegal opcodes
|
||||||
|
|
||||||
private fun iAhx() {
|
|
||||||
TODO("\$${hexB(currentOpcode)} - ahx - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
private fun iAhx(): Boolean {
|
||||||
|
val addrHi = 0xff // TODO get the correct byte from the instruction (=last byte read)
|
||||||
|
val value = regA and regX and (addrHi+1)
|
||||||
|
write(fetchedAddress, value)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iAlr() {
|
private fun iAlr(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - alr=asr - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iAnd()
|
||||||
|
iLsr()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iAnc() {
|
private fun iAnc(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - anc - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iAnd()
|
||||||
|
regP.C = regP.N
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iArr() {
|
private fun iArr(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - arr - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iAnd()
|
||||||
|
iRor()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iAxs() {
|
private fun iAxs(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - axs - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
val oldA = regA
|
||||||
|
regA = regA and regX
|
||||||
|
regP.C = false
|
||||||
|
iSbc()
|
||||||
|
regX = regA
|
||||||
|
regA = oldA
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iDcp() {
|
private fun iDcp(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - dcp - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
val data = (read(fetchedAddress)-1) and 0xff
|
||||||
|
write(fetchedAddress, data)
|
||||||
|
iCmp(data)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iIsc() {
|
private fun iIsc(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - isc=isb - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
val data = (read(fetchedAddress)+1) and 0xff
|
||||||
|
write(fetchedAddress, data)
|
||||||
|
iSbc(data)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iLas() {
|
private fun iLas(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - las=lar - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
regA = regSP and getFetched()
|
||||||
|
regX = regA
|
||||||
|
regSP = regA
|
||||||
|
regP.Z = regA == 0
|
||||||
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iLax() {
|
private fun iLax(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - lax - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iLda()
|
||||||
|
regX = regA
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRla() {
|
private fun iRla(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - rla - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iRol()
|
||||||
|
iAnd()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRra() {
|
private fun iRra(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - rra - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iRor()
|
||||||
|
iAdc()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSax() {
|
private fun iSax(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - sax - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
write(fetchedAddress, regA and regX)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iShx() {
|
private fun iShx(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - shx - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
val addrHi = 0xff // TODO get the correct byte from the instruction (=last byte read)
|
||||||
|
write(fetchedAddress, regX and (addrHi+1))
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iShy() {
|
private fun iShy(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - shy - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
val addrHi = 0xff // TODO get the correct byte from the instruction (=last byte read)
|
||||||
|
write(fetchedAddress, regY and (addrHi+1))
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSlo() {
|
private fun iSlo(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - slo=aso - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iAsl()
|
||||||
|
iOra()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSre() {
|
private fun iSre(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - sre=lse - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
iLsr()
|
||||||
|
iEor()
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iTas() {
|
private fun iTas(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - tas - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
regSP = regA and regX
|
||||||
|
val addrHi = 0xff // TODO get the correct byte from the instruction (=last byte read)
|
||||||
|
write(fetchedAddress, regSP and addrHi)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iXaa() {
|
private fun iXaa(): Boolean {
|
||||||
TODO("\$${hexB(currentOpcode)} - xaa - ('illegal' instruction) @ \$${hexW(currentOpcodeAddress)}")
|
regA = (regX and fetchedData)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalid instruction (JAM / KIL / HLT)
|
// invalid instruction (JAM / KIL / HLT)
|
||||||
private fun iInvalid() {
|
private fun iInvalid(): Boolean {
|
||||||
throw InstructionError("invalid instruction encountered: opcode=${hexB(currentOpcode)} instr=${currentInstruction.mnemonic} @ ${hexW(currentOpcodeAddress)}")
|
throw InstructionError("invalid instruction encountered: opcode=${hexB(currentOpcode)} instr=${currentInstruction.mnemonic} @ ${hexW(currentOpcodeAddress)}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ class Cpu65C02 : Cpu6502() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchOpcode(opcode: Int): Boolean {
|
override fun dispatchOpcode(opcode: Int): Boolean {
|
||||||
when (opcode) {
|
return when (opcode) {
|
||||||
0x00 -> iBrk()
|
0x00 -> iBrk()
|
||||||
0x01 -> iOra()
|
0x01 -> iOra()
|
||||||
0x02 -> iNop()
|
0x02 -> iNop()
|
||||||
|
@ -360,9 +360,8 @@ class Cpu65C02 : Cpu6502() {
|
||||||
0xfd -> iSbc()
|
0xfd -> iSbc()
|
||||||
0xfe -> iInc()
|
0xfe -> iInc()
|
||||||
0xff -> iBbs7()
|
0xff -> iBbs7()
|
||||||
else -> { /* can't occur */ }
|
else -> false /* can't occur */
|
||||||
}
|
}
|
||||||
return false // TODO determine if instructions can cause extra clock cycle
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// opcode list: http://www.oxyron.de/html/opcodesc02.html
|
// opcode list: http://www.oxyron.de/html/opcodesc02.html
|
||||||
|
@ -624,7 +623,7 @@ class Cpu65C02 : Cpu6502() {
|
||||||
/* fe */ Instruction("inc", AddrMode.AbsX, 7),
|
/* fe */ Instruction("inc", AddrMode.AbsX, 7),
|
||||||
/* ff */ Instruction("bbs7", AddrMode.Zpr, 5)).toTypedArray()
|
/* ff */ Instruction("bbs7", AddrMode.Zpr, 5)).toTypedArray()
|
||||||
|
|
||||||
override fun iBrk() {
|
override fun iBrk(): Boolean {
|
||||||
// handle BRK ('software interrupt')
|
// handle BRK ('software interrupt')
|
||||||
regPC++
|
regPC++
|
||||||
pushStackAddr(regPC)
|
pushStackAddr(regPC)
|
||||||
|
@ -635,6 +634,7 @@ class Cpu65C02 : Cpu6502() {
|
||||||
regPC = readWord(IRQ_vector)
|
regPC = readWord(IRQ_vector)
|
||||||
|
|
||||||
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
// TODO prevent NMI from triggering immediately after IRQ/BRK... how does that work exactly?
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleInterrupt() {
|
override fun handleInterrupt() {
|
||||||
|
@ -642,16 +642,17 @@ class Cpu65C02 : Cpu6502() {
|
||||||
regP.D = false // this is different from NMOS 6502
|
regP.D = false // this is different from NMOS 6502
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iBit() {
|
override fun iBit(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
regP.Z = (regA and data) == 0
|
regP.Z = (regA and data) == 0
|
||||||
if (currentInstruction.mode != AddrMode.Imm) {
|
if (currentInstruction.mode != AddrMode.Imm) {
|
||||||
regP.V = (data and 0b01000000) != 0
|
regP.V = (data and 0b01000000) != 0
|
||||||
regP.N = (data and 0b10000000) != 0
|
regP.N = (data and 0b10000000) != 0
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iAdc() {
|
override fun iAdc(): Boolean {
|
||||||
val value = getFetched()
|
val value = getFetched()
|
||||||
if (regP.D) {
|
if (regP.D) {
|
||||||
// BCD add
|
// BCD add
|
||||||
|
@ -680,13 +681,14 @@ class Cpu65C02 : Cpu6502() {
|
||||||
regP.C = tmp > 0xff
|
regP.C = tmp > 0xff
|
||||||
regA = tmp and 0xff
|
regA = tmp and 0xff
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iSbc() {
|
override fun iSbc(operandOverride: Int?): Boolean {
|
||||||
// see http://www.6502.org/tutorials/decimal_mode.html
|
// see http://www.6502.org/tutorials/decimal_mode.html
|
||||||
// and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/65c02core.c#l1205
|
// and https://sourceforge.net/p/vice-emu/code/HEAD/tree/trunk/vice/src/65c02core.c#l1205
|
||||||
// (the implementation below is based on the code used by Vice)
|
// (the implementation below is based on the code used by Vice)
|
||||||
val value = getFetched()
|
val value = operandOverride ?: getFetched()
|
||||||
var tmp = (regA-value-if (regP.C) 0 else 1) and 0xffff
|
var tmp = (regA-value-if (regP.C) 0 else 1) and 0xffff
|
||||||
regP.V = (regA xor tmp) and (regA xor value) and 0b10000000 != 0
|
regP.V = (regA xor tmp) and (regA xor value) and 0b10000000 != 0
|
||||||
if (regP.D) {
|
if (regP.D) {
|
||||||
|
@ -698,230 +700,323 @@ class Cpu65C02 : Cpu6502() {
|
||||||
regP.Z = (tmp and 0xff) == 0
|
regP.Z = (tmp and 0xff) == 0
|
||||||
regP.N = (tmp and 0b10000000) != 0
|
regP.N = (tmp and 0b10000000) != 0
|
||||||
regA = tmp and 0xff
|
regA = tmp and 0xff
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iDec() {
|
override fun iDec(): Boolean {
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
return if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
regA = (regA-1) and 0xff
|
regA = (regA-1) and 0xff
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
false
|
||||||
} else super.iDec()
|
} else super.iDec()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iInc() {
|
override fun iInc(): Boolean {
|
||||||
if (currentInstruction.mode == AddrMode.Acc) {
|
return if (currentInstruction.mode == AddrMode.Acc) {
|
||||||
regA = (regA+1) and 0xff
|
regA = (regA+1) and 0xff
|
||||||
regP.Z = regA == 0
|
regP.Z = regA == 0
|
||||||
regP.N = (regA and 0b10000000) != 0
|
regP.N = (regA and 0b10000000) != 0
|
||||||
|
false
|
||||||
} else super.iInc()
|
} else super.iInc()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBra() {
|
private fun iBra(): Boolean {
|
||||||
// unconditional branch
|
// unconditional branch
|
||||||
regPC = fetchedAddress
|
regPC = fetchedAddress
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iTrb() {
|
private fun iTrb(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
regP.Z = data and regA == 0
|
regP.Z = data and regA == 0
|
||||||
write(fetchedAddress, data and regA.inv())
|
write(fetchedAddress, data and regA.inv())
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iTsb() {
|
private fun iTsb(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
regP.Z = data and regA == 0
|
regP.Z = data and regA == 0
|
||||||
write(fetchedAddress, data or regA)
|
write(fetchedAddress, data or regA)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iStz() {
|
private fun iStz(): Boolean {
|
||||||
write(fetchedAddress, 0)
|
write(fetchedAddress, 0)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iWai() {
|
private fun iWai(): Boolean {
|
||||||
waiting = Wait.Waiting
|
waiting = Wait.Waiting
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iStp() {
|
private fun iStp(): Boolean {
|
||||||
waiting = Wait.Stopped
|
waiting = Wait.Stopped
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPhx() {
|
private fun iPhx(): Boolean {
|
||||||
pushStack(regX)
|
pushStack(regX)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPlx() {
|
private fun iPlx(): Boolean {
|
||||||
regX = popStack()
|
regX = popStack()
|
||||||
regP.Z = regX == 0
|
regP.Z = regX == 0
|
||||||
regP.N = (regX and 0b10000000) != 0
|
regP.N = (regX and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPhy() {
|
private fun iPhy(): Boolean {
|
||||||
pushStack(regY)
|
pushStack(regY)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iPly() {
|
private fun iPly(): Boolean {
|
||||||
regY = popStack()
|
regY = popStack()
|
||||||
regP.Z = regY == 0
|
regP.Z = regY == 0
|
||||||
regP.N = (regY and 0b10000000) != 0
|
regP.N = (regY and 0b10000000) != 0
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr0() {
|
private fun iBbr0(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 1 == 0) regPC = fetchedAddressZpr
|
if (data and 1 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr1() {
|
private fun iBbr1(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 2 == 0) regPC = fetchedAddressZpr
|
if (data and 2 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr2() {
|
private fun iBbr2(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 4 == 0) regPC = fetchedAddressZpr
|
if (data and 4 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr3() {
|
private fun iBbr3(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 8 == 0) regPC = fetchedAddressZpr
|
if (data and 8 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr4() {
|
private fun iBbr4(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 16 == 0) regPC = fetchedAddressZpr
|
if (data and 16 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr5() {
|
private fun iBbr5(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 32 == 0) regPC = fetchedAddressZpr
|
if (data and 32 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr6() {
|
private fun iBbr6(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 64 == 0) regPC = fetchedAddressZpr
|
if (data and 64 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbr7() {
|
private fun iBbr7(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 128 == 0) regPC = fetchedAddressZpr
|
if (data and 128 == 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs0() {
|
private fun iBbs0(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 1 != 0) regPC = fetchedAddressZpr
|
if (data and 1 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs1() {
|
private fun iBbs1(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 2 != 0) regPC = fetchedAddressZpr
|
if (data and 2 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs2() {
|
private fun iBbs2(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 4 != 0) regPC = fetchedAddressZpr
|
if (data and 4 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs3() {
|
private fun iBbs3(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 8 != 0) regPC = fetchedAddressZpr
|
if (data and 8 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs4() {
|
private fun iBbs4(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 16 != 0) regPC = fetchedAddressZpr
|
if (data and 16 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs5() {
|
private fun iBbs5(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 32 != 0) regPC = fetchedAddressZpr
|
if (data and 32 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs6() {
|
private fun iBbs6(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 64 != 0) regPC = fetchedAddressZpr
|
if (data and 64 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iBbs7() {
|
private fun iBbs7(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
if (data and 128 != 0) regPC = fetchedAddressZpr
|
if (data and 128 != 0) {
|
||||||
|
regPC = fetchedAddressZpr
|
||||||
|
instrCycles++
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb0() {
|
private fun iSmb0(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 1)
|
write(fetchedAddress, data or 1)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb1() {
|
private fun iSmb1(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 2)
|
write(fetchedAddress, data or 2)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb2() {
|
private fun iSmb2(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 4)
|
write(fetchedAddress, data or 4)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb3() {
|
private fun iSmb3(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 8)
|
write(fetchedAddress, data or 8)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb4() {
|
private fun iSmb4(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 16)
|
write(fetchedAddress, data or 16)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb5() {
|
private fun iSmb5(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 32)
|
write(fetchedAddress, data or 32)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb6() {
|
private fun iSmb6(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 64)
|
write(fetchedAddress, data or 64)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iSmb7() {
|
private fun iSmb7(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data or 128)
|
write(fetchedAddress, data or 128)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb0() {
|
private fun iRmb0(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b11111110)
|
write(fetchedAddress, data and 0b11111110)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb1() {
|
private fun iRmb1(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b11111101)
|
write(fetchedAddress, data and 0b11111101)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb2() {
|
private fun iRmb2(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b11111011)
|
write(fetchedAddress, data and 0b11111011)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb3() {
|
private fun iRmb3(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b11110111)
|
write(fetchedAddress, data and 0b11110111)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb4() {
|
private fun iRmb4(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b11101111)
|
write(fetchedAddress, data and 0b11101111)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb5() {
|
private fun iRmb5(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b11011111)
|
write(fetchedAddress, data and 0b11011111)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb6() {
|
private fun iRmb6(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b10111111)
|
write(fetchedAddress, data and 0b10111111)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun iRmb7() {
|
private fun iRmb7(): Boolean {
|
||||||
val data = getFetched()
|
val data = getFetched()
|
||||||
write(fetchedAddress, data and 0b01111111)
|
write(fetchedAddress, data and 0b01111111)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,13 +72,4 @@ abstract class FunctionalTestsBase {
|
||||||
}
|
}
|
||||||
fail("test failed")
|
fail("test failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun runTestExpectNotImplemented(testprogram: String) {
|
|
||||||
try {
|
|
||||||
runTest(testprogram)
|
|
||||||
fail("expected to crash with NotImplementedError")
|
|
||||||
} catch(nx: NotImplementedError) {
|
|
||||||
// okay!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,24 @@ class Test6502CpuBasics {
|
||||||
totalCycles = cycles
|
totalCycles = cycles
|
||||||
instrCycles = 0
|
instrCycles = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun iAdc(): Boolean {
|
||||||
|
// NES cpu doesn't have BCD mode
|
||||||
|
val decimal = regP.D
|
||||||
|
regP.D = false
|
||||||
|
val result = super.iAdc()
|
||||||
|
regP.D = decimal
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun iSbc(operandOverride: Int?): Boolean {
|
||||||
|
// NES cpu doesn't have BCD mode
|
||||||
|
val decimal = regP.D
|
||||||
|
regP.D = false
|
||||||
|
val result = super.iSbc(operandOverride)
|
||||||
|
regP.D = decimal
|
||||||
|
return result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val cpu = NesCpu()
|
val cpu = NesCpu()
|
||||||
|
@ -245,21 +263,23 @@ class Test6502CpuBasics {
|
||||||
bus.reset()
|
bus.reset()
|
||||||
cpu.resetTotalCycles(7) // that is what the nes rom starts with
|
cpu.resetTotalCycles(7) // that is what the nes rom starts with
|
||||||
cpu.regPC = 0xc000
|
cpu.regPC = 0xc000
|
||||||
|
var tracingSnapshot = cpu.snapshot()
|
||||||
|
cpu.tracing = { tracingSnapshot=it }
|
||||||
|
|
||||||
val neslog = javaClass.getResource("nestest.log").readText().lineSequence()
|
val neslog = javaClass.getResource("nestest.log").readText().lineSequence()
|
||||||
for(logline in neslog) {
|
for(logline in neslog) {
|
||||||
val s = cpu.snapshot() // TODO use cpu.tracing instead
|
if(logline.isEmpty())
|
||||||
|
break
|
||||||
|
|
||||||
|
cpu.step()
|
||||||
|
|
||||||
val nesAddressHex = logline.substring(0, 4).toInt(16)
|
val nesAddressHex = logline.substring(0, 4).toInt(16)
|
||||||
assertEquals(nesAddressHex, s.PC)
|
assertEquals(nesAddressHex, tracingSnapshot.PC)
|
||||||
|
|
||||||
println("NES: $logline")
|
// println("NES: $logline")
|
||||||
val disassem = disassembler.disassembleOneInstruction(ram.data, s.PC, 0).first.substring(1)
|
// val disassem = disassembler.disassembleOneInstruction(ram.data, tracingSnapshot.PC, 0).first.substring(1)
|
||||||
val spaces = " ".substring(disassem.length-1)
|
// val spaces = " ".substring(disassem.length-1)
|
||||||
println("EMU: $disassem $spaces A:${hexB(s.A)} X:${hexB(s.X)} Y:${hexB(s.Y)} P:${hexB(s.P.asInt())} SP:${hexB(s.SP)} PPU: 0, 0 CYC:${s.cycles}")
|
// println("EMU: $disassem $spaces A:${hexB(tracingSnapshot.A)} X:${hexB(tracingSnapshot.X)} Y:${hexB(tracingSnapshot.Y)} P:${hexB(tracingSnapshot.P.asInt())} SP:${hexB(tracingSnapshot.SP)} PPU: 0, 0 CYC:${tracingSnapshot.cycles}")
|
||||||
|
|
||||||
// TODO use cpu.tracing, as per https://forums.nesdev.com/viewtopic.php?t=19117 (i.e. BEFORE instruction gets executed):
|
|
||||||
// "before fetching the first operation code byte, make an internal record of the program counter and other registers;
|
|
||||||
// after reading the final operand byte, log all the values you stored back in step (1) plus the full instruction and its disassembly."
|
|
||||||
|
|
||||||
val nesRegsLog = logline.substring(48).split(':')
|
val nesRegsLog = logline.substring(48).split(':')
|
||||||
val nesA = nesRegsLog[1].substring(0, 2).toShort(16)
|
val nesA = nesRegsLog[1].substring(0, 2).toShort(16)
|
||||||
|
@ -268,17 +288,16 @@ class Test6502CpuBasics {
|
||||||
val nesP = nesRegsLog[4].substring(0, 2).toInt(16)
|
val nesP = nesRegsLog[4].substring(0, 2).toInt(16)
|
||||||
val nesSP = nesRegsLog[5].substring(0, 2).toInt(16)
|
val nesSP = nesRegsLog[5].substring(0, 2).toInt(16)
|
||||||
val nesCycles = nesRegsLog[7].toLong()
|
val nesCycles = nesRegsLog[7].toLong()
|
||||||
assertEquals(nesA, s.A)
|
assertEquals(nesA, tracingSnapshot.A)
|
||||||
assertEquals(nesX, s.X)
|
assertEquals(nesX, tracingSnapshot.X)
|
||||||
assertEquals(nesY, s.Y)
|
assertEquals(nesY, tracingSnapshot.Y)
|
||||||
assertEquals(nesP, s.P.asInt())
|
assertEquals(nesP, tracingSnapshot.P.asInt())
|
||||||
assertEquals(nesSP, s.SP)
|
assertEquals(nesSP, tracingSnapshot.SP)
|
||||||
assertEquals(nesCycles, s.cycles)
|
assertEquals(nesCycles, tracingSnapshot.cycles)
|
||||||
cpu.step()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO test $02 and $03 for test results see http://www.qmtpro.com/~nes/misc/nestest.txt
|
val two = ram[0x02]
|
||||||
|
val three = ram[0x03]
|
||||||
fail("todo: test success condition")
|
assertEquals(0, two, "test failed, code ${hexB(two)} ${hexB(three)}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,10 +182,11 @@ class Test6502TestSuiteC64Specific {
|
||||||
runTest("cnto2")
|
runTest("cnto2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("tests c64 specific hardware")
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCputiming() {
|
fun testCputiming() {
|
||||||
runTest("cputiming") // TODO fix this test once the cycle times are correct?
|
runTest("cputiming")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -2,328 +2,328 @@ import org.junit.jupiter.api.parallel.Execution
|
||||||
import org.junit.jupiter.api.parallel.ExecutionMode
|
import org.junit.jupiter.api.parallel.ExecutionMode
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
// TODO: implement the illegal instructions and replace these tests with the 'real' runTest
|
// TODO: implement the still missing illegal instructions and replace these tests with the 'real' runTest
|
||||||
|
|
||||||
@Execution(ExecutionMode.CONCURRENT)
|
@Execution(ExecutionMode.CONCURRENT)
|
||||||
class Test6502TestSuiteIllegalInstructions: FunctionalTestsBase() {
|
class Test6502TestSuiteIllegalInstructions: FunctionalTestsBase() {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAlrb() {
|
fun testAlrb() {
|
||||||
runTestExpectNotImplemented("alrb")
|
runTest("alrb") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAncb() {
|
fun testAncb() {
|
||||||
runTestExpectNotImplemented("ancb")
|
runTest("ancb")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAneb() {
|
fun testAneb() {
|
||||||
runTestExpectNotImplemented("aneb")
|
runTest("aneb") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testArrb() {
|
fun testArrb() {
|
||||||
runTestExpectNotImplemented("arrb")
|
runTest("arrb") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsoa() {
|
fun testAsoa() {
|
||||||
runTestExpectNotImplemented("asoa")
|
runTest("asoa")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsoax() {
|
fun testAsoax() {
|
||||||
runTestExpectNotImplemented("asoax")
|
runTest("asoax")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsoay() {
|
fun testAsoay() {
|
||||||
runTestExpectNotImplemented("asoay")
|
runTest("asoay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsoix() {
|
fun testAsoix() {
|
||||||
runTestExpectNotImplemented("asoix")
|
runTest("asoix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsoiy() {
|
fun testAsoiy() {
|
||||||
runTestExpectNotImplemented("asoiy")
|
runTest("asoiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsoz() {
|
fun testAsoz() {
|
||||||
runTestExpectNotImplemented("asoz")
|
runTest("asoz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAsozx() {
|
fun testAsozx() {
|
||||||
runTestExpectNotImplemented("asozx")
|
runTest("asozx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAxsa() {
|
fun testAxsa() {
|
||||||
runTestExpectNotImplemented("axsa")
|
runTest("axsa")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAxsix() {
|
fun testAxsix() {
|
||||||
runTestExpectNotImplemented("axsix")
|
runTest("axsix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAxsz() {
|
fun testAxsz() {
|
||||||
runTestExpectNotImplemented("axsz")
|
runTest("axsz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAxszy() {
|
fun testAxszy() {
|
||||||
runTestExpectNotImplemented("axszy")
|
runTest("axszy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcma() {
|
fun testDcma() {
|
||||||
runTestExpectNotImplemented("dcma")
|
runTest("dcma")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcmax() {
|
fun testDcmax() {
|
||||||
runTestExpectNotImplemented("dcmax")
|
runTest("dcmax")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcmay() {
|
fun testDcmay() {
|
||||||
runTestExpectNotImplemented("dcmay")
|
runTest("dcmay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcmix() {
|
fun testDcmix() {
|
||||||
runTestExpectNotImplemented("dcmix")
|
runTest("dcmix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcmiy() {
|
fun testDcmiy() {
|
||||||
runTestExpectNotImplemented("dcmiy")
|
runTest("dcmiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcmz() {
|
fun testDcmz() {
|
||||||
runTestExpectNotImplemented("dcmz")
|
runTest("dcmz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDcmzx() {
|
fun testDcmzx() {
|
||||||
runTestExpectNotImplemented("dcmzx")
|
runTest("dcmzx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInsa() {
|
fun testInsa() {
|
||||||
runTestExpectNotImplemented("insa")
|
runTest("insa")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInsax() {
|
fun testInsax() {
|
||||||
runTestExpectNotImplemented("insax")
|
runTest("insax")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInsay() {
|
fun testInsay() {
|
||||||
runTestExpectNotImplemented("insay")
|
runTest("insay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInsix() {
|
fun testInsix() {
|
||||||
runTestExpectNotImplemented("insix")
|
runTest("insix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInsiy() {
|
fun testInsiy() {
|
||||||
runTestExpectNotImplemented("insiy")
|
runTest("insiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInsz() {
|
fun testInsz() {
|
||||||
runTestExpectNotImplemented("insz")
|
runTest("insz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInszx() {
|
fun testInszx() {
|
||||||
runTestExpectNotImplemented("inszx")
|
runTest("inszx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLasay() {
|
fun testLasay() {
|
||||||
runTestExpectNotImplemented("lasay")
|
runTest("lasay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLaxa() {
|
fun testLaxa() {
|
||||||
runTestExpectNotImplemented("laxa")
|
runTest("laxa")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLaxay() {
|
fun testLaxay() {
|
||||||
runTestExpectNotImplemented("laxay")
|
runTest("laxay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLaxix() {
|
fun testLaxix() {
|
||||||
runTestExpectNotImplemented("laxix")
|
runTest("laxix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLaxiy() {
|
fun testLaxiy() {
|
||||||
runTestExpectNotImplemented("laxiy")
|
runTest("laxiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLaxz() {
|
fun testLaxz() {
|
||||||
runTestExpectNotImplemented("laxz")
|
runTest("laxz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLaxzy() {
|
fun testLaxzy() {
|
||||||
runTestExpectNotImplemented("laxzy")
|
runTest("laxzy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLsea() {
|
fun testLsea() {
|
||||||
runTestExpectNotImplemented("lsea")
|
runTest("lsea")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLseax() {
|
fun testLseax() {
|
||||||
runTestExpectNotImplemented("lseax")
|
runTest("lseax")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLseay() {
|
fun testLseay() {
|
||||||
runTestExpectNotImplemented("lseay")
|
runTest("lseay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLseix() {
|
fun testLseix() {
|
||||||
runTestExpectNotImplemented("lseix")
|
runTest("lseix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLseiy() {
|
fun testLseiy() {
|
||||||
runTestExpectNotImplemented("lseiy")
|
runTest("lseiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLsez() {
|
fun testLsez() {
|
||||||
runTestExpectNotImplemented("lsez")
|
runTest("lsez")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLsezx() {
|
fun testLsezx() {
|
||||||
runTestExpectNotImplemented("lsezx")
|
runTest("lsezx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLxab() {
|
fun testLxab() {
|
||||||
runTestExpectNotImplemented("lxab")
|
runTest("lxab") // TODO fix something?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlaa() {
|
fun testRlaa() {
|
||||||
runTestExpectNotImplemented("rlaa")
|
runTest("rlaa")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlaax() {
|
fun testRlaax() {
|
||||||
runTestExpectNotImplemented("rlaax")
|
runTest("rlaax")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlaay() {
|
fun testRlaay() {
|
||||||
runTestExpectNotImplemented("rlaay")
|
runTest("rlaay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlaix() {
|
fun testRlaix() {
|
||||||
runTestExpectNotImplemented("rlaix")
|
runTest("rlaix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlaiy() {
|
fun testRlaiy() {
|
||||||
runTestExpectNotImplemented("rlaiy")
|
runTest("rlaiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlaz() {
|
fun testRlaz() {
|
||||||
runTestExpectNotImplemented("rlaz")
|
runTest("rlaz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRlazx() {
|
fun testRlazx() {
|
||||||
runTestExpectNotImplemented("rlazx")
|
runTest("rlazx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRraa() {
|
fun testRraa() {
|
||||||
runTestExpectNotImplemented("rraa")
|
runTest("rraa")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRraax() {
|
fun testRraax() {
|
||||||
runTestExpectNotImplemented("rraax")
|
runTest("rraax")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRraay() {
|
fun testRraay() {
|
||||||
runTestExpectNotImplemented("rraay")
|
runTest("rraay")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRraix() {
|
fun testRraix() {
|
||||||
runTestExpectNotImplemented("rraix")
|
runTest("rraix")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRraiy() {
|
fun testRraiy() {
|
||||||
runTestExpectNotImplemented("rraiy")
|
runTest("rraiy")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRraz() {
|
fun testRraz() {
|
||||||
runTestExpectNotImplemented("rraz")
|
runTest("rraz")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRrazx() {
|
fun testRrazx() {
|
||||||
runTestExpectNotImplemented("rrazx")
|
runTest("rrazx")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSbxb() {
|
fun testSbxb() {
|
||||||
runTestExpectNotImplemented("sbxb")
|
runTest("sbxb") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testShaay() {
|
fun testShaay() {
|
||||||
runTestExpectNotImplemented("shaay")
|
runTest("shaay") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testShaiy() {
|
fun testShaiy() {
|
||||||
runTestExpectNotImplemented("shaiy")
|
runTest("shaiy") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testShsay() {
|
fun testShsay() {
|
||||||
runTestExpectNotImplemented("shsay")
|
runTest("shsay") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testShxay() {
|
fun testShxay() {
|
||||||
runTestExpectNotImplemented("shxay")
|
runTest("shxay") // TODO fix?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testShyax() {
|
fun testShyax() {
|
||||||
runTestExpectNotImplemented("shyax")
|
runTest("shyax") // TODO fix?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user