mirror of
https://github.com/ariejan/i6502.git
synced 2024-09-25 10:54:29 +00:00
Implement NOP instruction
This commit is contained in:
parent
0fe91268ad
commit
c3ffb2e87b
36
addressing-modes.go
Normal file
36
addressing-modes.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package i6502
|
||||||
|
|
||||||
|
// Addressing modes
|
||||||
|
const (
|
||||||
|
_ = iota
|
||||||
|
absolute
|
||||||
|
absoluteX
|
||||||
|
absoluteY
|
||||||
|
accumulator
|
||||||
|
immediate
|
||||||
|
implied
|
||||||
|
indirect
|
||||||
|
indirectX
|
||||||
|
indirectY
|
||||||
|
relative
|
||||||
|
zeropage
|
||||||
|
zeropageX
|
||||||
|
zoerpageY
|
||||||
|
)
|
||||||
|
|
||||||
|
var addressingNames = [...]string{
|
||||||
|
"",
|
||||||
|
"absolute",
|
||||||
|
"absoluteX",
|
||||||
|
"absoluteY",
|
||||||
|
"accumulator",
|
||||||
|
"immediate",
|
||||||
|
"implied",
|
||||||
|
"(indirect)",
|
||||||
|
"(indirect,X)",
|
||||||
|
"(indirect),Y",
|
||||||
|
"relative",
|
||||||
|
"zeropage",
|
||||||
|
"zeropageX",
|
||||||
|
"zeropageY",
|
||||||
|
}
|
13
cpu.go
13
cpu.go
@ -1,5 +1,7 @@
|
|||||||
package i6502
|
package i6502
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
type Cpu struct {
|
type Cpu struct {
|
||||||
bus *AddressBus // The address bus
|
bus *AddressBus // The address bus
|
||||||
|
|
||||||
@ -35,3 +37,14 @@ func (c *Cpu) LoadProgram(data []byte, location uint16) {
|
|||||||
|
|
||||||
c.PC = location
|
c.PC = location
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute the instruction pointed to by the Program Counter (PC)
|
||||||
|
func (c *Cpu) Step() {
|
||||||
|
instruction := c.readNextInstruction()
|
||||||
|
c.PC += uint16(instruction.Size)
|
||||||
|
fmt.Println(instruction)
|
||||||
|
c.execute(instruction)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cpu) execute(instruction Instruction) {
|
||||||
|
}
|
||||||
|
@ -63,3 +63,10 @@ func TestProgramLoading(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(0x0300, cpu.PC)
|
assert.Equal(0x0300, cpu.PC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNOP(t *testing.T) {
|
||||||
|
cpu, _, _ := NewRamMachine()
|
||||||
|
cpu.LoadProgram([]byte{0xEA}, 0x0300)
|
||||||
|
cpu.Step()
|
||||||
|
assert.Equal(t, 0x0301, cpu.PC)
|
||||||
|
}
|
||||||
|
53
instruction.go
Normal file
53
instruction.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package i6502
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Instruction struct {
|
||||||
|
// Embed OpType
|
||||||
|
OpType
|
||||||
|
|
||||||
|
// 8-bit operand for 2-byte instructions
|
||||||
|
Op8 byte
|
||||||
|
|
||||||
|
// 16-bit operand for 3-byte instructions
|
||||||
|
Op16 uint16
|
||||||
|
|
||||||
|
// Address location where this instruction got read
|
||||||
|
Address uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Instruction) String() (output string) {
|
||||||
|
switch i.Size {
|
||||||
|
case 1:
|
||||||
|
output = fmt.Sprintf("~~ 0x%04X: 0x%02X - %s [%s] {%d}\n", i.Address, i.Opcode, instructionNames[i.opcodeId], addressingNames[i.addressingId], i.Cycles)
|
||||||
|
case 2:
|
||||||
|
output = fmt.Sprintf("~~ 0x%04X: 0x%02X - %s 0x%02X [%s] {%d}\n", i.Address, i.Opcode, instructionNames[i.opcodeId], i.Op8, addressingNames[i.addressingId], i.Cycles)
|
||||||
|
case 3:
|
||||||
|
output = fmt.Sprintf("~~ 0x%04X: 0x%02X - %s 0x%04X [%s] {%d}\n", i.Address, i.Opcode, instructionNames[i.opcodeId], i.Op16, addressingNames[i.addressingId], i.Cycles)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cpu) readNextInstruction() Instruction {
|
||||||
|
// Read the opcode
|
||||||
|
opcode := c.bus.Read(c.PC)
|
||||||
|
|
||||||
|
optype, ok := opTypes[opcode]
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Sprintf("Unknown or unimplemented opcde 0x%02X", opcode))
|
||||||
|
}
|
||||||
|
|
||||||
|
instruction := Instruction{OpType: optype}
|
||||||
|
switch instruction.Size {
|
||||||
|
case 1: // Zero operand instruction
|
||||||
|
case 2: // 8-bit operand
|
||||||
|
instruction.Op8 = c.bus.Read(c.PC + 1)
|
||||||
|
case 3: // 16-bit operand
|
||||||
|
instruction.Op16 = c.bus.Read16(c.PC + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return instruction
|
||||||
|
}
|
146
opcodes.go
Normal file
146
opcodes.go
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package i6502
|
||||||
|
|
||||||
|
// OpCode table
|
||||||
|
const (
|
||||||
|
_ = iota
|
||||||
|
adc
|
||||||
|
and
|
||||||
|
asl
|
||||||
|
bcc
|
||||||
|
bcs
|
||||||
|
beq
|
||||||
|
bit
|
||||||
|
bmi
|
||||||
|
bne
|
||||||
|
bpl
|
||||||
|
brk
|
||||||
|
bvc
|
||||||
|
bvs
|
||||||
|
clc
|
||||||
|
cld
|
||||||
|
cli
|
||||||
|
clv
|
||||||
|
cmp
|
||||||
|
cpx
|
||||||
|
cpy
|
||||||
|
dec
|
||||||
|
dex
|
||||||
|
dey
|
||||||
|
eor
|
||||||
|
inc
|
||||||
|
inx
|
||||||
|
iny
|
||||||
|
jmp
|
||||||
|
jsr
|
||||||
|
lda
|
||||||
|
ldx
|
||||||
|
ldy
|
||||||
|
lsr
|
||||||
|
nop
|
||||||
|
ora
|
||||||
|
pha
|
||||||
|
php
|
||||||
|
pla
|
||||||
|
plp
|
||||||
|
rol
|
||||||
|
ror
|
||||||
|
rti
|
||||||
|
rts
|
||||||
|
sbc
|
||||||
|
sec
|
||||||
|
sed
|
||||||
|
sei
|
||||||
|
sta
|
||||||
|
stx
|
||||||
|
sty
|
||||||
|
tax
|
||||||
|
tay
|
||||||
|
tsx
|
||||||
|
txa
|
||||||
|
txs
|
||||||
|
tya
|
||||||
|
)
|
||||||
|
|
||||||
|
var instructionNames = [...]string{
|
||||||
|
"",
|
||||||
|
"ADC",
|
||||||
|
"AND",
|
||||||
|
"ASL",
|
||||||
|
"BCC",
|
||||||
|
"BCS",
|
||||||
|
"BEQ",
|
||||||
|
"BIT",
|
||||||
|
"BMI",
|
||||||
|
"BNE",
|
||||||
|
"BPL",
|
||||||
|
"BRK",
|
||||||
|
"BVC",
|
||||||
|
"BVS",
|
||||||
|
"CLC",
|
||||||
|
"CLD",
|
||||||
|
"CLI",
|
||||||
|
"CLV",
|
||||||
|
"CMP",
|
||||||
|
"CPX",
|
||||||
|
"CPY",
|
||||||
|
"DEC",
|
||||||
|
"DEX",
|
||||||
|
"DEY",
|
||||||
|
"EOR",
|
||||||
|
"INC",
|
||||||
|
"INX",
|
||||||
|
"INY",
|
||||||
|
"JMP",
|
||||||
|
"JSR",
|
||||||
|
"LDA",
|
||||||
|
"LDX",
|
||||||
|
"LDY",
|
||||||
|
"LSR",
|
||||||
|
"NOP",
|
||||||
|
"ORA",
|
||||||
|
"PHA",
|
||||||
|
"PHP",
|
||||||
|
"PLA",
|
||||||
|
"PLP",
|
||||||
|
"ROL",
|
||||||
|
"ROR",
|
||||||
|
"RTI",
|
||||||
|
"RTS",
|
||||||
|
"SBC",
|
||||||
|
"SEC",
|
||||||
|
"SED",
|
||||||
|
"SEI",
|
||||||
|
"STA",
|
||||||
|
"STX",
|
||||||
|
"STY",
|
||||||
|
"TAX",
|
||||||
|
"TAY",
|
||||||
|
"TSX",
|
||||||
|
"TXA",
|
||||||
|
"TXS",
|
||||||
|
"TYA",
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpType is the operation type, it includes the instruction and
|
||||||
|
// addressing mode. It also includes some extra information for the
|
||||||
|
// emulator, like number of cycles
|
||||||
|
type OpType struct {
|
||||||
|
// The actual Opcode byte read from memory
|
||||||
|
Opcode byte
|
||||||
|
|
||||||
|
// Opcode ID
|
||||||
|
opcodeId uint8
|
||||||
|
|
||||||
|
// Addressing Mode ID
|
||||||
|
addressingId uint8
|
||||||
|
|
||||||
|
// Size of this instruction, either 1, 2 or 3 bytes
|
||||||
|
Size uint8
|
||||||
|
|
||||||
|
// Number of clock cycles this instruction needs
|
||||||
|
Cycles uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
var opTypes = map[uint8]OpType{
|
||||||
|
0xEA: OpType{0xEA, nop, implied, 1, 2},
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user