Implement NOP instruction

This commit is contained in:
Ariejan de Vroom 2014-08-13 13:51:53 +02:00
parent 0fe91268ad
commit c3ffb2e87b
5 changed files with 255 additions and 0 deletions

36
addressing-modes.go Normal file
View 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
View File

@ -1,5 +1,7 @@
package i6502
import "fmt"
type Cpu struct {
bus *AddressBus // The address bus
@ -35,3 +37,14 @@ func (c *Cpu) LoadProgram(data []byte, location uint16) {
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) {
}

View File

@ -63,3 +63,10 @@ func TestProgramLoading(t *testing.T) {
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
View 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
View 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},
}