Skip to content

Commit 7b0a28c

Browse files
committed
cpu: add basic support for some 65C02 opcodes
This is very much a RFC rather than something which is finished and proposed for merging. I've got my own 6502 homebrew project at https://github.com/rjw57/buri and I make use of the 65C02 instructions such as PHX, PHY, etc. This commit adds just enough support to boot the 65C02 ROM image I have. This is a work-in-progress change and is not complete 65C02 support by any means. My question is: is this worth pursuing further? Would you be interested in 65C02 support? If so, would you want some form of configuration allowing 65C02-support to be switched on/off?
1 parent 8cbd0f5 commit 7b0a28c

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

cpu/cpu.go

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,15 @@ func (c *Cpu) memoryAddress(in Instruction) uint16 {
156156
return uint16(in.Op8 + c.X)
157157
case zeropageY:
158158
return uint16(in.Op8 + c.Y)
159+
160+
// 65C02-only modes
161+
case zpindirect:
162+
return c.Bus.Read16(uint16(in.Op8))
163+
case indirect:
164+
return c.Bus.Read16(uint16(in.Op16))
165+
159166
default:
160-
panic("unhandled addressing")
167+
panic(fmt.Sprintf("unhandled addressing: %v", in.addressing))
161168
}
162169
}
163170

@@ -304,6 +311,18 @@ func (c *Cpu) execute(in Instruction) {
304311
c.TXS(in)
305312
case tya:
306313
c.TYA(in)
314+
case phx:
315+
c.PHX(in)
316+
case phy:
317+
c.PHY(in)
318+
case plx:
319+
c.PLX(in)
320+
case ply:
321+
c.PLY(in)
322+
case stz:
323+
c.STZ(in)
324+
case bra:
325+
c.BRA(in)
307326
case _end:
308327
c._END(in)
309328
default:
@@ -392,6 +411,11 @@ func (c *Cpu) BPL(in Instruction) {
392411
}
393412
}
394413

414+
// BRA: Unconditional branch
415+
func (c *Cpu) BRA(in Instruction) {
416+
c.branch(in)
417+
}
418+
395419
// BRK: software interrupt
396420
func (c *Cpu) BRK(in Instruction) {
397421
// temporarily used to dump status
@@ -550,6 +574,30 @@ func (c *Cpu) PLA(in Instruction) {
550574
c.AC = c.Bus.Read(0x0100 + uint16(c.SP))
551575
}
552576

577+
// PHX: Push X onto stack.
578+
func (c *Cpu) PHX(in Instruction) {
579+
c.Bus.Write(0x0100+uint16(c.SP), c.X)
580+
c.SP--
581+
}
582+
583+
// PLX: Pull X from stack.
584+
func (c *Cpu) PLX(in Instruction) {
585+
c.SP++
586+
c.X = c.Bus.Read(0x0100 + uint16(c.SP))
587+
}
588+
589+
// PHY: Push Y onto stack.
590+
func (c *Cpu) PHY(in Instruction) {
591+
c.Bus.Write(0x0100+uint16(c.SP), c.Y)
592+
c.SP--
593+
}
594+
595+
// PLY: Pull Y from stack.
596+
func (c *Cpu) PLY(in Instruction) {
597+
c.SP++
598+
c.Y = c.Bus.Read(0x0100 + uint16(c.SP))
599+
}
600+
553601
// ROL: Rotate memory or accumulator left one bit.
554602
func (c *Cpu) ROL(in Instruction) {
555603
carry := c.getStatusInt(sCarry)
@@ -637,6 +685,11 @@ func (c *Cpu) STY(in Instruction) {
637685
c.Bus.Write(c.memoryAddress(in), c.Y)
638686
}
639687

688+
// STZ: Store zero to memory.
689+
func (c *Cpu) STZ(in Instruction) {
690+
c.Bus.Write(c.memoryAddress(in), 0)
691+
}
692+
640693
// TAX: Transfer accumulator to index register X.
641694
func (c *Cpu) TAX(in Instruction) {
642695
c.X = c.AC

cpu/op_type.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ const (
1818
zeropage
1919
zeropageX
2020
zeropageY
21+
22+
// 65C02 only
23+
zpindirect
2124
)
2225

2326
var addressingNames = [...]string{
@@ -35,6 +38,7 @@ var addressingNames = [...]string{
3538
"zeropage",
3639
"zeropageX",
3740
"zeropageY",
41+
"(zeropage)",
3842
}
3943

4044
// adc..tya represent the 6502 instruction set mnemonics. Each mnemonic maps to
@@ -97,6 +101,17 @@ const (
97101
txa
98102
txs
99103
tya
104+
105+
// 65{S}C02-only
106+
bra
107+
phx
108+
phy
109+
plx
110+
ply
111+
stz
112+
trb
113+
tsb
114+
100115
_end
101116
)
102117

@@ -158,6 +173,17 @@ var instructionNames = [...]string{
158173
"TXA",
159174
"TXS",
160175
"TYA",
176+
177+
// 65{S}C02-only
178+
"BRA",
179+
"PHX",
180+
"PHY",
181+
"PLX",
182+
"PLY",
183+
"STZ",
184+
"TRB",
185+
"TSB",
186+
161187
"_END",
162188
}
163189

@@ -351,5 +377,29 @@ var optypes = map[uint8]OpType{
351377
0x8A: OpType{0x8A, txa, implied, 1, 2},
352378
0x9A: OpType{0x9A, txs, implied, 1, 2},
353379
0x98: OpType{0x98, tya, implied, 1, 2},
380+
381+
// 65{S}C02 only
382+
0x80: OpType{0x80, bra, relative, 2, 3},
383+
0xDA: OpType{0xDA, phx, implied, 1, 3},
384+
0x5A: OpType{0x5A, phy, implied, 1, 3},
385+
0xFA: OpType{0xFA, plx, implied, 1, 4},
386+
0x7A: OpType{0x7A, ply, implied, 1, 4},
387+
0x64: OpType{0x64, stz, zeropage, 2, 3},
388+
0x74: OpType{0x74, stz, zeropageX, 2, 4},
389+
0x9C: OpType{0x9C, stz, absolute, 3, 4},
390+
0x9E: OpType{0x9E, stz, absoluteX, 3, 5},
391+
0x14: OpType{0x14, trb, zeropage, 2, 5},
392+
0x1C: OpType{0x1C, trb, absolute, 3, 6},
393+
0x04: OpType{0x04, tsb, zeropage, 2, 5},
394+
0x0C: OpType{0x0C, tsb, absolute, 3, 5},
395+
0x12: OpType{0x12, ora, zpindirect, 2, 5},
396+
0x32: OpType{0x32, and, zpindirect, 2, 5},
397+
0x52: OpType{0x52, eor, zpindirect, 2, 5},
398+
0x72: OpType{0x72, adc, zpindirect, 2, 5},
399+
0x92: OpType{0x92, sta, zpindirect, 2, 5},
400+
0xB2: OpType{0xB2, lda, zpindirect, 2, 5},
401+
0xD2: OpType{0xD2, cmp, zpindirect, 2, 5},
402+
0xF2: OpType{0xF2, sbc, zpindirect, 2, 5},
403+
354404
0xFF: OpType{0xFF, _end, implied, 1, 1},
355405
}

0 commit comments

Comments
 (0)