1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-26 02:29:38 +00:00

prepare for extra cycles in addrmode/instructions

This commit is contained in:
Irmen de Jong 2019-10-15 22:28:48 +02:00
parent e5e41d053e
commit ca2eede585
2 changed files with 39 additions and 19 deletions

View File

@ -9,7 +9,6 @@ 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 * 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 class Cpu6502 : BusComponent() {
open val name = "6502" open val name = "6502"
@ -285,8 +284,10 @@ open class Cpu6502 : BusComponent() {
regPC++ regPC++
instrCycles = currentInstruction.cycles instrCycles = currentInstruction.cycles
applyAddressingMode(currentInstruction.mode) val extraCycleFromAddr = applyAddressingMode(currentInstruction.mode)
dispatchOpcode(currentOpcode) val extraCycleFromInstr = dispatchOpcode(currentOpcode)
if(extraCycleFromAddr and extraCycleFromInstr)
instrCycles++
} }
instrCycles-- instrCycles--
@ -631,45 +632,57 @@ open class Cpu6502 : BusComponent() {
/* fe */ Instruction("inc", AddrMode.AbsX, 7), /* fe */ Instruction("inc", AddrMode.AbsX, 7),
/* ff */ Instruction("isc", AddrMode.AbsX, 7)).toTypedArray() /* ff */ Instruction("isc", AddrMode.AbsX, 7)).toTypedArray()
protected open fun applyAddressingMode(addrMode: AddrMode) { protected open fun applyAddressingMode(addrMode: AddrMode): Boolean {
when (addrMode) { // an addressing mode can cause an extra clock cycle on certain instructions
return when (addrMode) {
AddrMode.Imp, AddrMode.Acc -> { AddrMode.Imp, AddrMode.Acc -> {
fetchedData = regA fetchedData = regA
false
} }
AddrMode.Imm -> { AddrMode.Imm -> {
fetchedData = readPc() fetchedData = readPc()
false
} }
AddrMode.Zp -> { AddrMode.Zp -> {
fetchedAddress = readPc() fetchedAddress = readPc()
false
} }
AddrMode.ZpX -> { AddrMode.ZpX -> {
// note: zeropage index will not leave Zp when page boundary is crossed // note: zeropage index will not leave Zp when page boundary is crossed
fetchedAddress = (readPc()+regX) and 0xff fetchedAddress = (readPc()+regX) and 0xff
false
} }
AddrMode.ZpY -> { AddrMode.ZpY -> {
// note: zeropage index will not leave Zp when page boundary is crossed // note: zeropage index will not leave Zp when page boundary is crossed
fetchedAddress = (readPc()+regY) and 0xff fetchedAddress = (readPc()+regY) and 0xff
false
} }
AddrMode.Rel -> { AddrMode.Rel -> {
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
} }
AddrMode.Abs -> { AddrMode.Abs -> {
val lo = readPc() val lo = readPc()
val hi = readPc() val hi = readPc()
fetchedAddress = lo or (hi shl 8) fetchedAddress = lo or (hi shl 8)
false
} }
AddrMode.AbsX -> { AddrMode.AbsX -> {
val lo = readPc() val lo = readPc()
val hi = readPc() val hi = readPc()
fetchedAddress = regX+(lo or (hi shl 8)) and 0xffff 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 -> { AddrMode.AbsY -> {
val lo = readPc() val lo = readPc()
val hi = readPc() val hi = readPc()
fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff 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 -> { AddrMode.Ind -> {
var lo = readPc() var lo = readPc()
@ -686,6 +699,7 @@ open class Cpu6502 : BusComponent() {
hi = read(fetchedAddress+1) hi = read(fetchedAddress+1)
} }
fetchedAddress = lo or (hi shl 8) fetchedAddress = lo or (hi shl 8)
false
} }
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
@ -693,6 +707,7 @@ 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
} }
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
@ -700,6 +715,7 @@ open class Cpu6502 : BusComponent() {
val lo = read(fetchedAddress) val lo = read(fetchedAddress)
val hi = read((fetchedAddress+1) and 0xff) val hi = read((fetchedAddress+1) and 0xff)
fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff fetchedAddress = regY+(lo or (hi shl 8)) and 0xffff
false
} }
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
@ -708,7 +724,7 @@ open class Cpu6502 : BusComponent() {
} }
} }
protected open fun dispatchOpcode(opcode: Int) { protected open fun dispatchOpcode(opcode: Int): Boolean {
when (opcode) { when (opcode) {
0x00 -> iBrk() 0x00 -> iBrk()
0x01 -> iOra() 0x01 -> iOra()
@ -966,9 +982,9 @@ open class Cpu6502 : BusComponent() {
0xfd -> iSbc() 0xfd -> iSbc()
0xfe -> iInc() 0xfe -> iInc()
0xff -> iIsc() 0xff -> iIsc()
else -> { /* can't occur */ else -> { /* can't occur */ }
}
} }
return false // TODO determine if instructions can cause extra clock cycle
} }

View File

@ -4,7 +4,6 @@ import razorvine.ksim65.components.Address
/** /**
* 65C02 cpu simulation (the CMOS version of the 6502). * 65C02 cpu simulation (the CMOS version of the 6502).
* TODO: add the optional additional cycles to certain instructions and addressing modes
*/ */
class Cpu65C02 : Cpu6502() { class Cpu65C02 : Cpu6502() {
override val name = "65C02" override val name = "65C02"
@ -56,9 +55,10 @@ class Cpu65C02 : Cpu6502() {
// branch-relative address fetched by the ZpR addressing mode // branch-relative address fetched by the ZpR addressing mode
private var fetchedAddressZpr: Address = 0 private var fetchedAddressZpr: Address = 0
override fun applyAddressingMode(addrMode: AddrMode) { override fun applyAddressingMode(addrMode: AddrMode): Boolean {
when (addrMode) { 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 -> { 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) super.applyAddressingMode(addrMode)
} }
AddrMode.Ind -> { AddrMode.Ind -> {
@ -69,15 +69,16 @@ class Cpu65C02 : Cpu6502() {
lo = read(fetchedAddress) lo = read(fetchedAddress)
hi = read(fetchedAddress+1) hi = read(fetchedAddress+1)
fetchedAddress = lo or (hi shl 8) fetchedAddress = lo or (hi shl 8)
false
} }
AddrMode.Zpr -> { AddrMode.Zpr -> {
// addressing mode used by the 65C02 only // addressing mode used by the 65C02 only
// combination of zp addresssing + relative branch addressing // combination of zp addressing + relative branch addressing
fetchedAddress = readPc() fetchedAddress = readPc()
val relative = readPc() val relative = readPc()
fetchedAddressZpr = if (relative >= 0x80) { fetchedAddressZpr =
regPC-(256-relative) and 0xffff if (relative >= 0x80) regPC-(256-relative) and 0xffff else regPC+relative and 0xffff
} else regPC+relative and 0xffff false
} }
AddrMode.Izp -> { AddrMode.Izp -> {
// addressing mode used by the 65C02 only // addressing mode used by the 65C02 only
@ -85,6 +86,7 @@ class Cpu65C02 : Cpu6502() {
val lo = read((fetchedAddress) and 0xff) val lo = read((fetchedAddress) and 0xff)
val hi = read((fetchedAddress+1) and 0xff) val hi = read((fetchedAddress+1) and 0xff)
fetchedAddress = lo or (hi shl 8) fetchedAddress = lo or (hi shl 8)
false
} }
AddrMode.IaX -> { AddrMode.IaX -> {
// addressing mode used by the 65C02 only // addressing mode used by the 65C02 only
@ -94,11 +96,13 @@ class Cpu65C02 : Cpu6502() {
lo = read((fetchedAddress+regX) and 0xffff) lo = read((fetchedAddress+regX) and 0xffff)
hi = read((fetchedAddress+regX+1) and 0xffff) hi = read((fetchedAddress+regX+1) and 0xffff)
fetchedAddress = lo or (hi shl 8) 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) { when (opcode) {
0x00 -> iBrk() 0x00 -> iBrk()
0x01 -> iOra() 0x01 -> iOra()
@ -356,9 +360,9 @@ class Cpu65C02 : Cpu6502() {
0xfd -> iSbc() 0xfd -> iSbc()
0xfe -> iInc() 0xfe -> iInc()
0xff -> iBbs7() 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 // opcode list: http://www.oxyron.de/html/opcodesc02.html