1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-01 21:41:31 +00:00

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 // timer A is enabled, assume system cycles counting for now
timerAactual-- timerAactual--
if (timerAactual == 0 && timerAinterruptEnabled) { if (timerAactual == 0 && timerAinterruptEnabled) {
if (number == 1) cpu.irq() if (number == 1) cpu.irqAsserted = true
else if (number == 2) cpu.nmi() else if (number == 2) cpu.nmiAsserted = true
} }
if (timerAactual < 0) timerAactual = if (ramBuffer[0x0e].toInt() and 0b00001000 != 0) 0 else timerAset 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-- timerBactual--
} }
if (timerBactual == 0 && timerBinterruptEnabled) { if (timerBactual == 0 && timerBinterruptEnabled) {
if (number == 1) cpu.irq() if (number == 1) cpu.irqAsserted = true
else if (number == 2) cpu.nmi() else if (number == 2) cpu.nmiAsserted = true
} }
if (timerBactual < 0) timerBactual = if (regCRB and 0b00001000 != 0) 0 else timerBset 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) { override fun keyPressed(event: KeyEvent) {
// '\' is mapped as RESTORE, this causes a NMI on the cpu // '\' is mapped as RESTORE, this causes a NMI on the cpu
if (event.keyChar == '\\') { if (event.keyChar == '\\') {
cpu.nmi() cpu.nmiAsserted = true
} else { } else {
keypressCia.hostKeyPressed(event) keypressCia.hostKeyPressed(event)
} }

View File

@ -38,7 +38,7 @@ class VicII(startAddress: Address, endAddress: Address, val cpu: Cpu6502) : MemM
interruptStatusRegisterD019 = if (currentRasterLine == rasterIrqLine) { interruptStatusRegisterD019 = if (currentRasterLine == rasterIrqLine) {
// signal that current raster line is equal to the desired IRQ raster line // signal that current raster line is equal to the desired IRQ raster line
// schedule an IRQ as well if the raster interrupt is enabled // 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 interruptStatusRegisterD019 or 0b10000001
} else interruptStatusRegisterD019 and 0b11111110 } else interruptStatusRegisterD019 and 0b11111110
} }

View File

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

View File

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

View File

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

View File

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

View File

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