internal/vm/{exec_funcs,opcodes,vm}: implement the rest of the opcode exec funcs
This commit is contained in:
parent
ca699a78af
commit
a9a3ae5c0a
|
@ -117,11 +117,11 @@ func execDEY(a *Appleone, o op) error {
|
|||
// M -> A N Z C I D V
|
||||
// + + - - - -
|
||||
func execLDA(a *Appleone, o op) error {
|
||||
b, err := o.getData(a)
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.a = b
|
||||
a.cpu.a = operand
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
return nil
|
||||
|
@ -130,11 +130,11 @@ func execLDA(a *Appleone, o op) error {
|
|||
// M -> X N Z C I D V
|
||||
// + + - - - -
|
||||
func execLDX(a *Appleone, o op) error {
|
||||
b, err := o.getData(a)
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.x = b
|
||||
a.cpu.x = operand
|
||||
a.setZeroIfNeeded(a.cpu.x)
|
||||
a.setNegativeIfOverflow(a.cpu.x)
|
||||
return nil
|
||||
|
@ -143,11 +143,11 @@ func execLDX(a *Appleone, o op) error {
|
|||
// M -> Y N Z C I D V
|
||||
// + + - - - -
|
||||
func execLDY(a *Appleone, o op) error {
|
||||
b, err := o.getData(a)
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.y = b
|
||||
a.cpu.y = operand
|
||||
a.setZeroIfNeeded(a.cpu.y)
|
||||
a.setNegativeIfOverflow(a.cpu.y)
|
||||
return nil
|
||||
|
@ -156,14 +156,14 @@ 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.getData(a)
|
||||
b, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
operand := uint16(b)
|
||||
regA := uint16(a.cpu.a)
|
||||
sum := regA + operand + uint16(a.getCarry())
|
||||
a.cpu.a = uint8(sum)
|
||||
a.cpu.a = byte(sum)
|
||||
|
||||
a.clearCarry()
|
||||
if sum > 255 {
|
||||
|
@ -181,3 +181,536 @@ func execADC(a *Appleone, o op) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// A - M - C -> A N Z C I D V
|
||||
// + + + - - +
|
||||
func execSBC(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
carry := uint16(1 - a.getCarry())
|
||||
regA := a.cpu.a
|
||||
sum := uint16(regA) - carry - uint16(operand)
|
||||
a.cpu.a = byte(sum)
|
||||
a.clearOverflow()
|
||||
|
||||
if byte(regA)>>7 != a.cpu.a>>7 {
|
||||
a.setOverflow()
|
||||
}
|
||||
|
||||
if uint16(sum) < 256 {
|
||||
a.setCarry()
|
||||
} else {
|
||||
a.clearCarry()
|
||||
}
|
||||
|
||||
a.clearOverflow()
|
||||
if ((255-operand)^a.cpu.a)&(regA^a.cpu.a)&0x80 != 0 {
|
||||
a.setOverflow()
|
||||
}
|
||||
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// X -> M N Z C I D V
|
||||
// - - - - - -
|
||||
func execSTX(a *Appleone, o op) error {
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = a.cpu.x
|
||||
return nil
|
||||
}
|
||||
|
||||
// Y -> M N Z C I D V
|
||||
// - - - - - -
|
||||
func execSTY(a *Appleone, o op) error {
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = a.cpu.y
|
||||
return nil
|
||||
}
|
||||
|
||||
// A -> M N Z C I D V
|
||||
// - - - - - -
|
||||
func execSTA(a *Appleone, o op) error {
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = a.cpu.a
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on Z = 1 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBEQ(a *Appleone, o op) error {
|
||||
if a.getZero() == flagZero {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on Z = 0 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBNE(a *Appleone, o op) error {
|
||||
if a.getZero() != flagZero {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on V = 0 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBVC(a *Appleone, o op) error {
|
||||
if a.getOverflow() == 0 {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on V = 1 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBVS(a *Appleone, o op) error {
|
||||
if a.getOverflow() != 0 {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.setZeroIfNeeded(a.cpu.a & operand)
|
||||
a.clearOverflow()
|
||||
|
||||
if operand&flagOverflow != 0 {
|
||||
a.setOverflow()
|
||||
}
|
||||
|
||||
a.setNegativeIfOverflow(operand)
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on C = 0 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBCC(a *Appleone, o op) error {
|
||||
if a.getCarry() == 0 {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on N = 1 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBMI(a *Appleone, o op) error {
|
||||
if a.getNegative() == flagNegative {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// branch on N = 0 N Z C I D V
|
||||
// - - - - - -
|
||||
func execBPL(a *Appleone, o op) error {
|
||||
if a.getNegative() == 0 {
|
||||
a.branch(o)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// X - M N Z C I D V
|
||||
// + + + - - -
|
||||
func execCPX(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.compare(a.cpu.x, operand)
|
||||
return nil
|
||||
}
|
||||
|
||||
// A EOR M -> A N Z C I D V
|
||||
// + + - - - -
|
||||
func execEOR(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.a ^= operand
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// A - M N Z C I D V
|
||||
// + + + - - -
|
||||
func execCMP(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.compare(a.cpu.a, operand)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Y - M N Z C I D V
|
||||
// + + + - - -
|
||||
func execCPY(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.compare(a.cpu.y, operand)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 0 -> C N Z C I D V
|
||||
// - - 0 - - -
|
||||
func execCLC(a *Appleone, o op) error {
|
||||
a.clearCarry()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 0 -> D N Z C I D V
|
||||
// - - - - 0 -
|
||||
func execCLD(a *Appleone, o op) error {
|
||||
a.clearDec()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 0 -> I N Z C I D V
|
||||
// - - - 0 - -
|
||||
func execCLI(a *Appleone, o op) error {
|
||||
a.clearInterrupt()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 0 -> V N Z C I D V
|
||||
// - - - - - 0
|
||||
func execCLV(a *Appleone, o op) error {
|
||||
a.clearOverflow()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 1 -> C N Z C I D V
|
||||
// - - 1 - - -
|
||||
func execSEC(a *Appleone, o op) error {
|
||||
a.setCarry()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 1 -> D N Z C I D V
|
||||
// - - - - 1 -
|
||||
func execSED(a *Appleone, o op) error {
|
||||
a.setDec()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 1 -> I N Z C I D V
|
||||
// - - - 1 - -
|
||||
func execSEI(a *Appleone, o op) error {
|
||||
a.setInterrupt()
|
||||
return nil
|
||||
}
|
||||
|
||||
// --- N Z C I D V
|
||||
// - - - - - -
|
||||
func execNOP(a *Appleone, o op) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// (PC+1) -> PCL N Z C I D V
|
||||
// (PC+2) -> PCH - - - - - -
|
||||
func execJMP(a *Appleone, o op) error {
|
||||
if o.addrMode == indirect {
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.pc = a.littleEndianToUint16(a.mem[addr+1], a.mem[addr])
|
||||
return nil
|
||||
}
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.pc = addr
|
||||
return nil
|
||||
}
|
||||
|
||||
// push A N Z C I D V
|
||||
// - - - - - -
|
||||
func execPHA(a *Appleone, o op) error {
|
||||
a.pushWordToStack(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// X -> A N Z C I D V
|
||||
// + + - - - -
|
||||
func execTXA(a *Appleone, o op) error {
|
||||
a.cpu.a = a.cpu.x
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Y -> A N Z C I D V
|
||||
// + + - - - -
|
||||
func execTYA(a *Appleone, o op) error {
|
||||
a.cpu.a = a.cpu.y
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SP -> X N Z C I D V
|
||||
// + + - - - -
|
||||
func execTSX(a *Appleone, o op) error {
|
||||
a.cpu.x = a.cpu.sp
|
||||
a.setNegativeIfOverflow(a.cpu.x)
|
||||
a.setZeroIfNeeded(a.cpu.x)
|
||||
return nil
|
||||
}
|
||||
|
||||
// pull A N Z C I D V
|
||||
// + + - - - -
|
||||
func execPLA(a *Appleone, o op) error {
|
||||
a.cpu.a = a.popStackWord()
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// pull SR from stack N Z C I D V
|
||||
func execPLP(a *Appleone, o op) error {
|
||||
a.cpu.ps = a.popStackWord() | 0B_00110000
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// push SR N Z C I D V
|
||||
// - - - - - -
|
||||
func execPHP(a *Appleone, o op) error {
|
||||
a.pushWordToStack(a.cpu.ps)
|
||||
return nil
|
||||
}
|
||||
|
||||
// push (PC+2), N Z C I D V
|
||||
// (PC+1) -> PCL - - - - - -
|
||||
// (PC+2) -> PCH
|
||||
func execJSR(a *Appleone, o op) error {
|
||||
a.pushDWordToStack(a.cpu.pc - 1)
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.pc = addr
|
||||
return nil
|
||||
}
|
||||
|
||||
// pull PC, PC+1 -> PC N Z C I D V
|
||||
// - - - - - -
|
||||
func execRTS(a *Appleone, o op) error {
|
||||
a.cpu.pc = a.popStackDWord() + 1
|
||||
return nil
|
||||
}
|
||||
|
||||
// 0 -> [76543210] -> C N Z C I D V
|
||||
// 0 + + - - -
|
||||
func execLSR(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bit := (operand << 7) > 0
|
||||
operand >>= 1
|
||||
|
||||
if bit {
|
||||
a.setCarry()
|
||||
} else {
|
||||
a.clearCarry()
|
||||
}
|
||||
|
||||
a.setZeroIfNeeded(operand)
|
||||
a.setNegativeIfOverflow(operand)
|
||||
|
||||
if o.addrMode == accumulator {
|
||||
a.cpu.a = operand
|
||||
return nil
|
||||
}
|
||||
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = operand
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// C <- [76543210] <- C N Z C I D V
|
||||
// + + + - - -
|
||||
func execROL(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var carry bool
|
||||
if a.getCarry() == flagCarry {
|
||||
carry = true
|
||||
}
|
||||
|
||||
if operand>>7 != 0 {
|
||||
a.setCarry()
|
||||
} else {
|
||||
a.clearCarry()
|
||||
}
|
||||
|
||||
operand <<= 1
|
||||
|
||||
if carry {
|
||||
operand |= flagCarry
|
||||
}
|
||||
|
||||
a.setZeroIfNeeded(operand)
|
||||
a.setNegativeIfOverflow(operand)
|
||||
|
||||
if o.addrMode == accumulator {
|
||||
a.cpu.a = operand
|
||||
return nil
|
||||
}
|
||||
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = operand
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// X -> SP N Z C I D V
|
||||
// - - - - - -
|
||||
func execTXS(a *Appleone, o op) error {
|
||||
a.cpu.sp = a.cpu.x
|
||||
// TODO: needed?
|
||||
// a.setZeroIfNeeded(a.cpu.sp)
|
||||
// a.setNegativeIfOverflow(a.cpu.sp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// C -> [76543210] -> C N Z C I D V
|
||||
// + + + - - -
|
||||
func execROR(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var carry bool
|
||||
if a.getCarry() == flagCarry {
|
||||
carry = true
|
||||
}
|
||||
|
||||
if operand&0x01 != 0 {
|
||||
a.setCarry()
|
||||
} else {
|
||||
a.clearCarry()
|
||||
}
|
||||
|
||||
operand >>= 1
|
||||
|
||||
if carry {
|
||||
operand |= flagNegative
|
||||
}
|
||||
|
||||
a.setZeroIfNeeded(operand)
|
||||
a.setNegativeIfOverflow(operand)
|
||||
|
||||
if o.addrMode == accumulator {
|
||||
a.cpu.a = operand
|
||||
return nil
|
||||
}
|
||||
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = operand
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// C <- [76543210] <- 0 N Z C I D V
|
||||
// + + + - - -
|
||||
func execASL(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if operand>>7 == 1 {
|
||||
a.setCarry()
|
||||
} else {
|
||||
a.clearCarry()
|
||||
}
|
||||
|
||||
operand <<= 1
|
||||
|
||||
a.setZeroIfNeeded(operand)
|
||||
a.setNegativeIfOverflow(operand)
|
||||
|
||||
if o.addrMode == accumulator {
|
||||
a.cpu.a = operand
|
||||
return nil
|
||||
}
|
||||
|
||||
addr, err := o.getAddr(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.mem[addr] = operand
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// A AND M -> A N Z C I D V
|
||||
// + + - - - -
|
||||
func execAND(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.a &= operand
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
||||
// A OR M -> A N Z C I D V
|
||||
// + + - - - -
|
||||
func execORA(a *Appleone, o op) error {
|
||||
operand, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.cpu.a |= operand
|
||||
a.setZeroIfNeeded(a.cpu.a)
|
||||
a.setNegativeIfOverflow(a.cpu.a)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ func (o op) getAddr(a *Appleone) (uint16, error) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o op) getData(a *Appleone) (uint8, error) {
|
||||
func (o op) getOperand(a *Appleone) (uint8, error) {
|
||||
if o.addrMode == accumulator {
|
||||
return a.cpu.a, nil
|
||||
}
|
||||
|
@ -235,14 +235,14 @@ var opcodes = map[uint8]op{
|
|||
// absolute,Y SBC oper,Y F9 3 4*
|
||||
// (indirect,X) SBC (oper,X) E1 2 6
|
||||
// (indirect),Y SBC (oper),Y F1 2 5*
|
||||
0xE9: newOp("SBC", 0xE9, 2, immediate, todo),
|
||||
0xE5: newOp("SBC", 0xE5, 2, zeroPage, todo),
|
||||
0xF5: newOp("SBC", 0xF5, 2, zeroPageXIndexed, todo),
|
||||
0xED: newOp("SBC", 0xED, 3, absolute, todo),
|
||||
0xFD: newOp("SBC", 0xFD, 3, absoluteXIndexed, todo),
|
||||
0xF9: newOp("SBC", 0xF9, 3, absoluteYIndexed, todo),
|
||||
0xE1: newOp("SBC", 0xE1, 2, indirectXIndexed, todo),
|
||||
0xF1: newOp("SBC", 0xF1, 2, indirectYIndexed, todo),
|
||||
0xE9: newOp("SBC", 0xE9, 2, immediate, execSBC),
|
||||
0xE5: newOp("SBC", 0xE5, 2, zeroPage, execSBC),
|
||||
0xF5: newOp("SBC", 0xF5, 2, zeroPageXIndexed, execSBC),
|
||||
0xED: newOp("SBC", 0xED, 3, absolute, execSBC),
|
||||
0xFD: newOp("SBC", 0xFD, 3, absoluteXIndexed, execSBC),
|
||||
0xF9: newOp("SBC", 0xF9, 3, absoluteYIndexed, execSBC),
|
||||
0xE1: newOp("SBC", 0xE1, 2, indirectXIndexed, execSBC),
|
||||
0xF1: newOp("SBC", 0xF1, 2, indirectYIndexed, execSBC),
|
||||
|
||||
// STX Store Index X in Memory
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -250,9 +250,9 @@ var opcodes = map[uint8]op{
|
|||
// zeropage STX oper 86 2 3
|
||||
// zeropage,Y STX oper,Y 96 2 4
|
||||
// absolute STX oper 8E 3 4
|
||||
0x86: newOp("STX", 0x86, 2, zeroPage, todo),
|
||||
0x96: newOp("STX", 0x96, 2, zeroPageYIndexed, todo),
|
||||
0x8E: newOp("STX", 0x8E, 3, absolute, todo),
|
||||
0x86: newOp("STX", 0x86, 2, zeroPage, execSTX),
|
||||
0x96: newOp("STX", 0x96, 2, zeroPageYIndexed, execSTX),
|
||||
0x8E: newOp("STX", 0x8E, 3, absolute, execSTX),
|
||||
|
||||
// STY Store Index Y in Memory
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -260,9 +260,9 @@ var opcodes = map[uint8]op{
|
|||
// zeropage STY oper 84 2 3
|
||||
// zeropage,X STY oper,X 94 2 4
|
||||
// absolute STY oper 8C 3 4
|
||||
0x84: newOp("STY", 0x84, 2, zeroPage, todo),
|
||||
0x94: newOp("STY", 0x94, 2, zeroPageXIndexed, todo),
|
||||
0x8C: newOp("STY", 0x8C, 3, absolute, todo),
|
||||
0x84: newOp("STY", 0x84, 2, zeroPage, execSTY),
|
||||
0x94: newOp("STY", 0x94, 2, zeroPageXIndexed, execSTY),
|
||||
0x8C: newOp("STY", 0x8C, 3, absolute, execSTY),
|
||||
|
||||
// STA Store Accumulator in Memory
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -274,63 +274,63 @@ var opcodes = map[uint8]op{
|
|||
// absolute,Y STA oper,Y 99 3 5
|
||||
// (indirect,X) STA (oper,X) 81 2 6
|
||||
// (indirect),Y STA (oper),Y 91 2 6
|
||||
0x85: newOp("STA", 0x85, 2, zeroPage, todo),
|
||||
0x95: newOp("STA", 0x95, 2, zeroPageXIndexed, todo),
|
||||
0x8D: newOp("STA", 0x8D, 3, absolute, todo),
|
||||
0x9D: newOp("STA", 0x9D, 3, absoluteXIndexed, todo),
|
||||
0x99: newOp("STA", 0x99, 3, absoluteYIndexed, todo),
|
||||
0x81: newOp("STA", 0x81, 2, indirectXIndexed, todo),
|
||||
0x91: newOp("STA", 0x91, 2, indirectYIndexed, todo),
|
||||
0x85: newOp("STA", 0x85, 2, zeroPage, execSTA),
|
||||
0x95: newOp("STA", 0x95, 2, zeroPageXIndexed, execSTA),
|
||||
0x8D: newOp("STA", 0x8D, 3, absolute, execSTA),
|
||||
0x9D: newOp("STA", 0x9D, 3, absoluteXIndexed, execSTA),
|
||||
0x99: newOp("STA", 0x99, 3, absoluteYIndexed, execSTA),
|
||||
0x81: newOp("STA", 0x81, 2, indirectXIndexed, execSTA),
|
||||
0x91: newOp("STA", 0x91, 2, indirectYIndexed, execSTA),
|
||||
|
||||
// BEQ Branch on Result Zero
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BEQ oper F0 2 2**
|
||||
0xF0: newOp("BEQ", 0xF0, 2, relative, todo),
|
||||
0xF0: newOp("BEQ", 0xF0, 2, relative, execBEQ),
|
||||
|
||||
// BNE Branch on Result not Zero
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BNE oper D0 2 2**
|
||||
0xD0: newOp("BNE", 0xD0, 2, relative, todo),
|
||||
0xD0: newOp("BNE", 0xD0, 2, relative, execBNE),
|
||||
|
||||
// BVC Branch on Overflow Clear
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BVC oper 50 2 2**
|
||||
0x50: newOp("BVC", 0x50, 2, relative, todo),
|
||||
0x50: newOp("BVC", 0x50, 2, relative, execBVC),
|
||||
|
||||
// BVS Branch on Overflow Set
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BVC oper 70 2 2**
|
||||
0x70: newOp("BVS", 0x70, 2, relative, todo),
|
||||
0x70: newOp("BVS", 0x70, 2, relative, execBVS),
|
||||
|
||||
// BIT Test Bits in Memory with Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// zeropage BIT oper 24 2 3
|
||||
// absolute BIT oper 2C 3 4
|
||||
0x24: newOp("BIT", 0x24, 2, zeroPage, todo),
|
||||
0x2C: newOp("BIT", 0x2C, 3, absolute, todo),
|
||||
0x24: newOp("BIT", 0x24, 2, zeroPage, execBIT),
|
||||
0x2C: newOp("BIT", 0x2C, 3, absolute, execBIT),
|
||||
|
||||
// BCC Branch on Carry Clear
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BCC oper 90 2 2**
|
||||
0x90: newOp("BCC", 0x90, 2, relative, todo),
|
||||
0x90: newOp("BCC", 0x90, 2, relative, execBCC),
|
||||
|
||||
// BMI Branch on Result Minus
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BMI oper 30 2 2**
|
||||
0x30: newOp("BMI", 0x30, 2, relative, todo),
|
||||
0x30: newOp("BMI", 0x30, 2, relative, execBMI),
|
||||
|
||||
// BPL Branch on Result Plus
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// relative BPL oper 10 2 2**
|
||||
0x10: newOp("BPL", 0x10, 2, relative, todo),
|
||||
0x10: newOp("BPL", 0x10, 2, relative, execBPL),
|
||||
|
||||
// BCS Branch on Carry Set
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -344,9 +344,9 @@ var opcodes = map[uint8]op{
|
|||
// immidiate CPX #oper E0 2 2
|
||||
// zeropage CPX oper E4 2 3
|
||||
// absolute CPX oper EC 3 4
|
||||
0xE0: newOp("CPX", 0xE0, 2, immediate, todo),
|
||||
0xE4: newOp("CPX", 0xE4, 2, zeroPage, todo),
|
||||
0xEC: newOp("CPX", 0xEC, 3, absolute, todo),
|
||||
0xE0: newOp("CPX", 0xE0, 2, immediate, execCPX),
|
||||
0xE4: newOp("CPX", 0xE4, 2, zeroPage, execCPX),
|
||||
0xEC: newOp("CPX", 0xEC, 3, absolute, execCPX),
|
||||
|
||||
// EOR Exclusive-OR Memory with Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -359,14 +359,14 @@ var opcodes = map[uint8]op{
|
|||
// absolute,Y EOR oper,Y 59 3 4*
|
||||
// (indirect,X) EOR (oper,X) 41 2 6
|
||||
// (indirect),Y EOR (oper),Y 51 2 5*
|
||||
0x49: newOp("EOR", 0x49, 2, immediate, todo),
|
||||
0x45: newOp("EOR", 0x45, 2, zeroPage, todo),
|
||||
0x55: newOp("EOR", 0x55, 2, zeroPageXIndexed, todo),
|
||||
0x4D: newOp("EOR", 0x4D, 3, absolute, todo),
|
||||
0x5D: newOp("EOR", 0x5D, 3, absoluteXIndexed, todo),
|
||||
0x59: newOp("EOR", 0x59, 3, absoluteYIndexed, todo),
|
||||
0x41: newOp("EOR", 0x41, 2, indirectXIndexed, todo),
|
||||
0x51: newOp("EOR", 0x51, 2, indirectYIndexed, todo),
|
||||
0x49: newOp("EOR", 0x49, 2, immediate, execEOR),
|
||||
0x45: newOp("EOR", 0x45, 2, zeroPage, execEOR),
|
||||
0x55: newOp("EOR", 0x55, 2, zeroPageXIndexed, execEOR),
|
||||
0x4D: newOp("EOR", 0x4D, 3, absolute, execEOR),
|
||||
0x5D: newOp("EOR", 0x5D, 3, absoluteXIndexed, execEOR),
|
||||
0x59: newOp("EOR", 0x59, 3, absoluteYIndexed, execEOR),
|
||||
0x41: newOp("EOR", 0x41, 2, indirectXIndexed, execEOR),
|
||||
0x51: newOp("EOR", 0x51, 2, indirectYIndexed, execEOR),
|
||||
|
||||
// CMP Compare Memory with Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -379,14 +379,14 @@ var opcodes = map[uint8]op{
|
|||
// absolute,Y CMP oper,Y D9 3 4*
|
||||
// (indirect,X) CMP (oper,X) C1 2 6
|
||||
// (indirect),Y CMP (oper),Y D1 2 5*
|
||||
0xC9: newOp("CMP", 0xC9, 2, immediate, todo),
|
||||
0xC5: newOp("CMP", 0xC5, 2, zeroPage, todo),
|
||||
0xD5: newOp("CMP", 0xD5, 2, zeroPageXIndexed, todo),
|
||||
0xCD: newOp("CMP", 0xCD, 3, absolute, todo),
|
||||
0xDD: newOp("CMP", 0xDD, 3, absoluteXIndexed, todo),
|
||||
0xD9: newOp("CMP", 0xD9, 3, absoluteYIndexed, todo),
|
||||
0xC1: newOp("CMP", 0xC1, 2, indirectXIndexed, todo),
|
||||
0xD1: newOp("CMP", 0xD1, 2, indirectYIndexed, todo),
|
||||
0xC9: newOp("CMP", 0xC9, 2, immediate, execCMP),
|
||||
0xC5: newOp("CMP", 0xC5, 2, zeroPage, execCMP),
|
||||
0xD5: newOp("CMP", 0xD5, 2, zeroPageXIndexed, execCMP),
|
||||
0xCD: newOp("CMP", 0xCD, 3, absolute, execCMP),
|
||||
0xDD: newOp("CMP", 0xDD, 3, absoluteXIndexed, execCMP),
|
||||
0xD9: newOp("CMP", 0xD9, 3, absoluteYIndexed, execCMP),
|
||||
0xC1: newOp("CMP", 0xC1, 2, indirectXIndexed, execCMP),
|
||||
0xD1: newOp("CMP", 0xD1, 2, indirectYIndexed, execCMP),
|
||||
|
||||
// CPY Compare Memory and Index Y
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -394,119 +394,119 @@ var opcodes = map[uint8]op{
|
|||
// immidiate CPY #oper C0 2 2
|
||||
// zeropage CPY oper C4 2 3
|
||||
// absolute CPY oper CC 3 4
|
||||
0xC0: newOp("CPY", 0xC0, 2, immediate, todo),
|
||||
0xC4: newOp("CPY", 0xC4, 2, zeroPage, todo),
|
||||
0xCC: newOp("CPY", 0xCC, 3, absolute, todo),
|
||||
0xC0: newOp("CPY", 0xC0, 2, immediate, execCPY),
|
||||
0xC4: newOp("CPY", 0xC4, 2, zeroPage, execCPY),
|
||||
0xCC: newOp("CPY", 0xCC, 3, absolute, execCPY),
|
||||
|
||||
// CLC Clear Carry Flag
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied CLC 18 1 2
|
||||
0x18: newOp("CLC", 0x18, 1, implied, todo),
|
||||
0x18: newOp("CLC", 0x18, 1, implied, execCLC),
|
||||
|
||||
// CLD Clear Decimal Mode
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied CLD D8 1 2
|
||||
0xD8: newOp("CLD", 0xD8, 1, implied, todo),
|
||||
0xD8: newOp("CLD", 0xD8, 1, implied, execCLD),
|
||||
|
||||
// CLI Clear Interrupt Disable Bit
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied CLI 58 1 2
|
||||
0x58: newOp("CLI", 0x58, 1, implied, todo),
|
||||
0x58: newOp("CLI", 0x58, 1, implied, execCLI),
|
||||
|
||||
// CLV Clear Overflow Flag
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied CLV B8 1 2
|
||||
0xB8: newOp("CLV", 0xB8, 1, implied, todo),
|
||||
0xB8: newOp("CLV", 0xB8, 1, implied, execCLV),
|
||||
|
||||
// SEC Set Carry Flag
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied SEC 38 1 2
|
||||
0x38: newOp("SEC", 0x38, 1, implied, todo),
|
||||
0x38: newOp("SEC", 0x38, 1, implied, execSEC),
|
||||
|
||||
// SED Set Decimal Flag
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied SED F8 1 2
|
||||
0xF8: newOp("SED", 0xF8, 1, implied, todo),
|
||||
0xF8: newOp("SED", 0xF8, 1, implied, execSED),
|
||||
|
||||
// SEI Set Interrupt Disable Status
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied SEI 78 1 2
|
||||
0x78: newOp("SEI", 0x78, 1, implied, todo),
|
||||
0x78: newOp("SEI", 0x78, 1, implied, execSEI),
|
||||
|
||||
// NOP No Operation
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied NOP EA 1 2
|
||||
0xEA: newOp("NOP", 0xEA, 1, implied, todo),
|
||||
0xEA: newOp("NOP", 0xEA, 1, implied, execNOP),
|
||||
|
||||
// JMP Jump to New Location
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// absolute JMP oper 4C 3 3
|
||||
// indirect JMP (oper) 6C 3 5
|
||||
0x4C: newOp("JMP", 0x4C, 3, absolute, todo),
|
||||
0x6C: newOp("JMP", 0x6C, 3, indirect, todo),
|
||||
0x4C: newOp("JMP", 0x4C, 3, absolute, execJMP),
|
||||
0x6C: newOp("JMP", 0x6C, 3, indirect, execJMP),
|
||||
|
||||
// PHA Push Accumulator on Stack
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied PHA 48 1 3
|
||||
0x48: newOp("PHA", 0x48, 1, implied, todo),
|
||||
0x48: newOp("PHA", 0x48, 1, implied, execPHA),
|
||||
|
||||
// TXA Transfer Index X to Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied TXA 8A 1 2
|
||||
0x8A: newOp("TXA", 0x8A, 1, implied, todo),
|
||||
0x8A: newOp("TXA", 0x8A, 1, implied, execTXA),
|
||||
|
||||
// TYA Transfer Index Y to Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied TYA 98 1 2
|
||||
0x98: newOp("TYA", 0x98, 1, implied, todo),
|
||||
0x98: newOp("TYA", 0x98, 1, implied, execTYA),
|
||||
|
||||
// TSX Transfer Stack Pointer to Index X
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied TSX BA 1 2
|
||||
0xBA: newOp("TSX", 0xBA, 1, implied, todo),
|
||||
0xBA: newOp("TSX", 0xBA, 1, implied, execTSX),
|
||||
|
||||
// PLA Pull Accumulator from Stack
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied PLA 68 1 4
|
||||
0x68: newOp("PLA", 0x68, 1, implied, todo),
|
||||
0x68: newOp("PLA", 0x68, 1, implied, execPLA),
|
||||
|
||||
// PLP Pull Processor Status from Stack
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied PLP 28 1 4
|
||||
0x28: newOp("PLP", 0x28, 1, implied, todo),
|
||||
0x28: newOp("PLP", 0x28, 1, implied, execPLP),
|
||||
|
||||
// PHP Push Processor Status on Stack
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied PHP 08 1 3
|
||||
0x08: newOp("PHP", 0x08, 1, implied, todo),
|
||||
0x08: newOp("PHP", 0x08, 1, implied, execPHP),
|
||||
|
||||
// JSR Jump to New Location Saving Return Address
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// absolute JSR oper 20 3 6
|
||||
0x20: newOp("JSR", 0x20, 3, absolute, todo),
|
||||
0x20: newOp("JSR", 0x20, 3, absolute, execJSR),
|
||||
|
||||
// RTS Return from Subroutine
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied RTS 60 1 6
|
||||
0x60: newOp("RTS", 0x60, 1, implied, todo),
|
||||
0x60: newOp("RTS", 0x60, 1, implied, execRTS),
|
||||
|
||||
// LSR Shift One Bit Right (Memory or Accumulator)
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -516,11 +516,11 @@ var opcodes = map[uint8]op{
|
|||
// zeropage,X LSR oper,X 56 2 6
|
||||
// absolute LSR oper 4E 3 6
|
||||
// absolute,X LSR oper,X 5E 3 7
|
||||
0x4A: newOp("LSR", 0x4A, 1, accumulator, todo),
|
||||
0x46: newOp("LSR", 0x46, 2, zeroPage, todo),
|
||||
0x56: newOp("LSR", 0x56, 2, zeroPageXIndexed, todo),
|
||||
0x4E: newOp("LSR", 0x4E, 3, absolute, todo),
|
||||
0x5E: newOp("LSR", 0x5E, 3, absoluteXIndexed, todo),
|
||||
0x4A: newOp("LSR", 0x4A, 1, accumulator, execLSR),
|
||||
0x46: newOp("LSR", 0x46, 2, zeroPage, execLSR),
|
||||
0x56: newOp("LSR", 0x56, 2, zeroPageXIndexed, execLSR),
|
||||
0x4E: newOp("LSR", 0x4E, 3, absolute, execLSR),
|
||||
0x5E: newOp("LSR", 0x5E, 3, absoluteXIndexed, execLSR),
|
||||
|
||||
// ROL Rotate One Bit Left (Memory or Accumulator)
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -530,17 +530,17 @@ var opcodes = map[uint8]op{
|
|||
// zeropage,X ROL oper,X 36 2 6
|
||||
// absolute ROL oper 2E 3 6
|
||||
// absolute,X ROL oper,X 3E 3 7
|
||||
0x2A: newOp("ROL", 0x2A, 1, accumulator, todo),
|
||||
0x26: newOp("ROL", 0x26, 2, zeroPage, todo),
|
||||
0x36: newOp("ROL", 0x36, 2, zeroPageXIndexed, todo),
|
||||
0x2E: newOp("ROL", 0x2E, 3, absolute, todo),
|
||||
0x3E: newOp("ROL", 0x3E, 3, absoluteXIndexed, todo),
|
||||
0x2A: newOp("ROL", 0x2A, 1, accumulator, execROL),
|
||||
0x26: newOp("ROL", 0x26, 2, zeroPage, execROL),
|
||||
0x36: newOp("ROL", 0x36, 2, zeroPageXIndexed, execROL),
|
||||
0x2E: newOp("ROL", 0x2E, 3, absolute, execROL),
|
||||
0x3E: newOp("ROL", 0x3E, 3, absoluteXIndexed, execROL),
|
||||
|
||||
// TXS Transfer Index X to Stack Register
|
||||
// addressing assembler opc bytes cyles
|
||||
// --------------------------------------------
|
||||
// implied TXS 9A 1 2
|
||||
0x9A: newOp("TXS", 0x9A, 1, implied, todo),
|
||||
0x9A: newOp("TXS", 0x9A, 1, implied, execTXS),
|
||||
|
||||
// ROR Rotate One Bit Right (Memory or Accumulator)
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -550,11 +550,11 @@ var opcodes = map[uint8]op{
|
|||
// zeropage,X ROR oper,X 76 2 6
|
||||
// absolute ROR oper 6E 3 6
|
||||
// absolute,X ROR oper,X 7E 3 7
|
||||
0x6A: newOp("ROR", 0x6A, 1, accumulator, todo),
|
||||
0x66: newOp("ROR", 0x66, 2, zeroPage, todo),
|
||||
0x76: newOp("ROR", 0x76, 2, zeroPageXIndexed, todo),
|
||||
0x6E: newOp("ROR", 0x6E, 3, absolute, todo),
|
||||
0x7E: newOp("ROR", 0x7E, 3, absoluteXIndexed, todo),
|
||||
0x6A: newOp("ROR", 0x6A, 1, accumulator, execROR),
|
||||
0x66: newOp("ROR", 0x66, 2, zeroPage, execROR),
|
||||
0x76: newOp("ROR", 0x76, 2, zeroPageXIndexed, execROR),
|
||||
0x6E: newOp("ROR", 0x6E, 3, absolute, execROR),
|
||||
0x7E: newOp("ROR", 0x7E, 3, absoluteXIndexed, execROR),
|
||||
|
||||
// ASL Shift Left One Bit (Memory or Accumulator)
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -564,11 +564,11 @@ var opcodes = map[uint8]op{
|
|||
// zeropage,X ASL oper,X 16 2 6
|
||||
// absolute ASL oper 0E 3 6
|
||||
// absolute,X ASL oper,X 1E 3 7
|
||||
0x0A: newOp("ASL", 0x0A, 1, accumulator, todo),
|
||||
0x06: newOp("ASL", 0x06, 2, zeroPage, todo),
|
||||
0x16: newOp("ASL", 0x16, 2, zeroPageXIndexed, todo),
|
||||
0x0E: newOp("ASL", 0x0E, 3, absolute, todo),
|
||||
0x1E: newOp("ASL", 0x1E, 3, absoluteXIndexed, todo),
|
||||
0x0A: newOp("ASL", 0x0A, 1, accumulator, execASL),
|
||||
0x06: newOp("ASL", 0x06, 2, zeroPage, execASL),
|
||||
0x16: newOp("ASL", 0x16, 2, zeroPageXIndexed, execASL),
|
||||
0x0E: newOp("ASL", 0x0E, 3, absolute, execASL),
|
||||
0x1E: newOp("ASL", 0x1E, 3, absoluteXIndexed, execASL),
|
||||
|
||||
// AND AND Memory with Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -581,14 +581,14 @@ var opcodes = map[uint8]op{
|
|||
// absolute,Y AND oper,Y 39 3 4*
|
||||
// (indirect,X) AND (oper,X) 21 2 6
|
||||
// (indirect),Y AND (oper),Y 31 2 5*
|
||||
0x29: newOp("AND", 0x29, 2, immediate, todo),
|
||||
0x25: newOp("AND", 0x25, 2, zeroPage, todo),
|
||||
0x35: newOp("AND", 0x35, 2, zeroPageXIndexed, todo),
|
||||
0x2D: newOp("AND", 0x2D, 3, absolute, todo),
|
||||
0x3D: newOp("AND", 0x3D, 3, absoluteXIndexed, todo),
|
||||
0x39: newOp("AND", 0x39, 3, absoluteYIndexed, todo),
|
||||
0x21: newOp("AND", 0x21, 2, indirectXIndexed, todo),
|
||||
0x31: newOp("AND", 0x31, 2, indirectYIndexed, todo),
|
||||
0x29: newOp("AND", 0x29, 2, immediate, execAND),
|
||||
0x25: newOp("AND", 0x25, 2, zeroPage, execAND),
|
||||
0x35: newOp("AND", 0x35, 2, zeroPageXIndexed, execAND),
|
||||
0x2D: newOp("AND", 0x2D, 3, absolute, execAND),
|
||||
0x3D: newOp("AND", 0x3D, 3, absoluteXIndexed, execAND),
|
||||
0x39: newOp("AND", 0x39, 3, absoluteYIndexed, execAND),
|
||||
0x21: newOp("AND", 0x21, 2, indirectXIndexed, execAND),
|
||||
0x31: newOp("AND", 0x31, 2, indirectYIndexed, execAND),
|
||||
|
||||
// ORA OR Memory with Accumulator
|
||||
// addressing assembler opc bytes cyles
|
||||
|
@ -601,12 +601,12 @@ var opcodes = map[uint8]op{
|
|||
// absolute,Y ORA oper,Y 19 3 4*
|
||||
// (indirect,X) ORA (oper,X) 01 2 6
|
||||
// (indirect),Y ORA (oper),Y 11 2 5*
|
||||
0x09: newOp("ORA", 0x09, 2, immediate, todo),
|
||||
0x05: newOp("ORA", 0x05, 2, zeroPage, todo),
|
||||
0x15: newOp("ORA", 0x15, 2, zeroPageXIndexed, todo),
|
||||
0x0D: newOp("ORA", 0x0D, 3, absolute, todo),
|
||||
0x1D: newOp("ORA", 0x1D, 3, absoluteXIndexed, todo),
|
||||
0x19: newOp("ORA", 0x19, 3, absoluteYIndexed, todo),
|
||||
0x01: newOp("ORA", 0x01, 2, indirectXIndexed, todo),
|
||||
0x11: newOp("ORA", 0x11, 2, indirectYIndexed, todo),
|
||||
0x09: newOp("ORA", 0x09, 2, immediate, execORA),
|
||||
0x05: newOp("ORA", 0x05, 2, zeroPage, execORA),
|
||||
0x15: newOp("ORA", 0x15, 2, zeroPageXIndexed, execORA),
|
||||
0x0D: newOp("ORA", 0x0D, 3, absolute, execORA),
|
||||
0x1D: newOp("ORA", 0x1D, 3, absoluteXIndexed, execORA),
|
||||
0x19: newOp("ORA", 0x19, 3, absoluteYIndexed, execORA),
|
||||
0x01: newOp("ORA", 0x01, 2, indirectXIndexed, execORA),
|
||||
0x11: newOp("ORA", 0x11, 2, indirectYIndexed, execORA),
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func New() *Appleone {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *Appleone) load(addr uint16, data []uint8) {
|
||||
func (a *Appleone) load(addr uint16, data []byte) {
|
||||
a.mem.load(addr, data)
|
||||
a.cpu.pc = addr
|
||||
}
|
||||
|
@ -36,27 +36,27 @@ func (a *Appleone) step() {
|
|||
}
|
||||
}
|
||||
|
||||
func (a *Appleone) littleEndianToUint16(big, little uint8) uint16 {
|
||||
func (a *Appleone) littleEndianToUint16(big, little byte) uint16 {
|
||||
return uint16(a.mem[big])<<8 | uint16(a.mem[little])
|
||||
}
|
||||
|
||||
// pushWordToStack pushes the given word (byte) into memory and sets the new stack pointer
|
||||
func (a *Appleone) pushWordToStack(b byte) {
|
||||
a.mem[StackBottom+uint16(a.cpu.sp)] = b
|
||||
a.cpu.sp = uint8((uint16(a.cpu.sp) - 1) & 0xFF)
|
||||
a.cpu.sp = byte((uint16(a.cpu.sp) - 1) & 0xFF)
|
||||
}
|
||||
|
||||
// pushWordToStack splits the high and low byte of the data passed in, and pushes them to the stack
|
||||
func (a *Appleone) pushDWordToStack(data uint16) {
|
||||
h := uint8((data >> 8) & 0xFF)
|
||||
l := uint8(data & 0xFF)
|
||||
h := byte((data >> 8) & 0xFF)
|
||||
l := byte(data & 0xFF)
|
||||
a.pushWordToStack(h)
|
||||
a.pushWordToStack(l)
|
||||
}
|
||||
|
||||
// popStackWord sets the new stack pointer and returns the appropriate byte in memory
|
||||
func (a *Appleone) popStackWord() uint8 {
|
||||
a.cpu.sp = uint8((uint16(a.cpu.sp) + 1) & 0xFF)
|
||||
func (a *Appleone) popStackWord() byte {
|
||||
a.cpu.sp = byte((uint16(a.cpu.sp) + 1) & 0xFF)
|
||||
return a.mem[StackBottom+uint16(a.cpu.sp)]
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ func (a *Appleone) popStackDWord() uint16 {
|
|||
}
|
||||
|
||||
// nextWord returns the next byte in memory
|
||||
func (a *Appleone) nextWord() uint8 {
|
||||
func (a *Appleone) nextWord() byte {
|
||||
return a.mem[a.cpu.pc-1]
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ func (a *Appleone) nextDWord() uint16 {
|
|||
return a.littleEndianToUint16(a.mem[a.cpu.pc-1], a.mem[a.cpu.pc-2])
|
||||
}
|
||||
|
||||
func (a *Appleone) setZeroIfNeeded(word uint8) {
|
||||
func (a *Appleone) setZeroIfNeeded(word byte) {
|
||||
a.clearZero()
|
||||
if word == 0 {
|
||||
a.setZero()
|
||||
|
@ -92,7 +92,11 @@ func (a *Appleone) clearZero() {
|
|||
a.cpu.sp &^= flagZero
|
||||
}
|
||||
|
||||
func (a *Appleone) setNegativeIfOverflow(word uint8) {
|
||||
func (a *Appleone) getNegative() byte {
|
||||
return a.cpu.ps & flagNegative
|
||||
}
|
||||
|
||||
func (a *Appleone) setNegativeIfOverflow(word byte) {
|
||||
a.clearNegative()
|
||||
if word > 127 {
|
||||
a.setNegative()
|
||||
|
@ -107,7 +111,7 @@ func (a *Appleone) clearNegative() {
|
|||
a.cpu.sp &^= flagZero
|
||||
}
|
||||
|
||||
func (a *Appleone) getCarry() uint8 {
|
||||
func (a *Appleone) getCarry() byte {
|
||||
return a.cpu.sp & flagCarry
|
||||
}
|
||||
|
||||
|
@ -119,6 +123,10 @@ func (a *Appleone) clearCarry() {
|
|||
a.cpu.sp &^= flagCarry
|
||||
}
|
||||
|
||||
func (a *Appleone) getOverflow() byte {
|
||||
return a.cpu.ps & flagOverflow
|
||||
}
|
||||
|
||||
func (a *Appleone) setOverflow() {
|
||||
a.cpu.sp |= flagOverflow
|
||||
}
|
||||
|
@ -126,3 +134,53 @@ func (a *Appleone) setOverflow() {
|
|||
func (a *Appleone) clearOverflow() {
|
||||
a.cpu.sp &^= flagOverflow
|
||||
}
|
||||
|
||||
func (a *Appleone) getZero() byte {
|
||||
return a.cpu.ps & flagZero
|
||||
}
|
||||
|
||||
func (a *Appleone) branch(o op) error {
|
||||
offset, err := o.getOperand(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if offset > 127 {
|
||||
a.cpu.pc -= 256 - uint16(offset)
|
||||
} else {
|
||||
a.cpu.pc += uint16(offset)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Appleone) compare(b1, b2 byte) {
|
||||
a.clearZero()
|
||||
a.clearCarry()
|
||||
a.clearNegative()
|
||||
|
||||
if b1 == b2 {
|
||||
a.setZero()
|
||||
a.setCarry()
|
||||
}
|
||||
if b1 > b2 {
|
||||
a.setCarry()
|
||||
}
|
||||
|
||||
sum := byte(uint16(b1) - uint16(b2))
|
||||
a.setNegativeIfOverflow(sum)
|
||||
}
|
||||
|
||||
func (a *Appleone) setDec() {
|
||||
a.cpu.sp |= flagDecimalMode
|
||||
}
|
||||
|
||||
func (a *Appleone) clearDec() {
|
||||
a.cpu.sp &^= flagDecimalMode
|
||||
}
|
||||
|
||||
func (a *Appleone) setInterrupt() {
|
||||
a.cpu.sp |= flagDisableInterrupts
|
||||
}
|
||||
|
||||
func (a *Appleone) clearInterrupt() {
|
||||
a.cpu.sp &^= flagDisableInterrupts
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue