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:
Bradford Lamson-Scribner 2020-05-31 21:41:47 -06:00
parent e5709ad58b
commit 01bb2379ce
3 changed files with 78 additions and 77 deletions

View File

@ -33,7 +33,7 @@ func execRTI(a *Appleone, o op) error {
// M - 1 -> M N Z C I D V
// + + - - - -
func execDEC(a *Appleone, o op) error {
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -48,7 +48,7 @@ func execDEC(a *Appleone, o op) error {
// M + 1 -> M N Z C I D V
// + + - - - -
func execINC(a *Appleone, o op) error {
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -117,7 +117,7 @@ func execDEY(a *Appleone, o op) error {
// M -> A N Z C I D V
// + + - - - -
func execLDA(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -130,7 +130,7 @@ func execLDA(a *Appleone, o op) error {
// M -> X N Z C I D V
// + + - - - -
func execLDX(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -143,7 +143,7 @@ func execLDX(a *Appleone, o op) error {
// M -> Y N Z C I D V
// + + - - - -
func execLDY(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -156,7 +156,7 @@ func execLDY(a *Appleone, o op) error {
// A + M + C -> A, C N Z C I D V
// + + + - - +
func execADC(a *Appleone, o op) error {
b, err := o.getOperand(a)
b, err := a.getOperand(o)
if err != nil {
return err
}
@ -185,7 +185,7 @@ func execADC(a *Appleone, o op) error {
// A - M - C -> A N Z C I D V
// + + + - - +
func execSBC(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -219,7 +219,7 @@ func execSBC(a *Appleone, o op) error {
// X -> M N Z C I D V
// - - - - - -
func execSTX(a *Appleone, o op) error {
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -230,7 +230,7 @@ func execSTX(a *Appleone, o op) error {
// Y -> M N Z C I D V
// - - - - - -
func execSTY(a *Appleone, o op) error {
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -241,7 +241,7 @@ func execSTY(a *Appleone, o op) error {
// A -> M N Z C I D V
// - - - - - -
func execSTA(a *Appleone, o op) error {
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
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);
// the zeroflag is set to the result of operand AND accumulator.
func execBIT(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -342,7 +342,7 @@ func execBCS(a *Appleone, o op) error {
// X - M N Z C I D V
// + + + - - -
func execCPX(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -353,7 +353,7 @@ func execCPX(a *Appleone, o op) error {
// A EOR M -> A N Z C I D V
// + + - - - -
func execEOR(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -366,7 +366,7 @@ func execEOR(a *Appleone, o op) error {
// A - M N Z C I D V
// + + + - - -
func execCMP(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -377,7 +377,7 @@ func execCMP(a *Appleone, o op) error {
// Y - M N Z C I D V
// + + + - - -
func execCPY(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -444,14 +444,14 @@ func execNOP(a *Appleone, o op) error {
// (PC+2) -> PCH - - - - - -
func execJMP(a *Appleone, o op) error {
if o.addrMode == indirect {
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
a.cpu.pc = a.littleEndianToUint16(a.mem[addr+1], a.mem[addr])
return nil
}
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -522,7 +522,7 @@ func execPHP(a *Appleone, o op) error {
// (PC+2) -> PCH
func execJSR(a *Appleone, o op) error {
a.pushDWordToStack(a.cpu.pc - 1)
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -540,7 +540,7 @@ func execRTS(a *Appleone, o op) error {
// 0 -> [76543210] -> C N Z C I D V
// 0 + + - - -
func execLSR(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -562,7 +562,7 @@ func execLSR(a *Appleone, o op) error {
return nil
}
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -574,7 +574,7 @@ func execLSR(a *Appleone, o op) error {
// C <- [76543210] <- C N Z C I D V
// + + + - - -
func execROL(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -604,7 +604,7 @@ func execROL(a *Appleone, o op) error {
return nil
}
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -626,7 +626,7 @@ func execTXS(a *Appleone, o op) error {
// C -> [76543210] -> C N Z C I D V
// + + + - - -
func execROR(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -656,7 +656,7 @@ func execROR(a *Appleone, o op) error {
return nil
}
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -668,7 +668,7 @@ func execROR(a *Appleone, o op) error {
// C <- [76543210] <- 0 N Z C I D V
// + + + - - -
func execASL(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -689,7 +689,7 @@ func execASL(a *Appleone, o op) error {
return nil
}
addr, err := o.getAddr(a)
addr, err := a.getAddr(o)
if err != nil {
return err
}
@ -701,7 +701,7 @@ func execASL(a *Appleone, o op) error {
// A AND M -> A N Z C I D V
// + + - - - -
func execAND(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}
@ -714,7 +714,7 @@ func execAND(a *Appleone, o op) error {
// A OR M -> A N Z C I D V
// + + - - - -
func execORA(a *Appleone, o op) error {
operand, err := o.getOperand(a)
operand, err := a.getOperand(o)
if err != nil {
return err
}

View File

@ -33,54 +33,6 @@ func opByCode(b byte) (op, error) {
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
// "op" which is just a struct holding metadata about the operation.
var opcodes = map[uint8]op{

View File

@ -1,6 +1,7 @@
package vm
import (
"errors"
"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 {
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 {
offset, err := o.getOperand(a)
offset, err := a.getOperand(o)
if err != nil {
return err
}