cpu irq/nmi now via "pin assert" instead of pending statuses

This commit is contained in:
Irmen de Jong 2020-02-16 16:01:41 +01:00
parent c327c59c8b
commit 3f86d5185e
8 changed files with 28 additions and 35 deletions

View File

@ -92,8 +92,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
// timer A is enabled, assume system cycles counting for now
timerAactual--
if (timerAactual == 0 && timerAinterruptEnabled) {
if (number == 1) cpu.irq()
else if (number == 2) cpu.nmi()
if (number == 1) cpu.irqAsserted = true
else if (number == 2) cpu.nmiAsserted = true
}
if (timerAactual < 0) timerAactual = if (ramBuffer[0x0e].toInt() and 0b00001000 != 0) 0 else timerAset
}
@ -108,8 +108,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
timerBactual--
}
if (timerBactual == 0 && timerBinterruptEnabled) {
if (number == 1) cpu.irq()
else if (number == 2) cpu.nmi()
if (number == 1) cpu.irqAsserted = true
else if (number == 2) cpu.nmiAsserted = true
}
if (timerBactual < 0) timerBactual = if (regCRB and 0b00001000 != 0) 0 else timerBset
}

View File

@ -85,7 +85,7 @@ class MainC64Window(title: String, chargen: Rom, val ram: MemoryComponent, val c
override fun keyPressed(event: KeyEvent) {
// '\' is mapped as RESTORE, this causes a NMI on the cpu
if (event.keyChar == '\\') {
cpu.nmi()
cpu.nmiAsserted = true
} else {
keypressCia.hostKeyPressed(event)
}

View File

@ -38,7 +38,7 @@ class VicII(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
interruptStatusRegisterD019 = if (currentRasterLine == rasterIrqLine) {
// signal that current raster line is equal to the desired IRQ raster line
// schedule an IRQ as well if the raster interrupt is enabled
if ((ramBuffer[0x1a].toInt() and 1) != 0) cpu.irq()
if ((ramBuffer[0x1a].toInt() and 1) != 0) cpu.irqAsserted = true
interruptStatusRegisterD019 or 0b10000001
} else interruptStatusRegisterD019 and 0b11111110
}

View File

@ -190,8 +190,8 @@ class DebugWindow(private val vm: IVirtualMachine) : JFrame("Debugger - ksim65 v
pauseBt.actionCommand = "pause"
pauseBt.text = "Pause"
}
"irq" -> vm.cpu.irq()
"nmi" -> vm.cpu.nmi()
"irq" -> vm.cpu.irqAsserted = true
"nmi" -> vm.cpu.nmiAsserted = true
"quit" -> {
dispatchEvent(WindowEvent(this, WindowEvent.WINDOW_CLOSING))
}

View File

@ -92,6 +92,8 @@ open class Cpu6502 : BusComponent() {
var regSP: Int = 0
var regPC: Address = 0
val regP = StatusRegister()
var irqAsserted = false
var nmiAsserted = false
var currentOpcode: Int = 0
protected set
var currentOpcodeAddress: Address = 0 // the PC can be changed already depending on the addressing mode
@ -100,7 +102,7 @@ open class Cpu6502 : BusComponent() {
protected set
val isLooping: Boolean get() {
// jump loop detection
return (previousOpcodeAddress == currentOpcodeAddress) && !(pendingNMI || pendingIRQ)
return (previousOpcodeAddress == currentOpcodeAddress) && !(nmiAsserted || irqAsserted)
}
private var previousOpcodeAddress: Address = 0xffff
@ -115,9 +117,6 @@ open class Cpu6502 : BusComponent() {
return State(regA.toShort(), regX.toShort(), regY.toShort(), regSP, status, regPC, totalCycles)
}
protected var pendingIRQ = false
protected var pendingNMI = false
// data byte from the instruction (only set when addr.mode is Accumulator, Immediate or Implied)
protected var fetchedData: Int = 0
@ -262,7 +261,7 @@ open class Cpu6502 : BusComponent() {
*/
override fun clock() {
if (instrCycles == 0) {
if(pendingNMI || (pendingIRQ && !regP.I)) {
if(nmiAsserted || (irqAsserted && !regP.I)) {
handleInterrupt()
return
}
@ -329,14 +328,6 @@ open class Cpu6502 : BusComponent() {
instrCycles = 0
}
fun nmi() {
pendingNMI = true
}
fun irq() {
pendingIRQ = true
}
protected fun getFetched() =
if (currentInstruction.mode == AddrMode.Imm || currentInstruction.mode == AddrMode.Acc || currentInstruction.mode == AddrMode.Imp) fetchedData
else read(fetchedAddress)
@ -1079,7 +1070,7 @@ open class Cpu6502 : BusComponent() {
protected open fun iBrk() {
// handle BRK ('software interrupt')
regPC++
if(pendingNMI)
if(nmiAsserted)
return // if an NMI occurs during BRK, the BRK won't get executed on 6502 (65C02 fixes this)
pushStackAddr(regPC)
regP.B = true
@ -1098,12 +1089,14 @@ open class Cpu6502 : BusComponent() {
regP.I = true // interrupts are now disabled
// NMOS 6502 doesn't clear the D flag (CMOS 65C02 version does...)
if(pendingNMI) {
// jump to the appropriate irq vector and clear the assertion status of the irq
// (hmm... should the cpu do that? or is this the peripheral's job?)
if(nmiAsserted) {
regPC = readWord(NMI_vector)
pendingNMI = false
nmiAsserted = false
} else {
regPC = readWord(IRQ_vector)
pendingIRQ = false
irqAsserted = false
}
}

View File

@ -23,14 +23,14 @@ class Cpu65C02 : Cpu6502() {
when (waiting) {
Wait.Normal -> super.clock()
Wait.Waiting -> {
if (pendingNMI || pendingIRQ) {
if (nmiAsserted || irqAsserted) {
// continue execution after hardware interrupt
waiting = Wait.Normal
instrCycles = 1
}
}
Wait.Stopped -> {
if (pendingNMI || pendingIRQ) {
if (nmiAsserted || irqAsserted) {
// jump to reset vector after hardware interrupt
regPC = readWord(RESET_vector)
}

View File

@ -33,8 +33,8 @@ class Timer(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
if (enabled && interval > 0) {
counter++
if (counter == interval) {
if (nmi) cpu.nmi()
else cpu.irq()
if (nmi) cpu.nmiAsserted = true
else cpu.irqAsserted = true
counter = 0
}
}

View File

@ -96,19 +96,19 @@ class Test6502Klaus2m5Functional {
1 -> {
// println("IRQ at pc ${hexW(cpu.regPC)}")
lastIRQpc = cpu.regPC
cpu.irq()
cpu.irqAsserted = true
}
2 -> {
// println("NMI at pc ${hexW(cpu.regPC)}")
lastNMIpc = cpu.regPC
cpu.nmi()
cpu.nmiAsserted = true
}
3 -> {
// println("IRQ+NMI at pc ${hexW(cpu.regPC)}")
lastIRQpc = cpu.regPC
lastNMIpc = cpu.regPC
cpu.nmi()
cpu.irq()
cpu.nmiAsserted = true
cpu.irqAsserted = true
}
}
}
@ -154,7 +154,7 @@ class Test6502Klaus2m5Functional {
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0200
cpu.breakpointForBRK = { cpu, address ->
cpu.breakpointForBRK = { _, address ->
if(address==0x024b) { // test end address
val error=bus.read(0x000b) // the 'ERROR' variable is stored here
if(error==0.toShort())
@ -189,7 +189,7 @@ class Test6502Klaus2m5Functional {
bus.add(ram)
cpu.reset()
cpu.regPC = 0x0200
cpu.breakpointForBRK = { cpu, address ->
cpu.breakpointForBRK = { _, address ->
if(address==0x024b) { // test end address
val error=bus.read(0x000b) // the 'ERROR' variable is stored here
if(error==0.toShort())