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:
parent
c327c59c8b
commit
3f86d5185e
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
Loading…
Reference in New Issue
Block a user