mirror of
https://github.com/ariejan/i6502.git
synced 2025-04-08 21:43:30 +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
|
||||
|
||||
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) {
|
||||
}
|
||||
|
@ -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
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…
x
Reference in New Issue
Block a user