mirror of
https://github.com/bradford-hamilton/apple-1.git
synced 2024-05-31 14:41:29 +00:00
internal/vm/{exec_funcs,opcodes,vm}: update design around opcode addr and operand fetching
Refactor: `(o op) getAddr` -> `(a *Appleone) getAddr` `(o op) getOperand` `(a *Appleone) getOperand` This makes way more sense to me and has been bothering me for a while.
This commit is contained in:
parent
e5709ad58b
commit
01bb2379ce
|
@ -33,7 +33,7 @@ func execRTI(a *Appleone, o op) error {
|
||||||
// M - 1 -> M N Z C I D V
|
// M - 1 -> M N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execDEC(a *Appleone, o op) error {
|
func execDEC(a *Appleone, o op) error {
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ func execDEC(a *Appleone, o op) error {
|
||||||
// M + 1 -> M N Z C I D V
|
// M + 1 -> M N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execINC(a *Appleone, o op) error {
|
func execINC(a *Appleone, o op) error {
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ func execDEY(a *Appleone, o op) error {
|
||||||
// M -> A N Z C I D V
|
// M -> A N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execLDA(a *Appleone, o op) error {
|
func execLDA(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ func execLDA(a *Appleone, o op) error {
|
||||||
// M -> X N Z C I D V
|
// M -> X N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execLDX(a *Appleone, o op) error {
|
func execLDX(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ func execLDX(a *Appleone, o op) error {
|
||||||
// M -> Y N Z C I D V
|
// M -> Y N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execLDY(a *Appleone, o op) error {
|
func execLDY(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ func execLDY(a *Appleone, o op) error {
|
||||||
// A + M + C -> A, C N Z C I D V
|
// A + M + C -> A, C N Z C I D V
|
||||||
// + + + - - +
|
// + + + - - +
|
||||||
func execADC(a *Appleone, o op) error {
|
func execADC(a *Appleone, o op) error {
|
||||||
b, err := o.getOperand(a)
|
b, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ func execADC(a *Appleone, o op) error {
|
||||||
// A - M - C -> A N Z C I D V
|
// A - M - C -> A N Z C I D V
|
||||||
// + + + - - +
|
// + + + - - +
|
||||||
func execSBC(a *Appleone, o op) error {
|
func execSBC(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ func execSBC(a *Appleone, o op) error {
|
||||||
// X -> M N Z C I D V
|
// X -> M N Z C I D V
|
||||||
// - - - - - -
|
// - - - - - -
|
||||||
func execSTX(a *Appleone, o op) error {
|
func execSTX(a *Appleone, o op) error {
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ func execSTX(a *Appleone, o op) error {
|
||||||
// Y -> M N Z C I D V
|
// Y -> M N Z C I D V
|
||||||
// - - - - - -
|
// - - - - - -
|
||||||
func execSTY(a *Appleone, o op) error {
|
func execSTY(a *Appleone, o op) error {
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ func execSTY(a *Appleone, o op) error {
|
||||||
// A -> M N Z C I D V
|
// A -> M N Z C I D V
|
||||||
// - - - - - -
|
// - - - - - -
|
||||||
func execSTA(a *Appleone, o op) error {
|
func execSTA(a *Appleone, o op) error {
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ func execBVS(a *Appleone, o op) error {
|
||||||
// bits 7 and 6 of operand are transfered to bit 7 and 6 of SR (N,V);
|
// bits 7 and 6 of operand are transfered to bit 7 and 6 of SR (N,V);
|
||||||
// the zeroflag is set to the result of operand AND accumulator.
|
// the zeroflag is set to the result of operand AND accumulator.
|
||||||
func execBIT(a *Appleone, o op) error {
|
func execBIT(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ func execBCS(a *Appleone, o op) error {
|
||||||
// X - M N Z C I D V
|
// X - M N Z C I D V
|
||||||
// + + + - - -
|
// + + + - - -
|
||||||
func execCPX(a *Appleone, o op) error {
|
func execCPX(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -353,7 +353,7 @@ func execCPX(a *Appleone, o op) error {
|
||||||
// A EOR M -> A N Z C I D V
|
// A EOR M -> A N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execEOR(a *Appleone, o op) error {
|
func execEOR(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -366,7 +366,7 @@ func execEOR(a *Appleone, o op) error {
|
||||||
// A - M N Z C I D V
|
// A - M N Z C I D V
|
||||||
// + + + - - -
|
// + + + - - -
|
||||||
func execCMP(a *Appleone, o op) error {
|
func execCMP(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -377,7 +377,7 @@ func execCMP(a *Appleone, o op) error {
|
||||||
// Y - M N Z C I D V
|
// Y - M N Z C I D V
|
||||||
// + + + - - -
|
// + + + - - -
|
||||||
func execCPY(a *Appleone, o op) error {
|
func execCPY(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -444,14 +444,14 @@ func execNOP(a *Appleone, o op) error {
|
||||||
// (PC+2) -> PCH - - - - - -
|
// (PC+2) -> PCH - - - - - -
|
||||||
func execJMP(a *Appleone, o op) error {
|
func execJMP(a *Appleone, o op) error {
|
||||||
if o.addrMode == indirect {
|
if o.addrMode == indirect {
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
a.cpu.pc = a.littleEndianToUint16(a.mem[addr+1], a.mem[addr])
|
a.cpu.pc = a.littleEndianToUint16(a.mem[addr+1], a.mem[addr])
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -522,7 +522,7 @@ func execPHP(a *Appleone, o op) error {
|
||||||
// (PC+2) -> PCH
|
// (PC+2) -> PCH
|
||||||
func execJSR(a *Appleone, o op) error {
|
func execJSR(a *Appleone, o op) error {
|
||||||
a.pushDWordToStack(a.cpu.pc - 1)
|
a.pushDWordToStack(a.cpu.pc - 1)
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -540,7 +540,7 @@ func execRTS(a *Appleone, o op) error {
|
||||||
// 0 -> [76543210] -> C N Z C I D V
|
// 0 -> [76543210] -> C N Z C I D V
|
||||||
// 0 + + - - -
|
// 0 + + - - -
|
||||||
func execLSR(a *Appleone, o op) error {
|
func execLSR(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -562,7 +562,7 @@ func execLSR(a *Appleone, o op) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -574,7 +574,7 @@ func execLSR(a *Appleone, o op) error {
|
||||||
// C <- [76543210] <- C N Z C I D V
|
// C <- [76543210] <- C N Z C I D V
|
||||||
// + + + - - -
|
// + + + - - -
|
||||||
func execROL(a *Appleone, o op) error {
|
func execROL(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -604,7 +604,7 @@ func execROL(a *Appleone, o op) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -626,7 +626,7 @@ func execTXS(a *Appleone, o op) error {
|
||||||
// C -> [76543210] -> C N Z C I D V
|
// C -> [76543210] -> C N Z C I D V
|
||||||
// + + + - - -
|
// + + + - - -
|
||||||
func execROR(a *Appleone, o op) error {
|
func execROR(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -656,7 +656,7 @@ func execROR(a *Appleone, o op) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -668,7 +668,7 @@ func execROR(a *Appleone, o op) error {
|
||||||
// C <- [76543210] <- 0 N Z C I D V
|
// C <- [76543210] <- 0 N Z C I D V
|
||||||
// + + + - - -
|
// + + + - - -
|
||||||
func execASL(a *Appleone, o op) error {
|
func execASL(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -689,7 +689,7 @@ func execASL(a *Appleone, o op) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := o.getAddr(a)
|
addr, err := a.getAddr(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -701,7 +701,7 @@ func execASL(a *Appleone, o op) error {
|
||||||
// A AND M -> A N Z C I D V
|
// A AND M -> A N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execAND(a *Appleone, o op) error {
|
func execAND(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -714,7 +714,7 @@ func execAND(a *Appleone, o op) error {
|
||||||
// A OR M -> A N Z C I D V
|
// A OR M -> A N Z C I D V
|
||||||
// + + - - - -
|
// + + - - - -
|
||||||
func execORA(a *Appleone, o op) error {
|
func execORA(a *Appleone, o op) error {
|
||||||
operand, err := o.getOperand(a)
|
operand, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,54 +33,6 @@ func opByCode(b byte) (op, error) {
|
||||||
return o, nil
|
return o, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o op) getAddr(a *Appleone) (uint16, error) {
|
|
||||||
switch o.addrMode {
|
|
||||||
// TODO: will these ever apply here?
|
|
||||||
// case accumulator:
|
|
||||||
//
|
|
||||||
// case implied:
|
|
||||||
//
|
|
||||||
case absolute:
|
|
||||||
return a.nextDWord(), nil
|
|
||||||
case absoluteXIndexed:
|
|
||||||
return a.nextDWord() + uint16(a.cpu.x), nil
|
|
||||||
case absoluteYIndexed:
|
|
||||||
return a.nextDWord() + uint16(a.cpu.y), nil
|
|
||||||
case immediate:
|
|
||||||
return a.cpu.pc - 1, nil
|
|
||||||
case indirect:
|
|
||||||
return uint16(a.nextWord()), nil
|
|
||||||
case indirectXIndexed:
|
|
||||||
addr := (uint16(a.nextWord()) + uint16(a.cpu.x)) & 0xFF
|
|
||||||
return a.littleEndianToUint16(a.mem[addr+1], a.mem[addr]), nil
|
|
||||||
case indirectYIndexed:
|
|
||||||
addr := uint16(a.nextWord())
|
|
||||||
val := a.littleEndianToUint16(a.mem[addr+1], a.mem[addr])
|
|
||||||
return val + uint16(a.cpu.y), nil
|
|
||||||
case relative:
|
|
||||||
return a.cpu.pc - 1, nil
|
|
||||||
case zeroPage:
|
|
||||||
return uint16(a.nextWord()) & 0xFF, nil
|
|
||||||
case zeroPageXIndexed:
|
|
||||||
return (uint16(a.nextWord()) + uint16(a.cpu.x)) & 0xFF, nil
|
|
||||||
case zeroPageYIndexed:
|
|
||||||
return (uint16(a.nextWord()) + uint16(a.cpu.y)) & 0xFF, nil
|
|
||||||
default:
|
|
||||||
return 0, errors.New("unkown addressing mode")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o op) getOperand(a *Appleone) (uint8, error) {
|
|
||||||
if o.addrMode == accumulator {
|
|
||||||
return a.cpu.a, nil
|
|
||||||
}
|
|
||||||
b, err := o.getAddr(a)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return a.mem[b], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// opcodes represent all of the Apple 1 opcodes available. Each 8 bit opcode is mapped to a corresponding
|
// opcodes represent all of the Apple 1 opcodes available. Each 8 bit opcode is mapped to a corresponding
|
||||||
// "op" which is just a struct holding metadata about the operation.
|
// "op" which is just a struct holding metadata about the operation.
|
||||||
var opcodes = map[uint8]op{
|
var opcodes = map[uint8]op{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,6 +37,54 @@ func (a *Appleone) step() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) getAddr(o op) (uint16, error) {
|
||||||
|
switch o.addrMode {
|
||||||
|
// TODO: will these ever apply here?
|
||||||
|
// case accumulator:
|
||||||
|
//
|
||||||
|
// case implied:
|
||||||
|
//
|
||||||
|
case absolute:
|
||||||
|
return a.nextDWord(), nil
|
||||||
|
case absoluteXIndexed:
|
||||||
|
return a.nextDWord() + uint16(a.cpu.x), nil
|
||||||
|
case absoluteYIndexed:
|
||||||
|
return a.nextDWord() + uint16(a.cpu.y), nil
|
||||||
|
case immediate:
|
||||||
|
return a.cpu.pc - 1, nil
|
||||||
|
case indirect:
|
||||||
|
return uint16(a.nextWord()), nil
|
||||||
|
case indirectXIndexed:
|
||||||
|
addr := (uint16(a.nextWord()) + uint16(a.cpu.x)) & 0xFF
|
||||||
|
return a.littleEndianToUint16(a.mem[addr+1], a.mem[addr]), nil
|
||||||
|
case indirectYIndexed:
|
||||||
|
addr := uint16(a.nextWord())
|
||||||
|
val := a.littleEndianToUint16(a.mem[addr+1], a.mem[addr])
|
||||||
|
return val + uint16(a.cpu.y), nil
|
||||||
|
case relative:
|
||||||
|
return a.cpu.pc - 1, nil
|
||||||
|
case zeroPage:
|
||||||
|
return uint16(a.nextWord()) & 0xFF, nil
|
||||||
|
case zeroPageXIndexed:
|
||||||
|
return (uint16(a.nextWord()) + uint16(a.cpu.x)) & 0xFF, nil
|
||||||
|
case zeroPageYIndexed:
|
||||||
|
return (uint16(a.nextWord()) + uint16(a.cpu.y)) & 0xFF, nil
|
||||||
|
default:
|
||||||
|
return 0, errors.New("unkown addressing mode")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) getOperand(o op) (uint8, error) {
|
||||||
|
if o.addrMode == accumulator {
|
||||||
|
return a.cpu.a, nil
|
||||||
|
}
|
||||||
|
b, err := a.getAddr(o)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return a.mem[b], nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Appleone) littleEndianToUint16(big, little byte) uint16 {
|
func (a *Appleone) littleEndianToUint16(big, little byte) uint16 {
|
||||||
return uint16(a.mem[big])<<8 | uint16(a.mem[little])
|
return uint16(a.mem[big])<<8 | uint16(a.mem[little])
|
||||||
}
|
}
|
||||||
|
@ -140,7 +189,7 @@ func (a *Appleone) getZero() byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Appleone) branch(o op) error {
|
func (a *Appleone) branch(o op) error {
|
||||||
offset, err := o.getOperand(a)
|
offset, err := a.getOperand(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user