mirror of
https://github.com/irmen/ksim65.git
synced 2024-09-28 14:54: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.
|
* 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user