1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-06-06 22:29:33 +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.
* 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
}

View File

@ -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