Added some documentation to cpu package & made some small tweaks
This commit is contained in:
parent
c397f0e092
commit
b549d0e33d
|
@ -19,7 +19,6 @@ func testBellCycles(delay int) {
|
||||||
mmu.WriteMemory(0x805, 0x00) // BRK
|
mmu.WriteMemory(0x805, 0x00) // BRK
|
||||||
|
|
||||||
// Run the code until the BRK instruction and count the cycles
|
// Run the code until the BRK instruction and count the cycles
|
||||||
system.FrameCycles = 0
|
|
||||||
showInstructions := false
|
showInstructions := false
|
||||||
breakAddress := uint16(0x805)
|
breakAddress := uint16(0x805)
|
||||||
exitAtBreak := false
|
exitAtBreak := false
|
||||||
|
|
101
cpu/cpu.go
101
cpu/cpu.go
|
@ -9,40 +9,42 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CpuFlagC byte = 1 << iota // 0x01
|
CpuFlagC byte = 1 << iota // 0x01 carry
|
||||||
CpuFlagZ // 0x02
|
CpuFlagZ // 0x02 zero
|
||||||
CpuFlagI // 0x04
|
CpuFlagI // 0x04 interrupt disable
|
||||||
CpuFlagD // 0x08
|
CpuFlagD // 0x08 decimal mode
|
||||||
CpuFlagB // 0x10
|
CpuFlagB // 0x10 break
|
||||||
CpuFlagR // 0x20
|
CpuFlagR // 0x20 reserved (unused)
|
||||||
CpuFlagV // 0x40
|
CpuFlagV // 0x40 overflow
|
||||||
CpuFlagN // 0x80
|
CpuFlagN // 0x80 sign/negative
|
||||||
)
|
)
|
||||||
|
|
||||||
var State struct {
|
var State struct {
|
||||||
A uint8
|
A uint8 // accumulator
|
||||||
X uint8
|
X uint8 // X register
|
||||||
Y uint8
|
Y uint8 // Y register
|
||||||
PC uint16
|
PC uint16 // program counter
|
||||||
SP uint8
|
SP uint8 // stack pointer
|
||||||
P uint8
|
P uint8 // processor flags
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init the CPU registers, interrupts and disable testing code
|
// Init sets up the CPU registers, interrupts and disable testing code
|
||||||
func Init() {
|
func Init() {
|
||||||
system.RunningTests = false
|
system.RunningTests = false
|
||||||
system.RunningFunctionalTests = false
|
system.RunningFunctionalTests = false
|
||||||
system.RunningInterruptTests = false
|
system.RunningInterruptTests = false
|
||||||
|
|
||||||
|
system.PendingInterrupt = false
|
||||||
|
system.PendingNMI = false
|
||||||
|
|
||||||
State.A = 0
|
State.A = 0
|
||||||
State.X = 0
|
State.X = 0
|
||||||
State.Y = 0
|
State.Y = 0
|
||||||
State.P = CpuFlagR | CpuFlagB | CpuFlagZ
|
State.P = CpuFlagR | CpuFlagB | CpuFlagZ
|
||||||
State.SP = 0xff
|
State.SP = 0xff
|
||||||
system.PendingInterrupt = false
|
|
||||||
system.PendingNMI = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setC sets the carry flag
|
||||||
func setC(value bool) {
|
func setC(value bool) {
|
||||||
if value {
|
if value {
|
||||||
State.P |= CpuFlagC
|
State.P |= CpuFlagC
|
||||||
|
@ -51,6 +53,7 @@ func setC(value bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setV sets the overflow flag
|
||||||
func setV(value bool) {
|
func setV(value bool) {
|
||||||
if value {
|
if value {
|
||||||
State.P |= CpuFlagV
|
State.P |= CpuFlagV
|
||||||
|
@ -59,6 +62,7 @@ func setV(value bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setN sets the sign/negative flag if the value is negative (>=0x80)
|
||||||
func setN(value uint8) {
|
func setN(value uint8) {
|
||||||
if (value & 0x80) != 0 {
|
if (value & 0x80) != 0 {
|
||||||
State.P |= CpuFlagN
|
State.P |= CpuFlagN
|
||||||
|
@ -67,6 +71,7 @@ func setN(value uint8) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setZ sets the zero flag if the value is zero
|
||||||
func setZ(value uint8) {
|
func setZ(value uint8) {
|
||||||
if value == 0 {
|
if value == 0 {
|
||||||
State.P |= CpuFlagZ
|
State.P |= CpuFlagZ
|
||||||
|
@ -95,12 +100,14 @@ func isN() bool {
|
||||||
return (State.P & CpuFlagN) != 0
|
return (State.P & CpuFlagN) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// push8 pushes an 8 bit value to the stack
|
||||||
func push8(value uint8) {
|
func push8(value uint8) {
|
||||||
mmu.WritePageTable[mmu.StackPage][State.SP] = value
|
mmu.WritePageTable[mmu.StackPage][State.SP] = value
|
||||||
State.SP -= 1
|
State.SP -= 1
|
||||||
State.SP &= 0xff
|
State.SP &= 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// push16 pushes a 16 bit value to the stack
|
||||||
func push16(value uint16) {
|
func push16(value uint16) {
|
||||||
mmu.WritePageTable[mmu.StackPage][State.SP] = uint8(value >> 8)
|
mmu.WritePageTable[mmu.StackPage][State.SP] = uint8(value >> 8)
|
||||||
mmu.WritePageTable[mmu.StackPage][State.SP-1] = uint8(value & 0xff)
|
mmu.WritePageTable[mmu.StackPage][State.SP-1] = uint8(value & 0xff)
|
||||||
|
@ -108,12 +115,14 @@ func push16(value uint16) {
|
||||||
State.SP &= 0xff
|
State.SP &= 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pop8 pulls an 8 bit value from the stack
|
||||||
func pop8() uint8 {
|
func pop8() uint8 {
|
||||||
State.SP += 1
|
State.SP += 1
|
||||||
State.SP &= 0xff
|
State.SP &= 0xff
|
||||||
return mmu.ReadPageTable[mmu.StackPage][State.SP]
|
return mmu.ReadPageTable[mmu.StackPage][State.SP]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pop16 pulls a 16 bit value from the stack
|
||||||
func pop16() uint16 {
|
func pop16() uint16 {
|
||||||
State.SP += 2
|
State.SP += 2
|
||||||
State.SP &= 0xff
|
State.SP &= 0xff
|
||||||
|
@ -122,7 +131,8 @@ func pop16() uint16 {
|
||||||
return lsb + msb<<8
|
return lsb + msb<<8
|
||||||
}
|
}
|
||||||
|
|
||||||
func branch(instructionName string, doBranch bool) {
|
// branch handles a branch instruction
|
||||||
|
func branch(doBranch bool) {
|
||||||
value := mmu.ReadMemory(State.PC + 1)
|
value := mmu.ReadMemory(State.PC + 1)
|
||||||
|
|
||||||
var relativeAddress uint16
|
var relativeAddress uint16
|
||||||
|
@ -135,10 +145,12 @@ func branch(instructionName string, doBranch bool) {
|
||||||
system.FrameCycles += 2
|
system.FrameCycles += 2
|
||||||
if doBranch {
|
if doBranch {
|
||||||
if system.RunningTests && State.PC == relativeAddress {
|
if system.RunningTests && State.PC == relativeAddress {
|
||||||
|
// Catch an infinite loop and exit
|
||||||
fmt.Printf("Trap at $%04x\n", relativeAddress)
|
fmt.Printf("Trap at $%04x\n", relativeAddress)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The number of cycles depends on if a page boundary was crossed
|
||||||
samePage := (State.PC & 0xff00) == (relativeAddress & 0xff00)
|
samePage := (State.PC & 0xff00) == (relativeAddress & 0xff00)
|
||||||
if samePage {
|
if samePage {
|
||||||
system.FrameCycles += 1
|
system.FrameCycles += 1
|
||||||
|
@ -151,6 +163,7 @@ func branch(instructionName string, doBranch bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAddressFromAddressMode gets the address an instruction is referring to
|
||||||
func getAddressFromAddressMode(addressMode byte) (result uint16, pageBoundaryCrossed bool) {
|
func getAddressFromAddressMode(addressMode byte) (result uint16, pageBoundaryCrossed bool) {
|
||||||
switch addressMode {
|
switch addressMode {
|
||||||
case amZeroPage:
|
case amZeroPage:
|
||||||
|
@ -186,6 +199,7 @@ func getAddressFromAddressMode(addressMode byte) (result uint16, pageBoundaryCro
|
||||||
return result, pageBoundaryCrossed
|
return result, pageBoundaryCrossed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readMemoryWithAddressMode reads memory using a particular address mode
|
||||||
func readMemoryWithAddressMode(addressMode byte) (result uint8, pageBoundaryCrossed bool) {
|
func readMemoryWithAddressMode(addressMode byte) (result uint8, pageBoundaryCrossed bool) {
|
||||||
switch addressMode {
|
switch addressMode {
|
||||||
case amImmediate:
|
case amImmediate:
|
||||||
|
@ -239,7 +253,7 @@ func readMemoryWithAddressMode(addressMode byte) (result uint8, pageBoundaryCros
|
||||||
return result, pageBoundaryCrossed
|
return result, pageBoundaryCrossed
|
||||||
}
|
}
|
||||||
|
|
||||||
// STA, STX and STY
|
// store handles STA, STX and STY
|
||||||
func store(regValue uint8, addressMode byte) {
|
func store(regValue uint8, addressMode byte) {
|
||||||
address, _ := getAddressFromAddressMode(addressMode)
|
address, _ := getAddressFromAddressMode(addressMode)
|
||||||
mmu.WriteMemory(address, regValue)
|
mmu.WriteMemory(address, regValue)
|
||||||
|
@ -277,7 +291,7 @@ func store(regValue uint8, addressMode byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These instructions take the same amount of system.FrameCycles
|
// advanceCyclesForAcculumatorOperation advances the number of cycles for common accumulator operations
|
||||||
func advanceCyclesForAcculumatorOperation(addressMode byte, pageBoundaryCrossed bool) {
|
func advanceCyclesForAcculumatorOperation(addressMode byte, pageBoundaryCrossed bool) {
|
||||||
extraCycle := uint64(0)
|
extraCycle := uint64(0)
|
||||||
if pageBoundaryCrossed {
|
if pageBoundaryCrossed {
|
||||||
|
@ -308,6 +322,7 @@ func advanceCyclesForAcculumatorOperation(addressMode byte, pageBoundaryCrossed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LDA, LDX, LDY
|
||||||
func load(addressMode byte) uint8 {
|
func load(addressMode byte) uint8 {
|
||||||
value, pageBoundaryCrossed := readMemoryWithAddressMode(addressMode)
|
value, pageBoundaryCrossed := readMemoryWithAddressMode(addressMode)
|
||||||
setN(value)
|
setN(value)
|
||||||
|
@ -316,6 +331,7 @@ func load(addressMode byte) uint8 {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CMP, CPX, CPY
|
||||||
func cmp(regValue uint8, addressMode byte) {
|
func cmp(regValue uint8, addressMode byte) {
|
||||||
value, pageBoundaryCrossed := readMemoryWithAddressMode(addressMode)
|
value, pageBoundaryCrossed := readMemoryWithAddressMode(addressMode)
|
||||||
var result uint16
|
var result uint16
|
||||||
|
@ -532,30 +548,37 @@ func nmi() {
|
||||||
system.FrameCycles += 7
|
system.FrameCycles += 7
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run runs the CPU until either wantedCycles has been reached (if non-zero) or the program counter reaches breakAddress.
|
||||||
|
// system.FrameCycles is the amount of cycles executed so far.
|
||||||
func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableFirmwareWait bool, wantedCycles uint64) {
|
func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableFirmwareWait bool, wantedCycles uint64) {
|
||||||
system.FrameCycles = 0
|
system.FrameCycles = 0
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
// Exit if wantedCycles is set and has been reached
|
||||||
if (wantedCycles != 0) && (system.FrameCycles >= wantedCycles) {
|
if (wantedCycles != 0) && (system.FrameCycles >= wantedCycles) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exit if the magic address of the functional tests has been reached
|
||||||
if system.RunningTests && (State.PC == 0x3869) {
|
if system.RunningTests && (State.PC == 0x3869) {
|
||||||
fmt.Println("Functional tests passed")
|
fmt.Println("Functional tests passed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exit if the magic address of the interupt tests has been reached
|
||||||
if system.RunningTests && (State.PC == 0x0af5) {
|
if system.RunningTests && (State.PC == 0x0af5) {
|
||||||
fmt.Println("Interrupt tests passed")
|
fmt.Println("Interrupt tests passed")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle an IRQ f there is one pending and interrupts are enabled
|
||||||
if system.PendingInterrupt && ((State.P & CpuFlagI) == 0) {
|
if system.PendingInterrupt && ((State.P & CpuFlagI) == 0) {
|
||||||
irq()
|
irq()
|
||||||
system.PendingInterrupt = false
|
system.PendingInterrupt = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle an NMI if there is one pending
|
||||||
if system.PendingNMI {
|
if system.PendingNMI {
|
||||||
nmi()
|
nmi()
|
||||||
system.PendingNMI = false
|
system.PendingNMI = false
|
||||||
|
@ -566,24 +589,29 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF
|
||||||
PrintInstruction(true)
|
PrintInstruction(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
opcode := mmu.ReadMemory(State.PC)
|
// Handle case of breakAddress being set and being been reached
|
||||||
addressMode := opCodes[opcode].addressingMode.mode
|
|
||||||
|
|
||||||
if breakAddress != nil && State.PC == *breakAddress {
|
if breakAddress != nil && State.PC == *breakAddress {
|
||||||
if exitAtBreak {
|
if exitAtBreak {
|
||||||
|
// Exit the process completely
|
||||||
fmt.Printf("Break at $%04x\n", *breakAddress)
|
fmt.Printf("Break at $%04x\n", *breakAddress)
|
||||||
PrintInstruction(true)
|
PrintInstruction(true)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
} else {
|
} else {
|
||||||
|
// Exit politely
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode opcode
|
||||||
|
opcode := mmu.ReadMemory(State.PC)
|
||||||
|
addressMode := opCodes[opcode].addressingMode.mode
|
||||||
|
|
||||||
switch opcode {
|
switch opcode {
|
||||||
|
|
||||||
case 0x4c: // JMP $0000
|
case 0x4c: // JMP $0000
|
||||||
value := uint16(mmu.ReadMemory(State.PC+1)) + uint16(mmu.ReadMemory(State.PC+2))<<8
|
value := uint16(mmu.ReadMemory(State.PC+1)) + uint16(mmu.ReadMemory(State.PC+2))<<8
|
||||||
if system.RunningTests && State.PC == value {
|
if system.RunningTests && State.PC == value {
|
||||||
|
// Check for an infinite loop and exit if so
|
||||||
fmt.Printf("Trap at $%04x\n", value)
|
fmt.Printf("Trap at $%04x\n", value)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
@ -599,6 +627,7 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF
|
||||||
system.FrameCycles += 6
|
system.FrameCycles += 6
|
||||||
|
|
||||||
if disableFirmwareWait && value == 0xfca8 {
|
if disableFirmwareWait && value == 0xfca8 {
|
||||||
|
// Don't call the firmware wait, just move forward and pretend it happened.
|
||||||
State.PC += 3
|
State.PC += 3
|
||||||
State.A = 0
|
State.A = 0
|
||||||
continue
|
continue
|
||||||
|
@ -679,25 +708,25 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF
|
||||||
State.PC++
|
State.PC++
|
||||||
system.FrameCycles += 2
|
system.FrameCycles += 2
|
||||||
|
|
||||||
case 0xE8:
|
case 0xE8: // INX
|
||||||
State.X = (State.X + 1) & 0xff
|
State.X = (State.X + 1) & 0xff
|
||||||
setN(State.X)
|
setN(State.X)
|
||||||
setZ(State.X)
|
setZ(State.X)
|
||||||
State.PC++
|
State.PC++
|
||||||
system.FrameCycles += 2
|
system.FrameCycles += 2
|
||||||
case 0xC8:
|
case 0xC8: // INY
|
||||||
State.Y = (State.Y + 1) & 0xff
|
State.Y = (State.Y + 1) & 0xff
|
||||||
setN(State.Y)
|
setN(State.Y)
|
||||||
setZ(State.Y)
|
setZ(State.Y)
|
||||||
State.PC++
|
State.PC++
|
||||||
system.FrameCycles += 2
|
system.FrameCycles += 2
|
||||||
case 0xca:
|
case 0xca: // DEX
|
||||||
State.X = (State.X - 1) & 0xff
|
State.X = (State.X - 1) & 0xff
|
||||||
setN(State.X)
|
setN(State.X)
|
||||||
setZ(State.X)
|
setZ(State.X)
|
||||||
State.PC++
|
State.PC++
|
||||||
system.FrameCycles += 2
|
system.FrameCycles += 2
|
||||||
case 0x88:
|
case 0x88: // DEY
|
||||||
State.Y = (State.Y - 1) & 0xff
|
State.Y = (State.Y - 1) & 0xff
|
||||||
setN(State.Y)
|
setN(State.Y)
|
||||||
setZ(State.Y)
|
setZ(State.Y)
|
||||||
|
@ -706,21 +735,21 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
case 0x10:
|
case 0x10:
|
||||||
branch("BPL", !isN())
|
branch(!isN())
|
||||||
case 0x30:
|
case 0x30:
|
||||||
branch("BMI", isN())
|
branch(isN())
|
||||||
case 0x50:
|
case 0x50:
|
||||||
branch("BVC", !isV())
|
branch(!isV())
|
||||||
case 0x70:
|
case 0x70:
|
||||||
branch("BVS", isV())
|
branch(isV())
|
||||||
case 0x90:
|
case 0x90:
|
||||||
branch("BCC", !isC())
|
branch(!isC())
|
||||||
case 0xb0:
|
case 0xb0:
|
||||||
branch("BCS", isC())
|
branch(isC())
|
||||||
case 0xd0:
|
case 0xd0:
|
||||||
branch("BNE", !isZ())
|
branch(!isZ())
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
branch("BEQ", isZ())
|
branch(isZ())
|
||||||
|
|
||||||
// Flag setting
|
// Flag setting
|
||||||
case 0x18: // CLC
|
case 0x18: // CLC
|
||||||
|
@ -752,6 +781,7 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF
|
||||||
State.PC++
|
State.PC++
|
||||||
system.FrameCycles += 2
|
system.FrameCycles += 2
|
||||||
|
|
||||||
|
// Stack operations
|
||||||
case 0x48: // PHA
|
case 0x48: // PHA
|
||||||
push8(State.A)
|
push8(State.A)
|
||||||
State.PC++
|
State.PC++
|
||||||
|
@ -796,6 +826,7 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF
|
||||||
State.PC += 3
|
State.PC += 3
|
||||||
system.FrameCycles += 4
|
system.FrameCycles += 4
|
||||||
|
|
||||||
|
// Shifts and rotations
|
||||||
case 0x0a, 0x06, 0x16, 0x0e, 0x1e: // ASL
|
case 0x0a, 0x06, 0x16, 0x0e, 0x1e: // ASL
|
||||||
address, value := preProcessShift(addressMode)
|
address, value := preProcessShift(addressMode)
|
||||||
setC((value & 0x80) != 0)
|
setC((value & 0x80) != 0)
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
package cpu_test
|
package cpu_test
|
||||||
|
|
||||||
|
// Test the CPU using the functional and interrupt tests defined in the *.a65
|
||||||
|
// files and compiled to bin.gz files. The cpu package is aware of tests being run and
|
||||||
|
// will exit or bail on success and failure certain conditions.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/freewilll/apple2/cpu"
|
"github.com/freewilll/apple2/cpu"
|
||||||
"github.com/freewilll/apple2/keyboard"
|
|
||||||
"github.com/freewilll/apple2/mmu"
|
"github.com/freewilll/apple2/mmu"
|
||||||
"github.com/freewilll/apple2/system"
|
"github.com/freewilll/apple2/system"
|
||||||
"github.com/freewilll/apple2/utils"
|
"github.com/freewilll/apple2/utils"
|
||||||
|
@ -73,8 +76,6 @@ func TestCPU(t *testing.T) {
|
||||||
mmu.WritePageTable[0xc0+i] = RomPretendingToBeRAM[i*0x100 : i*0x100+0x100]
|
mmu.WritePageTable[0xc0+i] = RomPretendingToBeRAM[i*0x100 : i*0x100+0x100]
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard.Init()
|
|
||||||
|
|
||||||
cpu.Run(*showInstructions, breakAddress, true, false, 0)
|
cpu.Run(*showInstructions, breakAddress, true, false, 0)
|
||||||
fmt.Printf("Finished running %s\n\n", rom)
|
fmt.Printf("Finished running %s\n\n", rom)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/freewilll/apple2/mmu"
|
"github.com/freewilll/apple2/mmu"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// printFlag prints a lower or uppercase letter depending on the state of the flag
|
||||||
func printFlag(p byte, flag uint8, code string) {
|
func printFlag(p byte, flag uint8, code string) {
|
||||||
if (p & flag) == 0 {
|
if (p & flag) == 0 {
|
||||||
fmt.Print(code)
|
fmt.Print(code)
|
||||||
|
@ -15,6 +16,7 @@ func printFlag(p byte, flag uint8, code string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printInstruction prings a single instruction and optionally also registers
|
||||||
func printInstruction(instruction string, showRegisters bool) {
|
func printInstruction(instruction string, showRegisters bool) {
|
||||||
fmt.Printf("%04x- %-24s", State.PC, instruction)
|
fmt.Printf("%04x- %-24s", State.PC, instruction)
|
||||||
|
|
||||||
|
@ -40,6 +42,7 @@ func printInstruction(instruction string, showRegisters bool) {
|
||||||
fmt.Println("")
|
fmt.Println("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintInstruction prints the instruction at the current PC
|
||||||
func PrintInstruction(showRegisters bool) {
|
func PrintInstruction(showRegisters bool) {
|
||||||
opcodeValue := mmu.ReadPageTable[(State.PC)>>8][(State.PC)&0xff]
|
opcodeValue := mmu.ReadPageTable[(State.PC)>>8][(State.PC)&0xff]
|
||||||
opcode := opCodes[opcodeValue]
|
opcode := opCodes[opcodeValue]
|
||||||
|
@ -82,6 +85,7 @@ func PrintInstruction(showRegisters bool) {
|
||||||
printInstruction(fmt.Sprintf("%s %s %s", opcodes, mnemonic, suffix), showRegisters)
|
printInstruction(fmt.Sprintf("%s %s %s", opcodes, mnemonic, suffix), showRegisters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AdvanceInstruction goes forward one instruction without executing anything
|
||||||
func AdvanceInstruction() {
|
func AdvanceInstruction() {
|
||||||
opcodeValue := mmu.ReadPageTable[(State.PC)>>8][(State.PC)&0xff]
|
opcodeValue := mmu.ReadPageTable[(State.PC)>>8][(State.PC)&0xff]
|
||||||
opcode := opCodes[opcodeValue]
|
opcode := opCodes[opcodeValue]
|
||||||
|
@ -89,6 +93,7 @@ func AdvanceInstruction() {
|
||||||
State.PC += uint16(size)
|
State.PC += uint16(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DumpMemory dumps $100 bytes of memory
|
||||||
func DumpMemory(offset uint16) {
|
func DumpMemory(offset uint16) {
|
||||||
var i uint16
|
var i uint16
|
||||||
for i = 0; i < 0x100; i++ {
|
for i = 0; i < 0x100; i++ {
|
||||||
|
|
|
@ -57,7 +57,6 @@ func DecodeCmdLineAddress(s *string) (result *uint16) {
|
||||||
// been reached.
|
// been reached.
|
||||||
func RunUntilBreakPoint(t *testing.T, breakAddress uint16, seconds int, showInstructions bool, message string) {
|
func RunUntilBreakPoint(t *testing.T, breakAddress uint16, seconds int, showInstructions bool, message string) {
|
||||||
fmt.Printf("Running until %#04x: %s \n", breakAddress, message)
|
fmt.Printf("Running until %#04x: %s \n", breakAddress, message)
|
||||||
system.FrameCycles = 0
|
|
||||||
system.LastAudioCycles = 0
|
system.LastAudioCycles = 0
|
||||||
exitAtBreak := false
|
exitAtBreak := false
|
||||||
disableFirmwareWait := false
|
disableFirmwareWait := false
|
||||||
|
|
Loading…
Reference in New Issue