mirror of
https://github.com/bradford-hamilton/apple-1.git
synced 2024-06-01 05:41:30 +00:00
internal/vm: add the first few opcode handlers
Still a little iffy on the code design, although this seems like it could be a desirable pattern. This way I would have to write an opcode handler for all the cases and register it to the “op”. That way step calls are super simple from Appleone’s point of view -> get the operation and that operation has everything needed to execute on the vm.
This commit is contained in:
parent
e91c4cdbca
commit
cdca8f735d
|
@ -1,4 +1,7 @@
|
||||||
// Package cpu emulates a Mos6502 cpu
|
// Package vm emulates a MOS Technology 6502 Microprocessor which is an 8-bit microprocessor
|
||||||
|
// that was designed by a small team led by Chuck Peddle for MOS Technology. The design team
|
||||||
|
// had formerly worked at Motorola on the Motorola 6800 project; the 6502 is essentially
|
||||||
|
// simplified, less expensive and faster version of that design.
|
||||||
//
|
//
|
||||||
// A .... Accumulator OPC A operand is AC (implied single byte instruction)
|
// A .... Accumulator OPC A operand is AC (implied single byte instruction)
|
||||||
// abs .... absolute OPC $LLHH operand is address $HHLL *
|
// abs .... absolute OPC $LLHH operand is address $HHLL *
|
||||||
|
@ -16,21 +19,11 @@
|
||||||
//
|
//
|
||||||
// 16-bit address words are little endian, lo(w)-byte first, followed by the hi(gh)-byte.
|
// 16-bit address words are little endian, lo(w)-byte first, followed by the hi(gh)-byte.
|
||||||
//
|
//
|
||||||
// SR Flags (bit 7 to bit 0):
|
|
||||||
// N .... Negative
|
|
||||||
// V .... Overflow
|
|
||||||
// - .... ignored
|
|
||||||
// B .... Break
|
|
||||||
// D .... Decimal (use BCD for arithmetics)
|
|
||||||
// I .... Interrupt (IRQ disable)
|
|
||||||
// Z .... Zero
|
|
||||||
// C .... Carry
|
|
||||||
//
|
|
||||||
// Processor Stack:
|
// Processor Stack:
|
||||||
// LIFO, top down, 8 bit range, 0x0100 - 0x01FF
|
// LIFO, top down, 8 bit range, 0x0100 - 0x01FF
|
||||||
//
|
//
|
||||||
// 6502 instructions have the general form AAABBBCC, where AAA and CC define the opcode, and BBB defines the addressing mode
|
// 6502 instructions have the general form AAABBBCC, where AAA and CC define the opcode, and BBB defines the addressing mode
|
||||||
package cpu
|
package vm
|
||||||
|
|
||||||
// addrMode is a type alias for a string, used below for defining addressing modes
|
// addrMode is a type alias for a string, used below for defining addressing modes
|
||||||
type addrMode int
|
type addrMode int
|
||||||
|
@ -88,8 +81,8 @@ type Mos6502 struct {
|
||||||
ps uint8 // register - processor status
|
ps uint8 // register - processor status
|
||||||
}
|
}
|
||||||
|
|
||||||
// New TODO: docs
|
// newCPU TODO: docs
|
||||||
func New() *Mos6502 {
|
func newCPU() *Mos6502 {
|
||||||
return &Mos6502{
|
return &Mos6502{
|
||||||
sp: 0xFF,
|
sp: 0xFF,
|
||||||
pc: 0,
|
pc: 0,
|
17
internal/vm/mem.go
Normal file
17
internal/vm/mem.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package vm
|
||||||
|
|
||||||
|
// block represents a 64kiB memory block
|
||||||
|
type block [64 * 1024]byte
|
||||||
|
|
||||||
|
func newBlock() [64 * 1024]byte {
|
||||||
|
return [64 * 1024]byte{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// load loads a program into memory at the provided address space
|
||||||
|
func (b block) load(addr uint16, data []uint8) {
|
||||||
|
end := int(addr) + len(data)
|
||||||
|
|
||||||
|
for i := int(addr); i < end; i++ {
|
||||||
|
b[int(addr)+i] = data[i]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,9 @@
|
||||||
package cpu
|
package vm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// op represents an operation. It includes the name of the op, it's 8 bit hexidecimal
|
// op represents an operation. It includes the name of the op, it's 8 bit hexidecimal
|
||||||
// opcode, how many bytes it occupies (it's size), as well as it's addressing mode.
|
// opcode, how many bytes it occupies (it's size), as well as it's addressing mode.
|
||||||
|
@ -7,17 +12,61 @@ type op struct {
|
||||||
opcode uint8
|
opcode uint8
|
||||||
size uint8
|
size uint8
|
||||||
addrMode addrMode
|
addrMode addrMode
|
||||||
|
exec func(a *Appleone, o op) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOp(name string, opcode, size uint8, addrMode addrMode) op {
|
func newOp(name string, opcode, size uint8, addrMode addrMode, exec func(a *Appleone, o op) error) op {
|
||||||
return op{
|
return op{
|
||||||
name: name,
|
name: name,
|
||||||
opcode: opcode,
|
opcode: opcode,
|
||||||
size: size,
|
size: size,
|
||||||
addrMode: addrMode,
|
addrMode: addrMode,
|
||||||
|
exec: exec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// opByCode takes an opcode (a single byte/word) and returns the associated operation
|
||||||
|
func opByCode(b byte) (op, error) {
|
||||||
|
o, ok := opcodes[b]
|
||||||
|
if !ok {
|
||||||
|
return op{}, errors.New("unknown opcode")
|
||||||
|
}
|
||||||
|
return o, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// interrupt, N Z C I D V
|
||||||
|
// push PC+2, push SR - - - 1 - -
|
||||||
|
func exec0x00(a *Appleone, o op) error {
|
||||||
|
// set processer status flag to BRK
|
||||||
|
a.cpu.ps = flagBreak
|
||||||
|
|
||||||
|
a.pushDWordToStack(a.cpu.pc + 1)
|
||||||
|
a.pushWordToStack(a.cpu.ps)
|
||||||
|
|
||||||
|
a.cpu.ps |= flagDisableInterrupts
|
||||||
|
a.cpu.pc = uint16(a.mem[0xFFFF])<<8 | uint16(a.mem[0xFFFE])
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pull SR, pull PC N Z C I D V
|
||||||
|
// from stack
|
||||||
|
func exec0x40(a *Appleone, o op) error {
|
||||||
|
a.cpu.ps = a.popStackWord()
|
||||||
|
a.cpu.pc = a.popStackDWord()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func exec0xC6(a *Appleone, o op) error {
|
||||||
|
fmt.Println("Implement me")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func todo(a *Appleone, o op) error {
|
||||||
|
fmt.Println("implement me")
|
||||||
|
return 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{
|
||||||
|
@ -25,13 +74,13 @@ var opcodes = map[uint8]op{
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied BRK 00 1 7
|
// implied BRK 00 1 7
|
||||||
0x00: newOp("BRK", 0x00, 1, implied),
|
0x00: newOp("BRK", 0x00, 1, implied, exec0x00),
|
||||||
|
|
||||||
// RTI Return from Interrupt
|
// RTI Return from Interrupt
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied RTI 40 1 6
|
// implied RTI 40 1 6
|
||||||
0x40: newOp("RTI", 0x40, 1, implied),
|
0x40: newOp("RTI", 0x40, 1, implied, exec0x40),
|
||||||
|
|
||||||
// DEC Decrement Memory by One
|
// DEC Decrement Memory by One
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -40,10 +89,10 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X DEC oper,X D6 2 6
|
// zeropage,X DEC oper,X D6 2 6
|
||||||
// absolute DEC oper CE 3 6
|
// absolute DEC oper CE 3 6
|
||||||
// absolute,X DEC oper,X DE 3 7
|
// absolute,X DEC oper,X DE 3 7
|
||||||
0xC6: newOp("DEC", 0xC6, 2, zeroPage),
|
0xC6: newOp("DEC", 0xC6, 2, zeroPage, exec0xC6),
|
||||||
0xD6: newOp("DEC", 0xD6, 2, zeroPageXIndexed),
|
0xD6: newOp("DEC", 0xD6, 2, zeroPageXIndexed, todo),
|
||||||
0xCE: newOp("DEC", 0xCE, 3, absolute),
|
0xCE: newOp("DEC", 0xCE, 3, absolute, todo),
|
||||||
0xDE: newOp("DEC", 0xDE, 3, absoluteXIndexed),
|
0xDE: newOp("DEC", 0xDE, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// INC Increment Memory by One
|
// INC Increment Memory by One
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -52,46 +101,46 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X INC oper,X F6 2 6
|
// zeropage,X INC oper,X F6 2 6
|
||||||
// absolute INC oper EE 3 6
|
// absolute INC oper EE 3 6
|
||||||
// absolute,X INC oper,X FE 3 7
|
// absolute,X INC oper,X FE 3 7
|
||||||
0xE6: newOp("INC", 0xE6, 2, zeroPage),
|
0xE6: newOp("INC", 0xE6, 2, zeroPage, todo),
|
||||||
0xF6: newOp("INC", 0xF6, 2, zeroPageXIndexed),
|
0xF6: newOp("INC", 0xF6, 2, zeroPageXIndexed, todo),
|
||||||
0xEE: newOp("INC", 0xEE, 3, absolute),
|
0xEE: newOp("INC", 0xEE, 3, absolute, todo),
|
||||||
0xFE: newOp("INC", 0xFE, 3, absoluteXIndexed),
|
0xFE: newOp("INC", 0xFE, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// INX Increment Index X by One
|
// INX Increment Index X by One
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied INX E8 1 2
|
// implied INX E8 1 2
|
||||||
0xE8: newOp("INX", 0xE8, 1, implied),
|
0xE8: newOp("INX", 0xE8, 1, implied, todo),
|
||||||
|
|
||||||
// INY Increment Index Y by One
|
// INY Increment Index Y by One
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied INY C8 1 2
|
// implied INY C8 1 2
|
||||||
0xC8: newOp("INY", 0xC8, 1, implied),
|
0xC8: newOp("INY", 0xC8, 1, implied, todo),
|
||||||
|
|
||||||
// TAX Transfer Accumulator to Index X
|
// TAX Transfer Accumulator to Index X
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied TAX AA 1 2
|
// implied TAX AA 1 2
|
||||||
0xAA: newOp("TAX", 0xAA, 1, implied),
|
0xAA: newOp("TAX", 0xAA, 1, implied, todo),
|
||||||
|
|
||||||
// TAY Transfer Accumulator to Index Y
|
// TAY Transfer Accumulator to Index Y
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied TAY A8 1 2
|
// implied TAY A8 1 2
|
||||||
0xA8: newOp("TAY", 0xA8, 1, implied),
|
0xA8: newOp("TAY", 0xA8, 1, implied, todo),
|
||||||
|
|
||||||
// DEX Decrement Index X by One
|
// DEX Decrement Index X by One
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied DEC CA 1 2
|
// implied DEC CA 1 2
|
||||||
0xCA: newOp("DEX", 0xCA, 1, implied),
|
0xCA: newOp("DEX", 0xCA, 1, implied, todo),
|
||||||
|
|
||||||
// DEY Decrement Index Y by One
|
// DEY Decrement Index Y by One
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied DEC 88 1 2
|
// implied DEC 88 1 2
|
||||||
0x88: newOp("DEY", 0x88, 1, implied),
|
0x88: newOp("DEY", 0x88, 1, implied, todo),
|
||||||
|
|
||||||
// LDA Load Accumulator with Memory
|
// LDA Load Accumulator with Memory
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -104,14 +153,14 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y LDA oper,Y B9 3 4*
|
// absolute,Y LDA oper,Y B9 3 4*
|
||||||
// (indirect,X) LDA (oper,X) A1 2 6
|
// (indirect,X) LDA (oper,X) A1 2 6
|
||||||
// (indirect),Y LDA (oper),Y B1 2 5*
|
// (indirect),Y LDA (oper),Y B1 2 5*
|
||||||
0xA9: newOp("LDA", 0xA9, 2, immediate),
|
0xA9: newOp("LDA", 0xA9, 2, immediate, todo),
|
||||||
0xA5: newOp("LDA", 0xA5, 2, zeroPage),
|
0xA5: newOp("LDA", 0xA5, 2, zeroPage, todo),
|
||||||
0xB5: newOp("LDA", 0xB5, 2, zeroPageXIndexed),
|
0xB5: newOp("LDA", 0xB5, 2, zeroPageXIndexed, todo),
|
||||||
0xAD: newOp("LDA", 0xAD, 3, absolute),
|
0xAD: newOp("LDA", 0xAD, 3, absolute, todo),
|
||||||
0xBD: newOp("LDA", 0xBD, 3, absoluteXIndexed),
|
0xBD: newOp("LDA", 0xBD, 3, absoluteXIndexed, todo),
|
||||||
0xB9: newOp("LDA", 0xB9, 3, absoluteYIndexed),
|
0xB9: newOp("LDA", 0xB9, 3, absoluteYIndexed, todo),
|
||||||
0xA1: newOp("LDA", 0xA1, 2, indirectXIndexed),
|
0xA1: newOp("LDA", 0xA1, 2, indirectXIndexed, todo),
|
||||||
0xB1: newOp("LDA", 0xB1, 2, indirectYIndexed),
|
0xB1: newOp("LDA", 0xB1, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// LDX Load Index X with Memory
|
// LDX Load Index X with Memory
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -121,11 +170,11 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,Y LDX oper,Y B6 2 4
|
// zeropage,Y LDX oper,Y B6 2 4
|
||||||
// absolute LDX oper AE 3 4
|
// absolute LDX oper AE 3 4
|
||||||
// absolute,Y LDX oper,Y BE 3 4*
|
// absolute,Y LDX oper,Y BE 3 4*
|
||||||
0xA2: newOp("LDX", 0xA2, 2, immediate),
|
0xA2: newOp("LDX", 0xA2, 2, immediate, todo),
|
||||||
0xA6: newOp("LDX", 0xA6, 2, zeroPage),
|
0xA6: newOp("LDX", 0xA6, 2, zeroPage, todo),
|
||||||
0xB6: newOp("LDX", 0xB6, 2, zeroPageYIndexed),
|
0xB6: newOp("LDX", 0xB6, 2, zeroPageYIndexed, todo),
|
||||||
0xAE: newOp("LDX", 0xAE, 3, absolute),
|
0xAE: newOp("LDX", 0xAE, 3, absolute, todo),
|
||||||
0xBE: newOp("LDX", 0xBE, 3, absoluteYIndexed),
|
0xBE: newOp("LDX", 0xBE, 3, absoluteYIndexed, todo),
|
||||||
|
|
||||||
// LDY Load Index Y with Memory
|
// LDY Load Index Y with Memory
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -135,11 +184,11 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X LDY oper,X B4 2 4
|
// zeropage,X LDY oper,X B4 2 4
|
||||||
// absolute LDY oper AC 3 4
|
// absolute LDY oper AC 3 4
|
||||||
// absolute,X LDY oper,X BC 3 4*
|
// absolute,X LDY oper,X BC 3 4*
|
||||||
0xA0: newOp("LDY", 0xA0, 2, immediate),
|
0xA0: newOp("LDY", 0xA0, 2, immediate, todo),
|
||||||
0xA4: newOp("LDY", 0xA4, 2, zeroPage),
|
0xA4: newOp("LDY", 0xA4, 2, zeroPage, todo),
|
||||||
0xB4: newOp("LDY", 0xB4, 2, zeroPageXIndexed),
|
0xB4: newOp("LDY", 0xB4, 2, zeroPageXIndexed, todo),
|
||||||
0xAC: newOp("LDY", 0xAC, 3, absolute),
|
0xAC: newOp("LDY", 0xAC, 3, absolute, todo),
|
||||||
0xBC: newOp("LDY", 0xBC, 3, absoluteXIndexed),
|
0xBC: newOp("LDY", 0xBC, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// ADC Add Memory to Accumulator with Carry
|
// ADC Add Memory to Accumulator with Carry
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -152,14 +201,14 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y ADC oper,Y 79 3 4*
|
// absolute,Y ADC oper,Y 79 3 4*
|
||||||
// (indirect,X) ADC (oper,X) 61 2 6
|
// (indirect,X) ADC (oper,X) 61 2 6
|
||||||
// (indirect),Y ADC (oper),Y 71 2 5*
|
// (indirect),Y ADC (oper),Y 71 2 5*
|
||||||
0x69: newOp("ADC", 0x69, 2, immediate),
|
0x69: newOp("ADC", 0x69, 2, immediate, todo),
|
||||||
0x65: newOp("ADC", 0x65, 2, zeroPage),
|
0x65: newOp("ADC", 0x65, 2, zeroPage, todo),
|
||||||
0x75: newOp("ADC", 0x75, 2, zeroPageXIndexed),
|
0x75: newOp("ADC", 0x75, 2, zeroPageXIndexed, todo),
|
||||||
0x6D: newOp("ADC", 0x6D, 3, absolute),
|
0x6D: newOp("ADC", 0x6D, 3, absolute, todo),
|
||||||
0x7D: newOp("ADC", 0x7D, 3, absoluteXIndexed),
|
0x7D: newOp("ADC", 0x7D, 3, absoluteXIndexed, todo),
|
||||||
0x79: newOp("ADC", 0x79, 3, absoluteYIndexed),
|
0x79: newOp("ADC", 0x79, 3, absoluteYIndexed, todo),
|
||||||
0x61: newOp("ADC", 0x61, 2, indirectXIndexed),
|
0x61: newOp("ADC", 0x61, 2, indirectXIndexed, todo),
|
||||||
0x71: newOp("ADC", 0x71, 2, indirectYIndexed),
|
0x71: newOp("ADC", 0x71, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// SBC Subtract Memory from Accumulator with Borrow
|
// SBC Subtract Memory from Accumulator with Borrow
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -172,14 +221,14 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y SBC oper,Y F9 3 4*
|
// absolute,Y SBC oper,Y F9 3 4*
|
||||||
// (indirect,X) SBC (oper,X) E1 2 6
|
// (indirect,X) SBC (oper,X) E1 2 6
|
||||||
// (indirect),Y SBC (oper),Y F1 2 5*
|
// (indirect),Y SBC (oper),Y F1 2 5*
|
||||||
0xE9: newOp("SBC", 0xE9, 2, immediate),
|
0xE9: newOp("SBC", 0xE9, 2, immediate, todo),
|
||||||
0xE5: newOp("SBC", 0xE5, 2, zeroPage),
|
0xE5: newOp("SBC", 0xE5, 2, zeroPage, todo),
|
||||||
0xF5: newOp("SBC", 0xF5, 2, zeroPageXIndexed),
|
0xF5: newOp("SBC", 0xF5, 2, zeroPageXIndexed, todo),
|
||||||
0xED: newOp("SBC", 0xED, 3, absolute),
|
0xED: newOp("SBC", 0xED, 3, absolute, todo),
|
||||||
0xFD: newOp("SBC", 0xFD, 3, absoluteXIndexed),
|
0xFD: newOp("SBC", 0xFD, 3, absoluteXIndexed, todo),
|
||||||
0xF9: newOp("SBC", 0xF9, 3, absoluteYIndexed),
|
0xF9: newOp("SBC", 0xF9, 3, absoluteYIndexed, todo),
|
||||||
0xE1: newOp("SBC", 0xE1, 2, indirectXIndexed),
|
0xE1: newOp("SBC", 0xE1, 2, indirectXIndexed, todo),
|
||||||
0xF1: newOp("SBC", 0xF1, 2, indirectYIndexed),
|
0xF1: newOp("SBC", 0xF1, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// STX Store Index X in Memory
|
// STX Store Index X in Memory
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -187,9 +236,9 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage STX oper 86 2 3
|
// zeropage STX oper 86 2 3
|
||||||
// zeropage,Y STX oper,Y 96 2 4
|
// zeropage,Y STX oper,Y 96 2 4
|
||||||
// absolute STX oper 8E 3 4
|
// absolute STX oper 8E 3 4
|
||||||
0x86: newOp("STX", 0x86, 2, zeroPage),
|
0x86: newOp("STX", 0x86, 2, zeroPage, todo),
|
||||||
0x96: newOp("STX", 0x96, 2, zeroPageYIndexed),
|
0x96: newOp("STX", 0x96, 2, zeroPageYIndexed, todo),
|
||||||
0x8E: newOp("STX", 0x8E, 3, absolute),
|
0x8E: newOp("STX", 0x8E, 3, absolute, todo),
|
||||||
|
|
||||||
// STY Store Index Y in Memory
|
// STY Store Index Y in Memory
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -197,9 +246,9 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage STY oper 84 2 3
|
// zeropage STY oper 84 2 3
|
||||||
// zeropage,X STY oper,X 94 2 4
|
// zeropage,X STY oper,X 94 2 4
|
||||||
// absolute STY oper 8C 3 4
|
// absolute STY oper 8C 3 4
|
||||||
0x84: newOp("STY", 0x84, 2, zeroPage),
|
0x84: newOp("STY", 0x84, 2, zeroPage, todo),
|
||||||
0x94: newOp("STY", 0x94, 2, zeroPageXIndexed),
|
0x94: newOp("STY", 0x94, 2, zeroPageXIndexed, todo),
|
||||||
0x8C: newOp("STY", 0x8C, 3, absolute),
|
0x8C: newOp("STY", 0x8C, 3, absolute, todo),
|
||||||
|
|
||||||
// STA Store Accumulator in Memory
|
// STA Store Accumulator in Memory
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -211,69 +260,69 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y STA oper,Y 99 3 5
|
// absolute,Y STA oper,Y 99 3 5
|
||||||
// (indirect,X) STA (oper,X) 81 2 6
|
// (indirect,X) STA (oper,X) 81 2 6
|
||||||
// (indirect),Y STA (oper),Y 91 2 6
|
// (indirect),Y STA (oper),Y 91 2 6
|
||||||
0x85: newOp("STA", 0x85, 2, zeroPage),
|
0x85: newOp("STA", 0x85, 2, zeroPage, todo),
|
||||||
0x95: newOp("STA", 0x95, 2, zeroPageXIndexed),
|
0x95: newOp("STA", 0x95, 2, zeroPageXIndexed, todo),
|
||||||
0x8D: newOp("STA", 0x8D, 3, absolute),
|
0x8D: newOp("STA", 0x8D, 3, absolute, todo),
|
||||||
0x9D: newOp("STA", 0x9D, 3, absoluteXIndexed),
|
0x9D: newOp("STA", 0x9D, 3, absoluteXIndexed, todo),
|
||||||
0x99: newOp("STA", 0x99, 3, absoluteYIndexed),
|
0x99: newOp("STA", 0x99, 3, absoluteYIndexed, todo),
|
||||||
0x81: newOp("STA", 0x81, 2, indirectXIndexed),
|
0x81: newOp("STA", 0x81, 2, indirectXIndexed, todo),
|
||||||
0x91: newOp("STA", 0x91, 2, indirectYIndexed),
|
0x91: newOp("STA", 0x91, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// BEQ Branch on Result Zero
|
// BEQ Branch on Result Zero
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BEQ oper F0 2 2**
|
// relative BEQ oper F0 2 2**
|
||||||
0xF0: newOp("BEQ", 0xF0, 2, relative),
|
0xF0: newOp("BEQ", 0xF0, 2, relative, todo),
|
||||||
|
|
||||||
// BNE Branch on Result not Zero
|
// BNE Branch on Result not Zero
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BNE oper D0 2 2**
|
// relative BNE oper D0 2 2**
|
||||||
0xD0: newOp("BNE", 0xD0, 2, relative),
|
0xD0: newOp("BNE", 0xD0, 2, relative, todo),
|
||||||
|
|
||||||
// BVC Branch on Overflow Clear
|
// BVC Branch on Overflow Clear
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BVC oper 50 2 2**
|
// relative BVC oper 50 2 2**
|
||||||
0x50: newOp("BVC", 0x50, 2, relative),
|
0x50: newOp("BVC", 0x50, 2, relative, todo),
|
||||||
|
|
||||||
// BVS Branch on Overflow Set
|
// BVS Branch on Overflow Set
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BVC oper 70 2 2**
|
// relative BVC oper 70 2 2**
|
||||||
0x70: newOp("BVS", 0x70, 2, relative),
|
0x70: newOp("BVS", 0x70, 2, relative, todo),
|
||||||
|
|
||||||
// BIT Test Bits in Memory with Accumulator
|
// BIT Test Bits in Memory with Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// zeropage BIT oper 24 2 3
|
// zeropage BIT oper 24 2 3
|
||||||
// absolute BIT oper 2C 3 4
|
// absolute BIT oper 2C 3 4
|
||||||
0x24: newOp("BIT", 0x24, 2, zeroPage),
|
0x24: newOp("BIT", 0x24, 2, zeroPage, todo),
|
||||||
0x2C: newOp("BIT", 0x2C, 3, absolute),
|
0x2C: newOp("BIT", 0x2C, 3, absolute, todo),
|
||||||
|
|
||||||
// BCC Branch on Carry Clear
|
// BCC Branch on Carry Clear
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BCC oper 90 2 2**
|
// relative BCC oper 90 2 2**
|
||||||
0x90: newOp("BCC", 0x90, 2, relative),
|
0x90: newOp("BCC", 0x90, 2, relative, todo),
|
||||||
|
|
||||||
// BMI Branch on Result Minus
|
// BMI Branch on Result Minus
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BMI oper 30 2 2**
|
// relative BMI oper 30 2 2**
|
||||||
0x30: newOp("BMI", 0x30, 2, relative),
|
0x30: newOp("BMI", 0x30, 2, relative, todo),
|
||||||
|
|
||||||
// BPL Branch on Result Plus
|
// BPL Branch on Result Plus
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BPL oper 10 2 2**
|
// relative BPL oper 10 2 2**
|
||||||
0x10: newOp("BPL", 0x10, 2, relative),
|
0x10: newOp("BPL", 0x10, 2, relative, todo),
|
||||||
|
|
||||||
// BCS Branch on Carry Set
|
// BCS Branch on Carry Set
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// relative BCS oper B0 2 2**
|
// relative BCS oper B0 2 2**
|
||||||
0xB0: newOp("BCS", 0xB0, 2, relative),
|
0xB0: newOp("BCS", 0xB0, 2, relative, todo),
|
||||||
|
|
||||||
// CPX Compare Memory and Index X
|
// CPX Compare Memory and Index X
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -281,9 +330,9 @@ var opcodes = map[uint8]op{
|
||||||
// immidiate CPX #oper E0 2 2
|
// immidiate CPX #oper E0 2 2
|
||||||
// zeropage CPX oper E4 2 3
|
// zeropage CPX oper E4 2 3
|
||||||
// absolute CPX oper EC 3 4
|
// absolute CPX oper EC 3 4
|
||||||
0xE0: newOp("CPX", 0xE0, 2, immediate),
|
0xE0: newOp("CPX", 0xE0, 2, immediate, todo),
|
||||||
0xE4: newOp("CPX", 0xE4, 2, zeroPage),
|
0xE4: newOp("CPX", 0xE4, 2, zeroPage, todo),
|
||||||
0xEC: newOp("CPX", 0xEC, 3, absolute),
|
0xEC: newOp("CPX", 0xEC, 3, absolute, todo),
|
||||||
|
|
||||||
// EOR Exclusive-OR Memory with Accumulator
|
// EOR Exclusive-OR Memory with Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -296,14 +345,14 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y EOR oper,Y 59 3 4*
|
// absolute,Y EOR oper,Y 59 3 4*
|
||||||
// (indirect,X) EOR (oper,X) 41 2 6
|
// (indirect,X) EOR (oper,X) 41 2 6
|
||||||
// (indirect),Y EOR (oper),Y 51 2 5*
|
// (indirect),Y EOR (oper),Y 51 2 5*
|
||||||
0x49: newOp("EOR", 0x49, 2, immediate),
|
0x49: newOp("EOR", 0x49, 2, immediate, todo),
|
||||||
0x45: newOp("EOR", 0x45, 2, zeroPage),
|
0x45: newOp("EOR", 0x45, 2, zeroPage, todo),
|
||||||
0x55: newOp("EOR", 0x55, 2, zeroPageXIndexed),
|
0x55: newOp("EOR", 0x55, 2, zeroPageXIndexed, todo),
|
||||||
0x4D: newOp("EOR", 0x4D, 3, absolute),
|
0x4D: newOp("EOR", 0x4D, 3, absolute, todo),
|
||||||
0x5D: newOp("EOR", 0x5D, 3, absoluteXIndexed),
|
0x5D: newOp("EOR", 0x5D, 3, absoluteXIndexed, todo),
|
||||||
0x59: newOp("EOR", 0x59, 3, absoluteYIndexed),
|
0x59: newOp("EOR", 0x59, 3, absoluteYIndexed, todo),
|
||||||
0x41: newOp("EOR", 0x41, 2, indirectXIndexed),
|
0x41: newOp("EOR", 0x41, 2, indirectXIndexed, todo),
|
||||||
0x51: newOp("EOR", 0x51, 2, indirectYIndexed),
|
0x51: newOp("EOR", 0x51, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// CMP Compare Memory with Accumulator
|
// CMP Compare Memory with Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -316,14 +365,14 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y CMP oper,Y D9 3 4*
|
// absolute,Y CMP oper,Y D9 3 4*
|
||||||
// (indirect,X) CMP (oper,X) C1 2 6
|
// (indirect,X) CMP (oper,X) C1 2 6
|
||||||
// (indirect),Y CMP (oper),Y D1 2 5*
|
// (indirect),Y CMP (oper),Y D1 2 5*
|
||||||
0xC9: newOp("CMP", 0xC9, 2, immediate),
|
0xC9: newOp("CMP", 0xC9, 2, immediate, todo),
|
||||||
0xC5: newOp("CMP", 0xC5, 2, zeroPage),
|
0xC5: newOp("CMP", 0xC5, 2, zeroPage, todo),
|
||||||
0xD5: newOp("CMP", 0xD5, 2, zeroPageXIndexed),
|
0xD5: newOp("CMP", 0xD5, 2, zeroPageXIndexed, todo),
|
||||||
0xCD: newOp("CMP", 0xCD, 3, absolute),
|
0xCD: newOp("CMP", 0xCD, 3, absolute, todo),
|
||||||
0xDD: newOp("CMP", 0xDD, 3, absoluteXIndexed),
|
0xDD: newOp("CMP", 0xDD, 3, absoluteXIndexed, todo),
|
||||||
0xD9: newOp("CMP", 0xD9, 3, absoluteYIndexed),
|
0xD9: newOp("CMP", 0xD9, 3, absoluteYIndexed, todo),
|
||||||
0xC1: newOp("CMP", 0xC1, 2, indirectXIndexed),
|
0xC1: newOp("CMP", 0xC1, 2, indirectXIndexed, todo),
|
||||||
0xD1: newOp("CMP", 0xD1, 2, indirectYIndexed),
|
0xD1: newOp("CMP", 0xD1, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// CPY Compare Memory and Index Y
|
// CPY Compare Memory and Index Y
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -331,119 +380,119 @@ var opcodes = map[uint8]op{
|
||||||
// immidiate CPY #oper C0 2 2
|
// immidiate CPY #oper C0 2 2
|
||||||
// zeropage CPY oper C4 2 3
|
// zeropage CPY oper C4 2 3
|
||||||
// absolute CPY oper CC 3 4
|
// absolute CPY oper CC 3 4
|
||||||
0xC0: newOp("CPY", 0xC0, 2, immediate),
|
0xC0: newOp("CPY", 0xC0, 2, immediate, todo),
|
||||||
0xC4: newOp("CPY", 0xC4, 2, zeroPage),
|
0xC4: newOp("CPY", 0xC4, 2, zeroPage, todo),
|
||||||
0xCC: newOp("CPY", 0xCC, 3, absolute),
|
0xCC: newOp("CPY", 0xCC, 3, absolute, todo),
|
||||||
|
|
||||||
// CLC Clear Carry Flag
|
// CLC Clear Carry Flag
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied CLC 18 1 2
|
// implied CLC 18 1 2
|
||||||
0x18: newOp("CLC", 0x18, 1, implied),
|
0x18: newOp("CLC", 0x18, 1, implied, todo),
|
||||||
|
|
||||||
// CLD Clear Decimal Mode
|
// CLD Clear Decimal Mode
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied CLD D8 1 2
|
// implied CLD D8 1 2
|
||||||
0xD8: newOp("CLD", 0xD8, 1, implied),
|
0xD8: newOp("CLD", 0xD8, 1, implied, todo),
|
||||||
|
|
||||||
// CLI Clear Interrupt Disable Bit
|
// CLI Clear Interrupt Disable Bit
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied CLI 58 1 2
|
// implied CLI 58 1 2
|
||||||
0x58: newOp("CLI", 0x58, 1, implied),
|
0x58: newOp("CLI", 0x58, 1, implied, todo),
|
||||||
|
|
||||||
// CLV Clear Overflow Flag
|
// CLV Clear Overflow Flag
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied CLV B8 1 2
|
// implied CLV B8 1 2
|
||||||
0xB8: newOp("CLV", 0xB8, 1, implied),
|
0xB8: newOp("CLV", 0xB8, 1, implied, todo),
|
||||||
|
|
||||||
// SEC Set Carry Flag
|
// SEC Set Carry Flag
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied SEC 38 1 2
|
// implied SEC 38 1 2
|
||||||
0x38: newOp("SEC", 0x38, 1, implied),
|
0x38: newOp("SEC", 0x38, 1, implied, todo),
|
||||||
|
|
||||||
// SED Set Decimal Flag
|
// SED Set Decimal Flag
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied SED F8 1 2
|
// implied SED F8 1 2
|
||||||
0xF8: newOp("SED", 0xF8, 1, implied),
|
0xF8: newOp("SED", 0xF8, 1, implied, todo),
|
||||||
|
|
||||||
// SEI Set Interrupt Disable Status
|
// SEI Set Interrupt Disable Status
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied SEI 78 1 2
|
// implied SEI 78 1 2
|
||||||
0x78: newOp("SEI", 0x78, 1, implied),
|
0x78: newOp("SEI", 0x78, 1, implied, todo),
|
||||||
|
|
||||||
// NOP No Operation
|
// NOP No Operation
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied NOP EA 1 2
|
// implied NOP EA 1 2
|
||||||
0xEA: newOp("NOP", 0xEA, 1, implied),
|
0xEA: newOp("NOP", 0xEA, 1, implied, todo),
|
||||||
|
|
||||||
// JMP Jump to New Location
|
// JMP Jump to New Location
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// absolute JMP oper 4C 3 3
|
// absolute JMP oper 4C 3 3
|
||||||
// indirect JMP (oper) 6C 3 5
|
// indirect JMP (oper) 6C 3 5
|
||||||
0x4C: newOp("JMP", 0x4C, 3, absolute),
|
0x4C: newOp("JMP", 0x4C, 3, absolute, todo),
|
||||||
0x6C: newOp("JMP", 0x6C, 3, indirect),
|
0x6C: newOp("JMP", 0x6C, 3, indirect, todo),
|
||||||
|
|
||||||
// PHA Push Accumulator on Stack
|
// PHA Push Accumulator on Stack
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied PHA 48 1 3
|
// implied PHA 48 1 3
|
||||||
0x48: newOp("PHA", 0x48, 1, implied),
|
0x48: newOp("PHA", 0x48, 1, implied, todo),
|
||||||
|
|
||||||
// TXA Transfer Index X to Accumulator
|
// TXA Transfer Index X to Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied TXA 8A 1 2
|
// implied TXA 8A 1 2
|
||||||
0x8A: newOp("TXA", 0x8A, 1, implied),
|
0x8A: newOp("TXA", 0x8A, 1, implied, todo),
|
||||||
|
|
||||||
// TYA Transfer Index Y to Accumulator
|
// TYA Transfer Index Y to Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied TYA 98 1 2
|
// implied TYA 98 1 2
|
||||||
0x98: newOp("TYA", 0x98, 1, implied),
|
0x98: newOp("TYA", 0x98, 1, implied, todo),
|
||||||
|
|
||||||
// TSX Transfer Stack Pointer to Index X
|
// TSX Transfer Stack Pointer to Index X
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied TSX BA 1 2
|
// implied TSX BA 1 2
|
||||||
0xBA: newOp("TSX", 0xBA, 1, implied),
|
0xBA: newOp("TSX", 0xBA, 1, implied, todo),
|
||||||
|
|
||||||
// PLA Pull Accumulator from Stack
|
// PLA Pull Accumulator from Stack
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied PLA 68 1 4
|
// implied PLA 68 1 4
|
||||||
0x68: newOp("PLA", 0x68, 1, implied),
|
0x68: newOp("PLA", 0x68, 1, implied, todo),
|
||||||
|
|
||||||
// PLP Pull Processor Status from Stack
|
// PLP Pull Processor Status from Stack
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied PLP 28 1 4
|
// implied PLP 28 1 4
|
||||||
0x28: newOp("PLP", 0x28, 1, implied),
|
0x28: newOp("PLP", 0x28, 1, implied, todo),
|
||||||
|
|
||||||
// PHP Push Processor Status on Stack
|
// PHP Push Processor Status on Stack
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied PHP 08 1 3
|
// implied PHP 08 1 3
|
||||||
0x08: newOp("PHP", 0x08, 1, implied),
|
0x08: newOp("PHP", 0x08, 1, implied, todo),
|
||||||
|
|
||||||
// JSR Jump to New Location Saving Return Address
|
// JSR Jump to New Location Saving Return Address
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// absolute JSR oper 20 3 6
|
// absolute JSR oper 20 3 6
|
||||||
0x20: newOp("JSR", 0x20, 3, absolute),
|
0x20: newOp("JSR", 0x20, 3, absolute, todo),
|
||||||
|
|
||||||
// RTS Return from Subroutine
|
// RTS Return from Subroutine
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied RTS 60 1 6
|
// implied RTS 60 1 6
|
||||||
0x60: newOp("RTS", 0x60, 1, implied),
|
0x60: newOp("RTS", 0x60, 1, implied, todo),
|
||||||
|
|
||||||
// LSR Shift One Bit Right (Memory or Accumulator)
|
// LSR Shift One Bit Right (Memory or Accumulator)
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -453,11 +502,11 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X LSR oper,X 56 2 6
|
// zeropage,X LSR oper,X 56 2 6
|
||||||
// absolute LSR oper 4E 3 6
|
// absolute LSR oper 4E 3 6
|
||||||
// absolute,X LSR oper,X 5E 3 7
|
// absolute,X LSR oper,X 5E 3 7
|
||||||
0x4A: newOp("LSR", 0x4A, 1, accumulator),
|
0x4A: newOp("LSR", 0x4A, 1, accumulator, todo),
|
||||||
0x46: newOp("LSR", 0x46, 2, zeroPage),
|
0x46: newOp("LSR", 0x46, 2, zeroPage, todo),
|
||||||
0x56: newOp("LSR", 0x56, 2, zeroPageXIndexed),
|
0x56: newOp("LSR", 0x56, 2, zeroPageXIndexed, todo),
|
||||||
0x4E: newOp("LSR", 0x4E, 3, absolute),
|
0x4E: newOp("LSR", 0x4E, 3, absolute, todo),
|
||||||
0x5E: newOp("LSR", 0x5E, 3, absoluteXIndexed),
|
0x5E: newOp("LSR", 0x5E, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// ROL Rotate One Bit Left (Memory or Accumulator)
|
// ROL Rotate One Bit Left (Memory or Accumulator)
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -467,17 +516,17 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X ROL oper,X 36 2 6
|
// zeropage,X ROL oper,X 36 2 6
|
||||||
// absolute ROL oper 2E 3 6
|
// absolute ROL oper 2E 3 6
|
||||||
// absolute,X ROL oper,X 3E 3 7
|
// absolute,X ROL oper,X 3E 3 7
|
||||||
0x2A: newOp("ROL", 0x2A, 1, accumulator),
|
0x2A: newOp("ROL", 0x2A, 1, accumulator, todo),
|
||||||
0x26: newOp("ROL", 0x26, 2, zeroPage),
|
0x26: newOp("ROL", 0x26, 2, zeroPage, todo),
|
||||||
0x36: newOp("ROL", 0x36, 2, zeroPageXIndexed),
|
0x36: newOp("ROL", 0x36, 2, zeroPageXIndexed, todo),
|
||||||
0x2E: newOp("ROL", 0x2E, 3, absolute),
|
0x2E: newOp("ROL", 0x2E, 3, absolute, todo),
|
||||||
0x3E: newOp("ROL", 0x3E, 3, absoluteXIndexed),
|
0x3E: newOp("ROL", 0x3E, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// TXS Transfer Index X to Stack Register
|
// TXS Transfer Index X to Stack Register
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
// implied TXS 9A 1 2
|
// implied TXS 9A 1 2
|
||||||
0x9A: newOp("TXS", 0x9A, 1, implied),
|
0x9A: newOp("TXS", 0x9A, 1, implied, todo),
|
||||||
|
|
||||||
// ROR Rotate One Bit Right (Memory or Accumulator)
|
// ROR Rotate One Bit Right (Memory or Accumulator)
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -487,11 +536,11 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X ROR oper,X 76 2 6
|
// zeropage,X ROR oper,X 76 2 6
|
||||||
// absolute ROR oper 6E 3 6
|
// absolute ROR oper 6E 3 6
|
||||||
// absolute,X ROR oper,X 7E 3 7
|
// absolute,X ROR oper,X 7E 3 7
|
||||||
0x6A: newOp("ROR", 0x6A, 1, accumulator),
|
0x6A: newOp("ROR", 0x6A, 1, accumulator, todo),
|
||||||
0x66: newOp("ROR", 0x66, 2, zeroPage),
|
0x66: newOp("ROR", 0x66, 2, zeroPage, todo),
|
||||||
0x76: newOp("ROR", 0x76, 2, zeroPageXIndexed),
|
0x76: newOp("ROR", 0x76, 2, zeroPageXIndexed, todo),
|
||||||
0x6E: newOp("ROR", 0x6E, 3, absolute),
|
0x6E: newOp("ROR", 0x6E, 3, absolute, todo),
|
||||||
0x7E: newOp("ROR", 0x7E, 3, absoluteXIndexed),
|
0x7E: newOp("ROR", 0x7E, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// ASL Shift Left One Bit (Memory or Accumulator)
|
// ASL Shift Left One Bit (Memory or Accumulator)
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -501,11 +550,11 @@ var opcodes = map[uint8]op{
|
||||||
// zeropage,X ASL oper,X 16 2 6
|
// zeropage,X ASL oper,X 16 2 6
|
||||||
// absolute ASL oper 0E 3 6
|
// absolute ASL oper 0E 3 6
|
||||||
// absolute,X ASL oper,X 1E 3 7
|
// absolute,X ASL oper,X 1E 3 7
|
||||||
0x0A: newOp("ASL", 0x0A, 1, accumulator),
|
0x0A: newOp("ASL", 0x0A, 1, accumulator, todo),
|
||||||
0x06: newOp("ASL", 0x06, 2, zeroPage),
|
0x06: newOp("ASL", 0x06, 2, zeroPage, todo),
|
||||||
0x16: newOp("ASL", 0x16, 2, zeroPageXIndexed),
|
0x16: newOp("ASL", 0x16, 2, zeroPageXIndexed, todo),
|
||||||
0x0E: newOp("ASL", 0x0E, 3, absolute),
|
0x0E: newOp("ASL", 0x0E, 3, absolute, todo),
|
||||||
0x1E: newOp("ASL", 0x1E, 3, absoluteXIndexed),
|
0x1E: newOp("ASL", 0x1E, 3, absoluteXIndexed, todo),
|
||||||
|
|
||||||
// AND AND Memory with Accumulator
|
// AND AND Memory with Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -518,14 +567,14 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y AND oper,Y 39 3 4*
|
// absolute,Y AND oper,Y 39 3 4*
|
||||||
// (indirect,X) AND (oper,X) 21 2 6
|
// (indirect,X) AND (oper,X) 21 2 6
|
||||||
// (indirect),Y AND (oper),Y 31 2 5*
|
// (indirect),Y AND (oper),Y 31 2 5*
|
||||||
0x29: newOp("AND", 0x29, 2, immediate),
|
0x29: newOp("AND", 0x29, 2, immediate, todo),
|
||||||
0x25: newOp("AND", 0x25, 2, zeroPage),
|
0x25: newOp("AND", 0x25, 2, zeroPage, todo),
|
||||||
0x35: newOp("AND", 0x35, 2, zeroPageXIndexed),
|
0x35: newOp("AND", 0x35, 2, zeroPageXIndexed, todo),
|
||||||
0x2D: newOp("AND", 0x2D, 3, absolute),
|
0x2D: newOp("AND", 0x2D, 3, absolute, todo),
|
||||||
0x3D: newOp("AND", 0x3D, 3, absoluteXIndexed),
|
0x3D: newOp("AND", 0x3D, 3, absoluteXIndexed, todo),
|
||||||
0x39: newOp("AND", 0x39, 3, absoluteYIndexed),
|
0x39: newOp("AND", 0x39, 3, absoluteYIndexed, todo),
|
||||||
0x21: newOp("AND", 0x21, 2, indirectXIndexed),
|
0x21: newOp("AND", 0x21, 2, indirectXIndexed, todo),
|
||||||
0x31: newOp("AND", 0x31, 2, indirectYIndexed),
|
0x31: newOp("AND", 0x31, 2, indirectYIndexed, todo),
|
||||||
|
|
||||||
// ORA OR Memory with Accumulator
|
// ORA OR Memory with Accumulator
|
||||||
// addressing assembler opc bytes cyles
|
// addressing assembler opc bytes cyles
|
||||||
|
@ -538,12 +587,12 @@ var opcodes = map[uint8]op{
|
||||||
// absolute,Y ORA oper,Y 19 3 4*
|
// absolute,Y ORA oper,Y 19 3 4*
|
||||||
// (indirect,X) ORA (oper,X) 01 2 6
|
// (indirect,X) ORA (oper,X) 01 2 6
|
||||||
// (indirect),Y ORA (oper),Y 11 2 5*
|
// (indirect),Y ORA (oper),Y 11 2 5*
|
||||||
0x09: newOp("ORA", 0x09, 2, immediate),
|
0x09: newOp("ORA", 0x09, 2, immediate, todo),
|
||||||
0x05: newOp("ORA", 0x05, 2, zeroPage),
|
0x05: newOp("ORA", 0x05, 2, zeroPage, todo),
|
||||||
0x15: newOp("ORA", 0x15, 2, zeroPageXIndexed),
|
0x15: newOp("ORA", 0x15, 2, zeroPageXIndexed, todo),
|
||||||
0x0D: newOp("ORA", 0x0D, 3, absolute),
|
0x0D: newOp("ORA", 0x0D, 3, absolute, todo),
|
||||||
0x1D: newOp("ORA", 0x1D, 3, absoluteXIndexed),
|
0x1D: newOp("ORA", 0x1D, 3, absoluteXIndexed, todo),
|
||||||
0x19: newOp("ORA", 0x19, 3, absoluteYIndexed),
|
0x19: newOp("ORA", 0x19, 3, absoluteYIndexed, todo),
|
||||||
0x01: newOp("ORA", 0x01, 2, indirectXIndexed),
|
0x01: newOp("ORA", 0x01, 2, indirectXIndexed, todo),
|
||||||
0x11: newOp("ORA", 0x11, 2, indirectYIndexed),
|
0x11: newOp("ORA", 0x11, 2, indirectYIndexed, todo),
|
||||||
}
|
}
|
|
@ -1,17 +1,60 @@
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
import "github.com/bradford-hamilton/apple-1/internal/cpu"
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
// Appleone represents the virtual Apple 1 computer
|
// Appleone represents the virtual Apple 1 computer
|
||||||
type Appleone struct {
|
type Appleone struct {
|
||||||
cpu *cpu.Mos6502 // virtual Mos6502 cpu
|
cpu *Mos6502 // virtual mos6502 cpu
|
||||||
mem [64 * 1024]byte // available memory (64kiB)
|
mem block // available memory (64kiB)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a pointer to an initialized Appleone with a brand spankin new CPU
|
// New returns a pointer to an initialized Appleone with a brand spankin new CPU
|
||||||
func New() *Appleone {
|
func New() *Appleone {
|
||||||
return &Appleone{
|
return &Appleone{
|
||||||
cpu: cpu.New(),
|
cpu: newCPU(),
|
||||||
mem: [64 * 1024]byte{},
|
mem: newBlock(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) load(addr uint16, data []uint8) {
|
||||||
|
a.mem.load(addr, data)
|
||||||
|
a.cpu.pc = addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) step() {
|
||||||
|
op, err := opByCode(a.mem[a.cpu.pc])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("TODO")
|
||||||
|
}
|
||||||
|
|
||||||
|
a.cpu.pc += uint16(op.size)
|
||||||
|
|
||||||
|
if err := op.exec(a, op); err != nil {
|
||||||
|
fmt.Println("TODO")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) pushWordToStack(data byte) {
|
||||||
|
a.mem[StackBottom+uint16(a.cpu.sp)] = data
|
||||||
|
a.cpu.sp = uint8((uint16(a.cpu.sp) - 1) & 0xFF)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) pushDWordToStack(data uint16) {
|
||||||
|
h := uint8((data >> 8) & 0xFF)
|
||||||
|
l := uint8(data & 0xFF)
|
||||||
|
a.pushWordToStack(h)
|
||||||
|
a.pushWordToStack(l)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) popStackWord() uint8 {
|
||||||
|
a.cpu.sp = uint8((uint16(a.cpu.sp) + 1) & 0xFF)
|
||||||
|
return a.mem[StackBottom+uint16(a.cpu.sp)]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Appleone) popStackDWord() uint16 {
|
||||||
|
l := a.popStackWord()
|
||||||
|
h := a.popStackWord()
|
||||||
|
return (uint16(h) << 8) | uint16(l)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user