mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-02-08 20:30:47 +00:00
Support for BRK, JMP, JSR, RTI and RTS
This commit is contained in:
parent
e43a0a9ae1
commit
7f9aea24e9
103
execute.go
103
execute.go
@ -22,6 +22,7 @@ const modeIndirectIndexedY = 8
|
|||||||
const modeAccumulator = 9
|
const modeAccumulator = 9
|
||||||
const modeRegisterX = 10
|
const modeRegisterX = 10
|
||||||
const modeRegisterY = 11
|
const modeRegisterY = 11
|
||||||
|
const modeIndirect = 12
|
||||||
|
|
||||||
// https://www.masswerk.at/6502/6502_instruction_set.html
|
// https://www.masswerk.at/6502/6502_instruction_set.html
|
||||||
// http://www.emulator101.com/reference/6502-reference.html
|
// http://www.emulator101.com/reference/6502-reference.html
|
||||||
@ -32,8 +33,7 @@ func getWordInLine(line []uint8) uint16 {
|
|||||||
return uint16(line[1]) + 0x100*uint16(line[2])
|
return uint16(line[1]) + 0x100*uint16(line[2])
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveWithAddressMode(s *state, line []uint8, addressMode int) (value uint8, setValue func(uint8)) {
|
func resolveWithAddressMode(s *state, line []uint8, addressMode int) (value uint8, address uint16, setValue func(uint8)) {
|
||||||
var address uint16
|
|
||||||
hasAddress := true
|
hasAddress := true
|
||||||
register := regNone
|
register := regNone
|
||||||
|
|
||||||
@ -68,6 +68,9 @@ func resolveWithAddressMode(s *state, line []uint8, addressMode int) (value uint
|
|||||||
case modeIndexedIndirectX:
|
case modeIndexedIndirectX:
|
||||||
addressAddress := uint8(line[1] + s.registers.getX())
|
addressAddress := uint8(line[1] + s.registers.getX())
|
||||||
address = s.memory.getZeroPageWord(addressAddress)
|
address = s.memory.getZeroPageWord(addressAddress)
|
||||||
|
case modeIndirect:
|
||||||
|
addressAddress := getWordInLine(line)
|
||||||
|
address = s.memory.getWord(addressAddress)
|
||||||
case modeIndirectIndexedY:
|
case modeIndirectIndexedY:
|
||||||
address = s.memory.getZeroPageWord(line[1]) +
|
address = s.memory.getZeroPageWord(line[1]) +
|
||||||
uint16(s.registers.getY())
|
uint16(s.registers.getY())
|
||||||
@ -98,8 +101,6 @@ type opcode struct {
|
|||||||
|
|
||||||
type opFunc func(s *state, line []uint8, opcode opcode)
|
type opFunc func(s *state, line []uint8, opcode opcode)
|
||||||
|
|
||||||
func opNOP(s *state, line []uint8, opcode opcode) {}
|
|
||||||
|
|
||||||
func buildOpTransfer(regSrc int, regDst int) opFunc {
|
func buildOpTransfer(regSrc int, regDst int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value := s.registers.getRegister(regSrc)
|
value := s.registers.getRegister(regSrc)
|
||||||
@ -112,7 +113,7 @@ func buildOpTransfer(regSrc int, regDst int) opFunc {
|
|||||||
|
|
||||||
func buildOpIncDec(addressMode int, inc bool) opFunc {
|
func buildOpIncDec(addressMode int, inc bool) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, setValue := resolveWithAddressMode(s, line, addressMode)
|
value, _, setValue := resolveWithAddressMode(s, line, addressMode)
|
||||||
if inc {
|
if inc {
|
||||||
value++
|
value++
|
||||||
} else {
|
} else {
|
||||||
@ -125,7 +126,7 @@ func buildOpIncDec(addressMode int, inc bool) opFunc {
|
|||||||
|
|
||||||
func buildShift(addressMode int, isLeft bool, isRotate bool) opFunc {
|
func buildShift(addressMode int, isLeft bool, isRotate bool) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, setValue := resolveWithAddressMode(s, line, addressMode)
|
value, _, setValue := resolveWithAddressMode(s, line, addressMode)
|
||||||
|
|
||||||
oldCarry := s.registers.getFlagBit(flagC)
|
oldCarry := s.registers.getFlagBit(flagC)
|
||||||
var carry bool
|
var carry bool
|
||||||
@ -150,7 +151,7 @@ func buildShift(addressMode int, isLeft bool, isRotate bool) opFunc {
|
|||||||
|
|
||||||
func buildOpLoad(addressMode int, regDst int) opFunc {
|
func buildOpLoad(addressMode int, regDst int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, _ := resolveWithAddressMode(s, line, addressMode)
|
value, _, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
s.registers.setRegister(regDst, value)
|
s.registers.setRegister(regDst, value)
|
||||||
s.registers.updateFlagZN(value)
|
s.registers.updateFlagZN(value)
|
||||||
}
|
}
|
||||||
@ -158,7 +159,7 @@ func buildOpLoad(addressMode int, regDst int) opFunc {
|
|||||||
|
|
||||||
func buildOpStore(addressMode int, regSrc int) opFunc {
|
func buildOpStore(addressMode int, regSrc int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
_, setValue := resolveWithAddressMode(s, line, addressMode)
|
_, _, setValue := resolveWithAddressMode(s, line, addressMode)
|
||||||
value := s.registers.getRegister(regSrc)
|
value := s.registers.getRegister(regSrc)
|
||||||
setValue(value)
|
setValue(value)
|
||||||
}
|
}
|
||||||
@ -183,7 +184,7 @@ func buildOpBranch(flag uint8, value bool) opFunc {
|
|||||||
|
|
||||||
func buildOpBit(addressMode int) opFunc {
|
func buildOpBit(addressMode int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, _ := resolveWithAddressMode(s, line, addressMode)
|
value, _, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
acc := s.registers.getA()
|
acc := s.registers.getA()
|
||||||
s.registers.updateFlag(flagZ, value&acc == 0)
|
s.registers.updateFlag(flagZ, value&acc == 0)
|
||||||
s.registers.updateFlag(flagN, value&(1<<7) != 0)
|
s.registers.updateFlag(flagN, value&(1<<7) != 0)
|
||||||
@ -193,7 +194,7 @@ func buildOpBit(addressMode int) opFunc {
|
|||||||
|
|
||||||
func buildOpCompare(addressMode int, reg int) opFunc {
|
func buildOpCompare(addressMode int, reg int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, _ := resolveWithAddressMode(s, line, addressMode)
|
value, _, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
reference := s.registers.getRegister(reg)
|
reference := s.registers.getRegister(reg)
|
||||||
s.registers.updateFlagZN(reference - value)
|
s.registers.updateFlagZN(reference - value)
|
||||||
s.registers.updateFlag(flagC, reference >= value)
|
s.registers.updateFlag(flagC, reference >= value)
|
||||||
@ -206,7 +207,7 @@ func operationXor(a uint8, b uint8) uint8 { return a ^ b }
|
|||||||
|
|
||||||
func buildOpLogic(addressMode int, operation func(uint8, uint8) uint8) opFunc {
|
func buildOpLogic(addressMode int, operation func(uint8, uint8) uint8) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, _ := resolveWithAddressMode(s, line, addressMode)
|
value, _, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
result := operation(value, s.registers.getA())
|
result := operation(value, s.registers.getA())
|
||||||
s.registers.setA(result)
|
s.registers.setA(result)
|
||||||
s.registers.updateFlagZN(result)
|
s.registers.updateFlagZN(result)
|
||||||
@ -215,9 +216,10 @@ func buildOpLogic(addressMode int, operation func(uint8, uint8) uint8) opFunc {
|
|||||||
|
|
||||||
func buildOpAdd(addressMode int) opFunc {
|
func buildOpAdd(addressMode int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, _ := resolveWithAddressMode(s, line, addressMode)
|
value, _, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
if s.registers.getFlag(flagD) {
|
if s.registers.getFlag(flagD) {
|
||||||
// TODO BCD
|
// TODO BCD. See http://www.6502.org/tutorials/decimal_mode.html
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
total := uint16(s.registers.getA()) +
|
total := uint16(s.registers.getA()) +
|
||||||
uint16(value) +
|
uint16(value) +
|
||||||
@ -232,7 +234,7 @@ func buildOpAdd(addressMode int) opFunc {
|
|||||||
|
|
||||||
func buildOpSub(addressMode int) opFunc {
|
func buildOpSub(addressMode int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
value, _ := resolveWithAddressMode(s, line, addressMode)
|
value, _, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
if s.registers.getFlag(flagD) {
|
if s.registers.getFlag(flagD) {
|
||||||
// TODO BCD
|
// TODO BCD
|
||||||
} else {
|
} else {
|
||||||
@ -249,38 +251,79 @@ func buildOpSub(addressMode int) opFunc {
|
|||||||
|
|
||||||
const stackAddress uint16 = 0x0100
|
const stackAddress uint16 = 0x0100
|
||||||
|
|
||||||
func buildOpPush(reg int) opFunc {
|
func pushByte(s *state, value uint8) {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
|
||||||
value := s.registers.getRegister(reg)
|
|
||||||
adresss := stackAddress + uint16(s.registers.getSP())
|
adresss := stackAddress + uint16(s.registers.getSP())
|
||||||
s.memory[adresss] = value
|
s.memory[adresss] = value
|
||||||
s.registers.setSP(s.registers.getSP() - 1)
|
s.registers.setSP(s.registers.getSP() - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pullByte(s *state) uint8 {
|
||||||
|
s.registers.setSP(s.registers.getSP() + 1)
|
||||||
|
adresss := stackAddress + uint16(s.registers.getSP())
|
||||||
|
return s.memory[adresss]
|
||||||
|
}
|
||||||
|
|
||||||
|
func pushWord(s *state, value uint16) {
|
||||||
|
pushByte(s, uint8(value>>8))
|
||||||
|
pushByte(s, uint8(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
func pullWord(s *state) uint16 {
|
||||||
|
return uint16(pullByte(s)) +
|
||||||
|
(uint16(pullByte(s)) << 8)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildOpPush(reg int) opFunc {
|
||||||
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
|
pushByte(s, s.registers.getRegister(reg))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildOpPull(reg int) opFunc {
|
func buildOpPull(reg int) opFunc {
|
||||||
return func(s *state, line []uint8, opcode opcode) {
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
s.registers.setSP(s.registers.getSP() + 1)
|
s.registers.setRegister(reg, pullByte(s))
|
||||||
adresss := stackAddress + uint16(s.registers.getSP())
|
|
||||||
value := s.memory[adresss]
|
|
||||||
s.registers.setRegister(reg, value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func buildOpJump(addressMode int) opFunc {
|
||||||
TODO:
|
return func(s *state, line []uint8, opcode opcode) {
|
||||||
http://www.6502.org/tutorials/decimal_mode.html
|
_, address, _ := resolveWithAddressMode(s, line, addressMode)
|
||||||
|
s.registers.setPC(address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BRK
|
func opNOP(s *state, line []uint8, opcode opcode) {}
|
||||||
|
|
||||||
JMP
|
func opJSR(s *state, line []uint8, opcode opcode) {
|
||||||
JSR
|
pushWord(s, s.registers.getPC())
|
||||||
RTI
|
s.registers.setPC(getWordInLine(line))
|
||||||
RTS
|
}
|
||||||
|
|
||||||
*/
|
func opRTI(s *state, line []uint8, opcode opcode) {
|
||||||
|
s.registers.setP(pullByte(s))
|
||||||
|
s.registers.setPC(pullWord(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
func opRTS(s *state, line []uint8, opcode opcode) {
|
||||||
|
s.registers.setPC(pullWord(s) + 1) // TODO: Do we really need to add 1?
|
||||||
|
}
|
||||||
|
|
||||||
|
func opBRK(s *state, line []uint8, opcode opcode) {
|
||||||
|
s.registers.setFlag(flagI)
|
||||||
|
pushWord(s, s.registers.getPC()+1) // TODO: De we have to add 1 or 2?
|
||||||
|
pushByte(s, s.registers.getP())
|
||||||
|
s.registers.setPC(s.memory.getWord(0xFFFE))
|
||||||
|
}
|
||||||
|
|
||||||
var opcodes = [256]opcode{
|
var opcodes = [256]opcode{
|
||||||
|
0x00: opcode{"BRK", 1, 7, opBRK},
|
||||||
|
0x4C: opcode{"JMP", 3, 3, buildOpJump(modeAbsolute)},
|
||||||
|
0x6C: opcode{"JMP", 3, 3, buildOpJump(modeIndirect)},
|
||||||
|
0x20: opcode{"JSR", 3, 6, opJSR},
|
||||||
|
0x40: opcode{"RTI", 1, 6, opRTI},
|
||||||
|
0x60: opcode{"RTS", 1, 6, opRTS},
|
||||||
|
|
||||||
0x48: opcode{"PHA", 1, 3, buildOpPush(regA)},
|
0x48: opcode{"PHA", 1, 3, buildOpPush(regA)},
|
||||||
0x08: opcode{"PHP", 1, 3, buildOpPush(regP)},
|
0x08: opcode{"PHP", 1, 3, buildOpPush(regP)},
|
||||||
0x68: opcode{"PLA", 1, 4, buildOpPull(regA)},
|
0x68: opcode{"PLA", 1, 4, buildOpPull(regA)},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user