mirror of
https://github.com/irmen/ksim65.git
synced 2024-11-16 16:04:53 +00:00
prepare for extra cycles in addrmode/instructions
This commit is contained in:
parent
e5e41d053e
commit
ca2eede585
@ -9,7 +9,6 @@ import razorvine.ksim65.components.UByte
|
||||
/**
|
||||
* 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
|
||||
* TODO: add the optional additional cycles to certain instructions and addressing modes
|
||||
*/
|
||||
open class Cpu6502 : BusComponent() {
|
||||
open val name = "6502"
|
||||
@ -285,8 +284,10 @@ open class Cpu6502 : BusComponent() {
|
||||
|
||||
regPC++
|
||||
instrCycles = currentInstruction.cycles
|
||||
applyAddressingMode(currentInstruction.mode)
|
||||
dispatchOpcode(currentOpcode)
|
||||
val extraCycleFromAddr = applyAddressingMode(currentInstruction.mode)
|
||||
val extraCycleFromInstr = dispatchOpcode(currentOpcode)
|
||||
if(extraCycleFromAddr and extraCycleFromInstr)
|
||||
instrCycles++
|
||||
}
|
||||
|
||||
instrCycles--
|
||||
@ -631,45 +632,57 @@ open class Cpu6502 : BusComponent() {
|
||||
/* fe */ Instruction("inc", AddrMode.AbsX, 7),
|
||||
/* ff */ Instruction("isc", AddrMode.AbsX, 7)).toTypedArray()
|
||||
|
||||
protected open fun applyAddressingMode(addrMode: AddrMode) {
|
||||
when (addrMode) {
|
||||
protected open fun applyAddressingMode(addrMode: AddrMode): Boolean {
|
||||
// an addressing mode can cause an extra clock cycle on certain instructions
|
||||
return when (addrMode) {
|
||||
AddrMode.Imp, AddrMode.Acc -> {
|
||||
fetchedData = regA
|
||||
false
|
||||
}
|
||||
AddrMode.Imm -> {
|
||||
fetchedData = readPc()
|
||||
false
|
||||
}
|
||||
AddrMode.Zp -> {
|
||||
fetchedAddress = readPc()
|
||||
false
|
||||
}
|
||||
AddrMode.ZpX -> {
|
||||
// note: zeropage index will not leave Zp when page boundary is crossed
|
||||
fetchedAddress = (readPc()+regX) and 0xff
|
||||
false
|
||||
}
|
||||
AddrMode.ZpY -> {
|
||||
// note: zeropage index will not leave Zp when page boundary is crossed
|
||||
fetchedAddress = (readPc()+regY) and 0xff
|
||||
false
|
||||
}
|
||||
AddrMode.Rel -> {
|
||||
val relative = readPc()
|
||||
fetchedAddress = if (relative >= 0x80) {
|
||||
regPC-(256-relative) and 0xffff
|
||||
} else regPC+relative and 0xffff
|
||||
false
|
||||
}
|
||||
AddrMode.Abs -> {
|
||||
val lo = readPc()
|
||||
val hi = readPc()
|
||||
fetchedAddress = lo or (hi shl 8)
|
||||
false
|
||||
}
|
||||
AddrMode.AbsX -> {
|
||||
val lo = readPc()
|
||||
val hi = readPc()
|
||||
fetchedAddress = regX+(lo or (hi shl 8)) and 0xffff
|
||||
// if this address is a different page, extra clock cycle:
|
||||
(fetchedAddress and 0xff00) != hi shl 8
|
||||
}
|
||||
AddrMode.AbsY -> {
|
||||
val lo = readPc()
|
||||
val hi = readPc()
|
||||
fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff
|
||||
// if this address is a different page, extra clock cycle:
|
||||
(fetchedAddress and 0xff00) != hi shl 8
|
||||
}
|
||||
AddrMode.Ind -> {
|
||||
var lo = readPc()
|
||||
@ -686,6 +699,7 @@ open class Cpu6502 : BusComponent() {
|
||||
hi = read(fetchedAddress+1)
|
||||
}
|
||||
fetchedAddress = lo or (hi shl 8)
|
||||
false
|
||||
}
|
||||
AddrMode.IzX -> {
|
||||
// note: not able to fetch an address which crosses the (zero)page boundary
|
||||
@ -693,6 +707,7 @@ open class Cpu6502 : BusComponent() {
|
||||
val lo = read((fetchedAddress+regX) and 0xff)
|
||||
val hi = read((fetchedAddress+regX+1) and 0xff)
|
||||
fetchedAddress = lo or (hi shl 8)
|
||||
false
|
||||
}
|
||||
AddrMode.IzY -> {
|
||||
// note: not able to fetch an address which crosses the (zero)page boundary
|
||||
@ -700,6 +715,7 @@ open class Cpu6502 : BusComponent() {
|
||||
val lo = read(fetchedAddress)
|
||||
val hi = read((fetchedAddress+1) and 0xff)
|
||||
fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff
|
||||
false
|
||||
}
|
||||
AddrMode.Zpr, AddrMode.Izp, AddrMode.IaX -> {
|
||||
// addressing mode used by the 65C02 only
|
||||
@ -708,7 +724,7 @@ open class Cpu6502 : BusComponent() {
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun dispatchOpcode(opcode: Int) {
|
||||
protected open fun dispatchOpcode(opcode: Int): Boolean {
|
||||
when (opcode) {
|
||||
0x00 -> iBrk()
|
||||
0x01 -> iOra()
|
||||
@ -966,9 +982,9 @@ open class Cpu6502 : BusComponent() {
|
||||
0xfd -> iSbc()
|
||||
0xfe -> iInc()
|
||||
0xff -> iIsc()
|
||||
else -> { /* can't occur */
|
||||
}
|
||||
else -> { /* can't occur */ }
|
||||
}
|
||||
return false // TODO determine if instructions can cause extra clock cycle
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,7 +4,6 @@ import razorvine.ksim65.components.Address
|
||||
|
||||
/**
|
||||
* 65C02 cpu simulation (the CMOS version of the 6502).
|
||||
* TODO: add the optional additional cycles to certain instructions and addressing modes
|
||||
*/
|
||||
class Cpu65C02 : Cpu6502() {
|
||||
override val name = "65C02"
|
||||
@ -56,9 +55,10 @@ class Cpu65C02 : Cpu6502() {
|
||||
// branch-relative address fetched by the ZpR addressing mode
|
||||
private var fetchedAddressZpr: Address = 0
|
||||
|
||||
override fun applyAddressingMode(addrMode: AddrMode) {
|
||||
when (addrMode) {
|
||||
AddrMode.Imp, AddrMode.Acc, AddrMode.Imm, AddrMode.Zp, AddrMode.ZpX, AddrMode.ZpY, AddrMode.Rel, AddrMode.Abs, AddrMode.AbsX, AddrMode.AbsY, AddrMode.IzX, AddrMode.IzY -> {
|
||||
override fun applyAddressingMode(addrMode: AddrMode): Boolean {
|
||||
return when (addrMode) {
|
||||
AddrMode.Imp, AddrMode.Acc, AddrMode.Imm, AddrMode.Zp, AddrMode.ZpX, AddrMode.ZpY,
|
||||
AddrMode.Rel, AddrMode.Abs, AddrMode.AbsX, AddrMode.AbsY, AddrMode.IzX, AddrMode.IzY -> {
|
||||
super.applyAddressingMode(addrMode)
|
||||
}
|
||||
AddrMode.Ind -> {
|
||||
@ -69,15 +69,16 @@ class Cpu65C02 : Cpu6502() {
|
||||
lo = read(fetchedAddress)
|
||||
hi = read(fetchedAddress+1)
|
||||
fetchedAddress = lo or (hi shl 8)
|
||||
false
|
||||
}
|
||||
AddrMode.Zpr -> {
|
||||
// addressing mode used by the 65C02 only
|
||||
// combination of zp addresssing + relative branch addressing
|
||||
// combination of zp addressing + relative branch addressing
|
||||
fetchedAddress = readPc()
|
||||
val relative = readPc()
|
||||
fetchedAddressZpr = if (relative >= 0x80) {
|
||||
regPC-(256-relative) and 0xffff
|
||||
} else regPC+relative and 0xffff
|
||||
fetchedAddressZpr =
|
||||
if (relative >= 0x80) regPC-(256-relative) and 0xffff else regPC+relative and 0xffff
|
||||
false
|
||||
}
|
||||
AddrMode.Izp -> {
|
||||
// addressing mode used by the 65C02 only
|
||||
@ -85,6 +86,7 @@ class Cpu65C02 : Cpu6502() {
|
||||
val lo = read((fetchedAddress) and 0xff)
|
||||
val hi = read((fetchedAddress+1) and 0xff)
|
||||
fetchedAddress = lo or (hi shl 8)
|
||||
false
|
||||
}
|
||||
AddrMode.IaX -> {
|
||||
// addressing mode used by the 65C02 only
|
||||
@ -94,11 +96,13 @@ class Cpu65C02 : Cpu6502() {
|
||||
lo = read((fetchedAddress+regX) and 0xffff)
|
||||
hi = read((fetchedAddress+regX+1) and 0xffff)
|
||||
fetchedAddress = lo or (hi shl 8)
|
||||
// if this address is a different page, extra clock cycle:
|
||||
(fetchedAddress and 0xff00) != hi shl 8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun dispatchOpcode(opcode: Int) {
|
||||
override fun dispatchOpcode(opcode: Int): Boolean {
|
||||
when (opcode) {
|
||||
0x00 -> iBrk()
|
||||
0x01 -> iOra()
|
||||
@ -356,9 +360,9 @@ class Cpu65C02 : Cpu6502() {
|
||||
0xfd -> iSbc()
|
||||
0xfe -> iInc()
|
||||
0xff -> iBbs7()
|
||||
else -> { /* can't occur */
|
||||
}
|
||||
else -> { /* can't occur */ }
|
||||
}
|
||||
return false // TODO determine if instructions can cause extra clock cycle
|
||||
}
|
||||
|
||||
// opcode list: http://www.oxyron.de/html/opcodesc02.html
|
||||
|
Loading…
Reference in New Issue
Block a user