From df2e9fac8fbfa40455dafced0081083536d60c0e Mon Sep 17 00:00:00 2001 From: Felipe Lima Date: Sun, 21 Jun 2015 18:06:44 -0700 Subject: [PATCH] Adds jump instructions --- app/src/main/kotlin/android/emu6502/CPU.kt | 26 +++++++-- .../emu6502/instructions/BaseInstruction.kt | 24 +++++++++ .../android/emu6502/instructions/impl/JMP.kt | 12 +++++ .../android/emu6502/instructions/impl/JSR.kt | 17 ++++++ .../android/emu6502/instructions/impl/RTS.kt | 13 +++++ .../test/java/android/emu6502/CPUTest.java | 53 ++++++++++++++++++- 6 files changed, 139 insertions(+), 6 deletions(-) create mode 100644 app/src/main/kotlin/android/emu6502/instructions/impl/JMP.kt create mode 100644 app/src/main/kotlin/android/emu6502/instructions/impl/JSR.kt create mode 100644 app/src/main/kotlin/android/emu6502/instructions/impl/RTS.kt diff --git a/app/src/main/kotlin/android/emu6502/CPU.kt b/app/src/main/kotlin/android/emu6502/CPU.kt index d63ed6d..f9b42d8 100644 --- a/app/src/main/kotlin/android/emu6502/CPU.kt +++ b/app/src/main/kotlin/android/emu6502/CPU.kt @@ -41,7 +41,10 @@ class CPU(val memory: Memory) { Pair(Instruction.ORA, ORA(this)), Pair(Instruction.CPX, CPX(this)), Pair(Instruction.BRK, BRK(this)), - Pair(Instruction.BNE, BNE(this)) + Pair(Instruction.BNE, BNE(this)), + Pair(Instruction.JMP, JMP(this)), + Pair(Instruction.JSR, JSR(this)), + Pair(Instruction.RTS, RTS(this)) // Pair(Instruction.BPL, BPL(this)), // Pair(Instruction.BMI, BMI(this)), // Pair(Instruction.BVC, BVC(this)), @@ -61,8 +64,6 @@ class CPU(val memory: Memory) { // Pair(Instruction.CLD, CLD(this)), // Pair(Instruction.SED, SED(this)), // Pair(Instruction.INC, INC(this)), -// Pair(Instruction.JMP, JMP(this)), -// Pair(Instruction.JSR, JSR(this)), // Pair(Instruction.LSR, LSR(this)), // Pair(Instruction.NOP, NOP(this)), // Pair(Instruction.TXA, TXA(this)), @@ -73,7 +74,6 @@ class CPU(val memory: Memory) { // Pair(Instruction.ROR, ROR(this)), // Pair(Instruction.ROL, ROL(this)), // Pair(Instruction.RTI, RTI(this)), -// Pair(Instruction.RTS, RTS(this)), // Pair(Instruction.SBC, SBC(this)), // Pair(Instruction.TXS, TXS(this)), // Pair(Instruction.TSX, TSX(this)), @@ -248,6 +248,24 @@ class CPU(val memory: Memory) { P = P.or(0x40) } + fun stackPush(value: Int) { + memory.set(SP.and(0xff) + 0x100, value.and(0xff)) + SP-- + if (SP < 0) { + SP = SP.and(0xff) + Log.i(TAG, "6502 Stack filled! Wrapping...") + } + } + + fun stackPop(): Int { + SP++; + if (SP >= 0x100) { + SP = SP.and(0xff) + Log.i(TAG, "6502 Stack emptied! Wrapping...") + } + return memory.get(SP + 0x100) + } + /** * http://nesdev.com/6502.txt * Returns the processor flags in the format SV-BDIZC diff --git a/app/src/main/kotlin/android/emu6502/instructions/BaseInstruction.kt b/app/src/main/kotlin/android/emu6502/instructions/BaseInstruction.kt index 54476ab..7e857fc 100644 --- a/app/src/main/kotlin/android/emu6502/instructions/BaseInstruction.kt +++ b/app/src/main/kotlin/android/emu6502/instructions/BaseInstruction.kt @@ -18,38 +18,62 @@ open class BaseInstruction(private val instruction: Instruction, } open fun immediate() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with immediate addressing") } open fun zeroPage() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with zeroPage addressing") } open fun zeroPageX() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with zeroPageX addressing") } open fun zeroPageY() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with zeroPageY addressing") } open fun absolute() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with absolute addressing") } open fun absoluteX() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with absoluteX addressing") } open fun absoluteY() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with absoluteY addressing") } open fun indirect() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with indirect addressing") } open fun indirectX() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with indirectX addressing") } open fun indirectY() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with indirectY addressing") } open fun single() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with single addressing") } open fun branch() { + throw IllegalStateException("Instruction " + javaClass.getSimpleName() + " not implemented" + + " with branch addressing") } } diff --git a/app/src/main/kotlin/android/emu6502/instructions/impl/JMP.kt b/app/src/main/kotlin/android/emu6502/instructions/impl/JMP.kt new file mode 100644 index 0000000..558ccf2 --- /dev/null +++ b/app/src/main/kotlin/android/emu6502/instructions/impl/JMP.kt @@ -0,0 +1,12 @@ +package android.emu6502.instructions.impl + +import android.emu6502.CPU +import android.emu6502.instructions.BaseInstruction +import android.emu6502.instructions.Instruction + +/** JuMP */ +class JMP(private val cpu: CPU) : BaseInstruction(Instruction.JMP, cpu.instructionList) { + override fun absolute() { + cpu.PC = cpu.popWord() + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/android/emu6502/instructions/impl/JSR.kt b/app/src/main/kotlin/android/emu6502/instructions/impl/JSR.kt new file mode 100644 index 0000000..7dc7f03 --- /dev/null +++ b/app/src/main/kotlin/android/emu6502/instructions/impl/JSR.kt @@ -0,0 +1,17 @@ +package android.emu6502.instructions.impl + +import android.emu6502.CPU +import android.emu6502.instructions.BaseInstruction +import android.emu6502.instructions.Instruction + +/** Jump to SubRoutine */ +class JSR(private val cpu: CPU) : BaseInstruction(Instruction.JSR, cpu.instructionList) { + override fun absolute() { + val addr = cpu.popWord() + val currAddr = cpu.PC - 1 + cpu.stackPush(currAddr.shr(8).and(0xff)) + cpu.stackPush(currAddr.and(0xff)) + cpu.PC = addr + } +} + diff --git a/app/src/main/kotlin/android/emu6502/instructions/impl/RTS.kt b/app/src/main/kotlin/android/emu6502/instructions/impl/RTS.kt new file mode 100644 index 0000000..3bfe56b --- /dev/null +++ b/app/src/main/kotlin/android/emu6502/instructions/impl/RTS.kt @@ -0,0 +1,13 @@ +package android.emu6502.instructions.impl + +import android.emu6502.CPU +import android.emu6502.instructions.BaseInstruction +import android.emu6502.instructions.Instruction + +/** ReTurn from Subroutine */ +class RTS(private val cpu: CPU) : BaseInstruction(Instruction.RTS, cpu.instructionList) { + override fun single() { + cpu.PC = cpu.stackPop().or(cpu.stackPop().shl(8)) + 1 + } +} + diff --git a/app/src/test/java/android/emu6502/CPUTest.java b/app/src/test/java/android/emu6502/CPUTest.java index 2f6f552..a1fb5e0 100644 --- a/app/src/test/java/android/emu6502/CPUTest.java +++ b/app/src/test/java/android/emu6502/CPUTest.java @@ -1,9 +1,9 @@ package android.emu6502; -import com.google.common.collect.ImmutableList; - import android.emu6502.instructions.Symbols; +import com.google.common.collect.ImmutableList; + import org.junit.Before; import org.junit.Test; @@ -61,6 +61,7 @@ public class CPUTest { @Test public void testBranchAndLabel() { List lines = ImmutableList.of( "LDX #$08", + "decrement:", "DEX", "STX $0200", @@ -77,4 +78,52 @@ public class CPUTest { assertThat(cpu.getPC(), equalTo(0x060e)); assertThat(cpu.flags(), equalTo("00110011")); } + + @Test public void testJump() { + List lines = ImmutableList.of( + "LDA #$03", + "JMP there", + "BRK", + "BRK", + "BRK", + + "there:", + "STA $0200"); + assembler.assembleCode(lines); + cpu.execute(); + assertThat(cpu.getA(), equalTo(0x03)); + assertThat(cpu.getX(), equalTo(0x00)); + assertThat(cpu.getY(), equalTo(0x00)); + assertThat(cpu.getSP(), equalTo(0xFF)); + assertThat(cpu.getPC(), equalTo(0x060c)); + assertThat(cpu.flags(), equalTo("00110000")); + } + + @Test public void testJumpToSubroutines() { + List lines = ImmutableList.of( + "JSR init", + "JSR loop", + "JSR end", + + "init:", + "LDX #$00", + "RTS", + + "loop:", + "INX", + "CPX #$05", + "BNE loop", + "RTS", + + "end:", + "BRK"); + assembler.assembleCode(lines); + cpu.execute(); + assertThat(cpu.getA(), equalTo(0x00)); + assertThat(cpu.getX(), equalTo(0x05)); + assertThat(cpu.getY(), equalTo(0x00)); + assertThat(cpu.getSP(), equalTo(0xFD)); + assertThat(cpu.getPC(), equalTo(0x0613)); + assertThat(cpu.flags(), equalTo("00110011")); + } }