define instruction set and opcode decoding tables
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
pub const AddressingMode = enum {
|
||||
implied,
|
||||
accumulator,
|
||||
immediate,
|
||||
zero_page,
|
||||
zero_page_x,
|
||||
zero_page_y,
|
||||
relative,
|
||||
absolute,
|
||||
absolute_x,
|
||||
absolute_y,
|
||||
indirect,
|
||||
indexed_indirect_x,
|
||||
indirect_indexed_y,
|
||||
|
||||
// 65C02 additions
|
||||
zero_page_indirect,
|
||||
absolute_indexed_indirect,
|
||||
zero_page_relative,
|
||||
};
|
||||
|
||||
pub const Operation = enum {
|
||||
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,
|
||||
|
||||
// Undocumented NMOS 6502 instructions
|
||||
ahx,
|
||||
alr,
|
||||
anc,
|
||||
arr,
|
||||
axs,
|
||||
dcp,
|
||||
isc,
|
||||
kil,
|
||||
las,
|
||||
lax,
|
||||
rla,
|
||||
rra,
|
||||
sax,
|
||||
shx,
|
||||
shy,
|
||||
slo,
|
||||
sre,
|
||||
tas,
|
||||
xaa,
|
||||
|
||||
// 65C02 CMOS additions
|
||||
bra,
|
||||
phx,
|
||||
phy,
|
||||
plx,
|
||||
ply,
|
||||
stz,
|
||||
trb,
|
||||
tsb,
|
||||
rmb0,
|
||||
rmb1,
|
||||
rmb2,
|
||||
rmb3,
|
||||
rmb4,
|
||||
rmb5,
|
||||
rmb6,
|
||||
rmb7,
|
||||
smb0,
|
||||
smb1,
|
||||
smb2,
|
||||
smb3,
|
||||
smb4,
|
||||
smb5,
|
||||
smb6,
|
||||
smb7,
|
||||
bbr0,
|
||||
bbr1,
|
||||
bbr2,
|
||||
bbr3,
|
||||
bbr4,
|
||||
bbr5,
|
||||
bbr6,
|
||||
bbr7,
|
||||
bbs0,
|
||||
bbs1,
|
||||
bbs2,
|
||||
bbs3,
|
||||
bbs4,
|
||||
bbs5,
|
||||
bbs6,
|
||||
bbs7,
|
||||
stp,
|
||||
wai,
|
||||
};
|
||||
|
||||
// Instruction contains strictly operation and addressing mode; cycles are dynamically accounted for by bus accesses.
|
||||
const Instruction = @This();
|
||||
|
||||
operation: Operation,
|
||||
mode: AddressingMode,
|
||||
@@ -0,0 +1,291 @@
|
||||
const Instruction = @import("../instruction.zig");
|
||||
|
||||
pub const instructions: [256]Instruction = .{
|
||||
// 0x00 - 0x0f
|
||||
.{ .operation = .brk, .mode = .implied },
|
||||
.{ .operation = .ora, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .slo, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .zero_page },
|
||||
.{ .operation = .ora, .mode = .zero_page },
|
||||
.{ .operation = .asl, .mode = .zero_page },
|
||||
.{ .operation = .slo, .mode = .zero_page },
|
||||
.{ .operation = .php, .mode = .implied },
|
||||
.{ .operation = .ora, .mode = .immediate },
|
||||
.{ .operation = .asl, .mode = .accumulator },
|
||||
.{ .operation = .anc, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .absolute },
|
||||
.{ .operation = .ora, .mode = .absolute },
|
||||
.{ .operation = .asl, .mode = .absolute },
|
||||
.{ .operation = .slo, .mode = .absolute },
|
||||
|
||||
// 0x10 - 0x1f
|
||||
.{ .operation = .bpl, .mode = .relative },
|
||||
.{ .operation = .ora, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .slo, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .ora, .mode = .zero_page_x },
|
||||
.{ .operation = .asl, .mode = .zero_page_x },
|
||||
.{ .operation = .slo, .mode = .zero_page_x },
|
||||
.{ .operation = .clc, .mode = .implied },
|
||||
.{ .operation = .ora, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .slo, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .absolute_x },
|
||||
.{ .operation = .ora, .mode = .absolute_x },
|
||||
.{ .operation = .asl, .mode = .absolute_x },
|
||||
.{ .operation = .slo, .mode = .absolute_x },
|
||||
|
||||
// 0x20 - 0x2f
|
||||
.{ .operation = .jsr, .mode = .absolute },
|
||||
.{ .operation = .@"and", .mode = .indexed_indirect_x },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .rla, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .bit, .mode = .zero_page },
|
||||
.{ .operation = .@"and", .mode = .zero_page },
|
||||
.{ .operation = .rol, .mode = .zero_page },
|
||||
.{ .operation = .rla, .mode = .zero_page },
|
||||
.{ .operation = .plp, .mode = .implied },
|
||||
.{ .operation = .@"and", .mode = .immediate },
|
||||
.{ .operation = .rol, .mode = .accumulator },
|
||||
.{ .operation = .anc, .mode = .immediate },
|
||||
.{ .operation = .bit, .mode = .absolute },
|
||||
.{ .operation = .@"and", .mode = .absolute },
|
||||
.{ .operation = .rol, .mode = .absolute },
|
||||
.{ .operation = .rla, .mode = .absolute },
|
||||
|
||||
// 0x30 - 0x3f
|
||||
.{ .operation = .bmi, .mode = .relative },
|
||||
.{ .operation = .@"and", .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .rla, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .@"and", .mode = .zero_page_x },
|
||||
.{ .operation = .rol, .mode = .zero_page_x },
|
||||
.{ .operation = .rla, .mode = .zero_page_x },
|
||||
.{ .operation = .sec, .mode = .implied },
|
||||
.{ .operation = .@"and", .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .rla, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .absolute_x },
|
||||
.{ .operation = .@"and", .mode = .absolute_x },
|
||||
.{ .operation = .rol, .mode = .absolute_x },
|
||||
.{ .operation = .rla, .mode = .absolute_x },
|
||||
|
||||
// 0x40 - 0x4f
|
||||
.{ .operation = .rti, .mode = .implied },
|
||||
.{ .operation = .eor, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .sre, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .zero_page },
|
||||
.{ .operation = .eor, .mode = .zero_page },
|
||||
.{ .operation = .lsr, .mode = .zero_page },
|
||||
.{ .operation = .sre, .mode = .zero_page },
|
||||
.{ .operation = .pha, .mode = .implied },
|
||||
.{ .operation = .eor, .mode = .immediate },
|
||||
.{ .operation = .lsr, .mode = .accumulator },
|
||||
.{ .operation = .alr, .mode = .immediate },
|
||||
.{ .operation = .jmp, .mode = .absolute },
|
||||
.{ .operation = .eor, .mode = .absolute },
|
||||
.{ .operation = .lsr, .mode = .absolute },
|
||||
.{ .operation = .sre, .mode = .absolute },
|
||||
|
||||
// 0x50 - 0x5f
|
||||
.{ .operation = .bvc, .mode = .relative },
|
||||
.{ .operation = .eor, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .sre, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .eor, .mode = .zero_page_x },
|
||||
.{ .operation = .lsr, .mode = .zero_page_x },
|
||||
.{ .operation = .sre, .mode = .zero_page_x },
|
||||
.{ .operation = .cli, .mode = .implied },
|
||||
.{ .operation = .eor, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .sre, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .absolute_x },
|
||||
.{ .operation = .eor, .mode = .absolute_x },
|
||||
.{ .operation = .lsr, .mode = .absolute_x },
|
||||
.{ .operation = .sre, .mode = .absolute_x },
|
||||
|
||||
// 0x60 - 0x6f
|
||||
.{ .operation = .rts, .mode = .implied },
|
||||
.{ .operation = .adc, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .rra, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .zero_page },
|
||||
.{ .operation = .adc, .mode = .zero_page },
|
||||
.{ .operation = .ror, .mode = .zero_page },
|
||||
.{ .operation = .rra, .mode = .zero_page },
|
||||
.{ .operation = .pla, .mode = .implied },
|
||||
.{ .operation = .adc, .mode = .immediate },
|
||||
.{ .operation = .ror, .mode = .accumulator },
|
||||
.{ .operation = .arr, .mode = .immediate },
|
||||
.{ .operation = .jmp, .mode = .indirect },
|
||||
.{ .operation = .adc, .mode = .absolute },
|
||||
.{ .operation = .ror, .mode = .absolute },
|
||||
.{ .operation = .rra, .mode = .absolute },
|
||||
|
||||
// 0x70 - 0x7f
|
||||
.{ .operation = .bvs, .mode = .relative },
|
||||
.{ .operation = .adc, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .rra, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .adc, .mode = .zero_page_x },
|
||||
.{ .operation = .ror, .mode = .zero_page_x },
|
||||
.{ .operation = .rra, .mode = .zero_page_x },
|
||||
.{ .operation = .sei, .mode = .implied },
|
||||
.{ .operation = .adc, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .rra, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .absolute_x },
|
||||
.{ .operation = .adc, .mode = .absolute_x },
|
||||
.{ .operation = .ror, .mode = .absolute_x },
|
||||
.{ .operation = .rra, .mode = .absolute_x },
|
||||
|
||||
// 0x80 - 0x8f
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .sta, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .sax, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .sty, .mode = .zero_page },
|
||||
.{ .operation = .sta, .mode = .zero_page },
|
||||
.{ .operation = .stx, .mode = .zero_page },
|
||||
.{ .operation = .sax, .mode = .zero_page },
|
||||
.{ .operation = .dey, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .txa, .mode = .implied },
|
||||
.{ .operation = .xaa, .mode = .immediate },
|
||||
.{ .operation = .sty, .mode = .absolute },
|
||||
.{ .operation = .sta, .mode = .absolute },
|
||||
.{ .operation = .stx, .mode = .absolute },
|
||||
.{ .operation = .sax, .mode = .absolute },
|
||||
|
||||
// 0x90 - 0x9f
|
||||
.{ .operation = .bcc, .mode = .relative },
|
||||
.{ .operation = .sta, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .ahx, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .sty, .mode = .zero_page_x },
|
||||
.{ .operation = .sta, .mode = .zero_page_x },
|
||||
.{ .operation = .stx, .mode = .zero_page_y },
|
||||
.{ .operation = .sax, .mode = .zero_page_y },
|
||||
.{ .operation = .tya, .mode = .implied },
|
||||
.{ .operation = .sta, .mode = .absolute_y },
|
||||
.{ .operation = .txs, .mode = .implied },
|
||||
.{ .operation = .tas, .mode = .absolute_y },
|
||||
.{ .operation = .shy, .mode = .absolute_x },
|
||||
.{ .operation = .sta, .mode = .absolute_x },
|
||||
.{ .operation = .shx, .mode = .absolute_y },
|
||||
.{ .operation = .ahx, .mode = .absolute_y },
|
||||
|
||||
// 0xa0 - 0xaf
|
||||
.{ .operation = .ldy, .mode = .immediate },
|
||||
.{ .operation = .lda, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .ldx, .mode = .immediate },
|
||||
.{ .operation = .lax, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .ldy, .mode = .zero_page },
|
||||
.{ .operation = .lda, .mode = .zero_page },
|
||||
.{ .operation = .ldx, .mode = .zero_page },
|
||||
.{ .operation = .lax, .mode = .zero_page },
|
||||
.{ .operation = .tay, .mode = .implied },
|
||||
.{ .operation = .lda, .mode = .immediate },
|
||||
.{ .operation = .tax, .mode = .implied },
|
||||
.{ .operation = .lax, .mode = .immediate },
|
||||
.{ .operation = .ldy, .mode = .absolute },
|
||||
.{ .operation = .lda, .mode = .absolute },
|
||||
.{ .operation = .ldx, .mode = .absolute },
|
||||
.{ .operation = .lax, .mode = .absolute },
|
||||
|
||||
// 0xb0 - 0xbf
|
||||
.{ .operation = .bcs, .mode = .relative },
|
||||
.{ .operation = .lda, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .lax, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .ldy, .mode = .zero_page_x },
|
||||
.{ .operation = .lda, .mode = .zero_page_x },
|
||||
.{ .operation = .ldx, .mode = .zero_page_y },
|
||||
.{ .operation = .lax, .mode = .zero_page_y },
|
||||
.{ .operation = .clv, .mode = .implied },
|
||||
.{ .operation = .lda, .mode = .absolute_y },
|
||||
.{ .operation = .tsx, .mode = .implied },
|
||||
.{ .operation = .las, .mode = .absolute_y },
|
||||
.{ .operation = .ldy, .mode = .absolute_x },
|
||||
.{ .operation = .lda, .mode = .absolute_x },
|
||||
.{ .operation = .ldx, .mode = .absolute_y },
|
||||
.{ .operation = .lax, .mode = .absolute_y },
|
||||
|
||||
// 0xc0 - 0xcf
|
||||
.{ .operation = .cpy, .mode = .immediate },
|
||||
.{ .operation = .cmp, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .dcp, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .cpy, .mode = .zero_page },
|
||||
.{ .operation = .cmp, .mode = .zero_page },
|
||||
.{ .operation = .dec, .mode = .zero_page },
|
||||
.{ .operation = .dcp, .mode = .zero_page },
|
||||
.{ .operation = .iny, .mode = .implied },
|
||||
.{ .operation = .cmp, .mode = .immediate },
|
||||
.{ .operation = .dex, .mode = .implied },
|
||||
.{ .operation = .axs, .mode = .immediate },
|
||||
.{ .operation = .cpy, .mode = .absolute },
|
||||
.{ .operation = .cmp, .mode = .absolute },
|
||||
.{ .operation = .dec, .mode = .absolute },
|
||||
.{ .operation = .dcp, .mode = .absolute },
|
||||
|
||||
// 0xd0 - 0xdf
|
||||
.{ .operation = .bne, .mode = .relative },
|
||||
.{ .operation = .cmp, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .dcp, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .cmp, .mode = .zero_page_x },
|
||||
.{ .operation = .dec, .mode = .zero_page_x },
|
||||
.{ .operation = .dcp, .mode = .zero_page_x },
|
||||
.{ .operation = .cld, .mode = .implied },
|
||||
.{ .operation = .cmp, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .dcp, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .absolute_x },
|
||||
.{ .operation = .cmp, .mode = .absolute_x },
|
||||
.{ .operation = .dec, .mode = .absolute_x },
|
||||
.{ .operation = .dcp, .mode = .absolute_x },
|
||||
|
||||
// 0xe0 - 0xef
|
||||
.{ .operation = .cpx, .mode = .immediate },
|
||||
.{ .operation = .sbc, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .isc, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .cpx, .mode = .zero_page },
|
||||
.{ .operation = .sbc, .mode = .zero_page },
|
||||
.{ .operation = .inc, .mode = .zero_page },
|
||||
.{ .operation = .isc, .mode = .zero_page },
|
||||
.{ .operation = .inx, .mode = .implied },
|
||||
.{ .operation = .sbc, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .sbc, .mode = .immediate },
|
||||
.{ .operation = .cpx, .mode = .absolute },
|
||||
.{ .operation = .sbc, .mode = .absolute },
|
||||
.{ .operation = .inc, .mode = .absolute },
|
||||
.{ .operation = .isc, .mode = .absolute },
|
||||
|
||||
// 0xf0 - 0xff
|
||||
.{ .operation = .beq, .mode = .relative },
|
||||
.{ .operation = .sbc, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .kil, .mode = .implied },
|
||||
.{ .operation = .isc, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .sbc, .mode = .zero_page_x },
|
||||
.{ .operation = .inc, .mode = .zero_page_x },
|
||||
.{ .operation = .isc, .mode = .zero_page_x },
|
||||
.{ .operation = .sed, .mode = .implied },
|
||||
.{ .operation = .sbc, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .isc, .mode = .absolute_y },
|
||||
.{ .operation = .nop, .mode = .absolute_x },
|
||||
.{ .operation = .sbc, .mode = .absolute_x },
|
||||
.{ .operation = .inc, .mode = .absolute_x },
|
||||
.{ .operation = .isc, .mode = .absolute_x },
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
pub const nmos6502 = @import("nmos6502.zig");
|
||||
pub const wdc65c02 = @import("wdc65c02.zig");
|
||||
@@ -0,0 +1,291 @@
|
||||
const Instruction = @import("../instruction.zig");
|
||||
|
||||
pub const instructions: [256]Instruction = .{
|
||||
// 0x00 - 0x0f
|
||||
.{ .operation = .brk, .mode = .implied },
|
||||
.{ .operation = .ora, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .tsb, .mode = .zero_page },
|
||||
.{ .operation = .ora, .mode = .zero_page },
|
||||
.{ .operation = .asl, .mode = .zero_page },
|
||||
.{ .operation = .rmb0, .mode = .zero_page },
|
||||
.{ .operation = .php, .mode = .implied },
|
||||
.{ .operation = .ora, .mode = .immediate },
|
||||
.{ .operation = .asl, .mode = .accumulator },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .tsb, .mode = .absolute },
|
||||
.{ .operation = .ora, .mode = .absolute },
|
||||
.{ .operation = .asl, .mode = .absolute },
|
||||
.{ .operation = .bbr0, .mode = .zero_page_relative },
|
||||
|
||||
// 0x10 - 0x1f
|
||||
.{ .operation = .bpl, .mode = .relative },
|
||||
.{ .operation = .ora, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .ora, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .trb, .mode = .zero_page },
|
||||
.{ .operation = .ora, .mode = .zero_page_x },
|
||||
.{ .operation = .asl, .mode = .zero_page_x },
|
||||
.{ .operation = .rmb1, .mode = .zero_page },
|
||||
.{ .operation = .clc, .mode = .implied },
|
||||
.{ .operation = .ora, .mode = .absolute_y },
|
||||
.{ .operation = .inc, .mode = .accumulator },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .trb, .mode = .absolute },
|
||||
.{ .operation = .ora, .mode = .absolute_x },
|
||||
.{ .operation = .asl, .mode = .absolute_x },
|
||||
.{ .operation = .bbr1, .mode = .zero_page_relative },
|
||||
|
||||
// 0x20 - 0x2f
|
||||
.{ .operation = .jsr, .mode = .absolute },
|
||||
.{ .operation = .@"and", .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .bit, .mode = .zero_page },
|
||||
.{ .operation = .@"and", .mode = .zero_page },
|
||||
.{ .operation = .rol, .mode = .zero_page },
|
||||
.{ .operation = .rmb2, .mode = .zero_page },
|
||||
.{ .operation = .plp, .mode = .implied },
|
||||
.{ .operation = .@"and", .mode = .immediate },
|
||||
.{ .operation = .rol, .mode = .accumulator },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .bit, .mode = .absolute },
|
||||
.{ .operation = .@"and", .mode = .absolute },
|
||||
.{ .operation = .rol, .mode = .absolute },
|
||||
.{ .operation = .bbr2, .mode = .zero_page_relative },
|
||||
|
||||
// 0x30 - 0x3f
|
||||
.{ .operation = .bmi, .mode = .relative },
|
||||
.{ .operation = .@"and", .mode = .indirect_indexed_y },
|
||||
.{ .operation = .@"and", .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .bit, .mode = .zero_page_x },
|
||||
.{ .operation = .@"and", .mode = .zero_page_x },
|
||||
.{ .operation = .rol, .mode = .zero_page_x },
|
||||
.{ .operation = .rmb3, .mode = .zero_page },
|
||||
.{ .operation = .sec, .mode = .implied },
|
||||
.{ .operation = .@"and", .mode = .absolute_y },
|
||||
.{ .operation = .dec, .mode = .accumulator },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .bit, .mode = .absolute_x },
|
||||
.{ .operation = .@"and", .mode = .absolute_x },
|
||||
.{ .operation = .rol, .mode = .absolute_x },
|
||||
.{ .operation = .bbr3, .mode = .zero_page_relative },
|
||||
|
||||
// 0x40 - 0x4f
|
||||
.{ .operation = .rti, .mode = .implied },
|
||||
.{ .operation = .eor, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .zero_page },
|
||||
.{ .operation = .eor, .mode = .zero_page },
|
||||
.{ .operation = .lsr, .mode = .zero_page },
|
||||
.{ .operation = .rmb4, .mode = .zero_page },
|
||||
.{ .operation = .pha, .mode = .implied },
|
||||
.{ .operation = .eor, .mode = .immediate },
|
||||
.{ .operation = .lsr, .mode = .accumulator },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .jmp, .mode = .absolute },
|
||||
.{ .operation = .eor, .mode = .absolute },
|
||||
.{ .operation = .lsr, .mode = .absolute },
|
||||
.{ .operation = .bbr4, .mode = .zero_page_relative },
|
||||
|
||||
// 0x50 - 0x5f
|
||||
.{ .operation = .bvc, .mode = .relative },
|
||||
.{ .operation = .eor, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .eor, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .eor, .mode = .zero_page_x },
|
||||
.{ .operation = .lsr, .mode = .zero_page_x },
|
||||
.{ .operation = .rmb5, .mode = .zero_page },
|
||||
.{ .operation = .cli, .mode = .implied },
|
||||
.{ .operation = .eor, .mode = .absolute_y },
|
||||
.{ .operation = .phy, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .absolute },
|
||||
.{ .operation = .eor, .mode = .absolute_x },
|
||||
.{ .operation = .lsr, .mode = .absolute_x },
|
||||
.{ .operation = .bbr5, .mode = .zero_page_relative },
|
||||
|
||||
// 0x60 - 0x6f
|
||||
.{ .operation = .rts, .mode = .implied },
|
||||
.{ .operation = .adc, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .stz, .mode = .zero_page },
|
||||
.{ .operation = .adc, .mode = .zero_page },
|
||||
.{ .operation = .ror, .mode = .zero_page },
|
||||
.{ .operation = .rmb6, .mode = .zero_page },
|
||||
.{ .operation = .pla, .mode = .implied },
|
||||
.{ .operation = .adc, .mode = .immediate },
|
||||
.{ .operation = .ror, .mode = .accumulator },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .jmp, .mode = .indirect },
|
||||
.{ .operation = .adc, .mode = .absolute },
|
||||
.{ .operation = .ror, .mode = .absolute },
|
||||
.{ .operation = .bbr6, .mode = .zero_page_relative },
|
||||
|
||||
// 0x70 - 0x7f
|
||||
.{ .operation = .bvs, .mode = .relative },
|
||||
.{ .operation = .adc, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .adc, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .stz, .mode = .zero_page_x },
|
||||
.{ .operation = .adc, .mode = .zero_page_x },
|
||||
.{ .operation = .ror, .mode = .zero_page_x },
|
||||
.{ .operation = .rmb7, .mode = .zero_page },
|
||||
.{ .operation = .sei, .mode = .implied },
|
||||
.{ .operation = .adc, .mode = .absolute_y },
|
||||
.{ .operation = .ply, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .jmp, .mode = .absolute_indexed_indirect },
|
||||
.{ .operation = .adc, .mode = .absolute_x },
|
||||
.{ .operation = .ror, .mode = .absolute_x },
|
||||
.{ .operation = .bbr7, .mode = .zero_page_relative },
|
||||
|
||||
// 0x80 - 0x8f
|
||||
.{ .operation = .bra, .mode = .relative },
|
||||
.{ .operation = .sta, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .sty, .mode = .zero_page },
|
||||
.{ .operation = .sta, .mode = .zero_page },
|
||||
.{ .operation = .stx, .mode = .zero_page },
|
||||
.{ .operation = .smb0, .mode = .zero_page },
|
||||
.{ .operation = .dey, .mode = .implied },
|
||||
.{ .operation = .bit, .mode = .immediate },
|
||||
.{ .operation = .txa, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .sty, .mode = .absolute },
|
||||
.{ .operation = .sta, .mode = .absolute },
|
||||
.{ .operation = .stx, .mode = .absolute },
|
||||
.{ .operation = .bbs0, .mode = .zero_page_relative },
|
||||
|
||||
// 0x90 - 0x9f
|
||||
.{ .operation = .bcc, .mode = .relative },
|
||||
.{ .operation = .sta, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .sta, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .sty, .mode = .zero_page_x },
|
||||
.{ .operation = .sta, .mode = .zero_page_x },
|
||||
.{ .operation = .stx, .mode = .zero_page_y },
|
||||
.{ .operation = .smb1, .mode = .zero_page },
|
||||
.{ .operation = .tya, .mode = .implied },
|
||||
.{ .operation = .sta, .mode = .absolute_y },
|
||||
.{ .operation = .txs, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .stz, .mode = .absolute },
|
||||
.{ .operation = .sta, .mode = .absolute_x },
|
||||
.{ .operation = .stz, .mode = .absolute_x },
|
||||
.{ .operation = .bbs1, .mode = .zero_page_relative },
|
||||
|
||||
// 0xa0 - 0xaf
|
||||
.{ .operation = .ldy, .mode = .immediate },
|
||||
.{ .operation = .lda, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .ldx, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .ldy, .mode = .zero_page },
|
||||
.{ .operation = .lda, .mode = .zero_page },
|
||||
.{ .operation = .ldx, .mode = .zero_page },
|
||||
.{ .operation = .smb2, .mode = .zero_page },
|
||||
.{ .operation = .tay, .mode = .implied },
|
||||
.{ .operation = .lda, .mode = .immediate },
|
||||
.{ .operation = .tax, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .ldy, .mode = .absolute },
|
||||
.{ .operation = .lda, .mode = .absolute },
|
||||
.{ .operation = .ldx, .mode = .absolute },
|
||||
.{ .operation = .bbs2, .mode = .zero_page_relative },
|
||||
|
||||
// 0xb0 - 0xbf
|
||||
.{ .operation = .bcs, .mode = .relative },
|
||||
.{ .operation = .lda, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .lda, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .ldy, .mode = .zero_page_x },
|
||||
.{ .operation = .lda, .mode = .zero_page_x },
|
||||
.{ .operation = .ldx, .mode = .zero_page_y },
|
||||
.{ .operation = .smb3, .mode = .zero_page },
|
||||
.{ .operation = .clv, .mode = .implied },
|
||||
.{ .operation = .lda, .mode = .absolute_y },
|
||||
.{ .operation = .tsx, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .ldy, .mode = .absolute_x },
|
||||
.{ .operation = .lda, .mode = .absolute_x },
|
||||
.{ .operation = .ldx, .mode = .absolute_y },
|
||||
.{ .operation = .bbs3, .mode = .zero_page_relative },
|
||||
|
||||
// 0xc0 - 0xcf
|
||||
.{ .operation = .cpy, .mode = .immediate },
|
||||
.{ .operation = .cmp, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .cpy, .mode = .zero_page },
|
||||
.{ .operation = .cmp, .mode = .zero_page },
|
||||
.{ .operation = .dec, .mode = .zero_page },
|
||||
.{ .operation = .smb4, .mode = .zero_page },
|
||||
.{ .operation = .iny, .mode = .implied },
|
||||
.{ .operation = .cmp, .mode = .immediate },
|
||||
.{ .operation = .dex, .mode = .implied },
|
||||
.{ .operation = .wai, .mode = .implied },
|
||||
.{ .operation = .cpy, .mode = .absolute },
|
||||
.{ .operation = .cmp, .mode = .absolute },
|
||||
.{ .operation = .dec, .mode = .absolute },
|
||||
.{ .operation = .bbs4, .mode = .zero_page_relative },
|
||||
|
||||
// 0xd0 - 0xdf
|
||||
.{ .operation = .bne, .mode = .relative },
|
||||
.{ .operation = .cmp, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .cmp, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .cmp, .mode = .zero_page_x },
|
||||
.{ .operation = .dec, .mode = .zero_page_x },
|
||||
.{ .operation = .smb5, .mode = .zero_page },
|
||||
.{ .operation = .cld, .mode = .implied },
|
||||
.{ .operation = .cmp, .mode = .absolute_y },
|
||||
.{ .operation = .phx, .mode = .implied },
|
||||
.{ .operation = .stp, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .absolute },
|
||||
.{ .operation = .cmp, .mode = .absolute_x },
|
||||
.{ .operation = .dec, .mode = .absolute_x },
|
||||
.{ .operation = .bbs5, .mode = .zero_page_relative },
|
||||
|
||||
// 0xe0 - 0xef
|
||||
.{ .operation = .cpx, .mode = .immediate },
|
||||
.{ .operation = .sbc, .mode = .indexed_indirect_x },
|
||||
.{ .operation = .nop, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .cpx, .mode = .zero_page },
|
||||
.{ .operation = .sbc, .mode = .zero_page },
|
||||
.{ .operation = .inc, .mode = .zero_page },
|
||||
.{ .operation = .smb6, .mode = .zero_page },
|
||||
.{ .operation = .inx, .mode = .implied },
|
||||
.{ .operation = .sbc, .mode = .immediate },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .cpx, .mode = .absolute },
|
||||
.{ .operation = .sbc, .mode = .absolute },
|
||||
.{ .operation = .inc, .mode = .absolute },
|
||||
.{ .operation = .bbs6, .mode = .zero_page_relative },
|
||||
|
||||
// 0xf0 - 0xff
|
||||
.{ .operation = .beq, .mode = .relative },
|
||||
.{ .operation = .sbc, .mode = .indirect_indexed_y },
|
||||
.{ .operation = .sbc, .mode = .zero_page_indirect },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .zero_page_x },
|
||||
.{ .operation = .sbc, .mode = .zero_page_x },
|
||||
.{ .operation = .inc, .mode = .zero_page_x },
|
||||
.{ .operation = .smb7, .mode = .zero_page },
|
||||
.{ .operation = .sed, .mode = .implied },
|
||||
.{ .operation = .sbc, .mode = .absolute_y },
|
||||
.{ .operation = .plx, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .implied },
|
||||
.{ .operation = .nop, .mode = .absolute },
|
||||
.{ .operation = .sbc, .mode = .absolute_x },
|
||||
.{ .operation = .inc, .mode = .absolute_x },
|
||||
.{ .operation = .bbs7, .mode = .zero_page_relative },
|
||||
};
|
||||
+53
-7
@@ -1,3 +1,6 @@
|
||||
const _opcode = @import("opcode/root.zig");
|
||||
const Instruction = @import("instruction.zig");
|
||||
|
||||
pub const Status = packed struct(u8) {
|
||||
carry: bool = false,
|
||||
zero: bool = false,
|
||||
@@ -30,13 +33,6 @@ pub const Registers = struct {
|
||||
sp: u8 = 0xfd,
|
||||
pc: u16 = 0,
|
||||
status: Status = .{},
|
||||
|
||||
pub fn dumpRegisters(self: Registers) void {
|
||||
const std = @import("std");
|
||||
std.debug.print("A:{X:02} X:{X:02} Y:{X:02} SP:{X:02} PC:{X:04}\n", .{
|
||||
self.a, self.x, self.y, self.sp, self.pc,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
pub const Model = enum {
|
||||
@@ -49,22 +45,26 @@ pub const Model = enum {
|
||||
r65c02,
|
||||
|
||||
pub fn features(self: Model) CpuFeatures {
|
||||
// group variants sharing exact feature sets to eliminate duplication
|
||||
return switch (self) {
|
||||
.mos6502, .mos6507, .mos6510 => .{
|
||||
.decimal_arithmetic = true,
|
||||
.undocumented_opcodes = true,
|
||||
.indirect_jump_bug = true,
|
||||
},
|
||||
|
||||
.ricoh2a03, .ricoh2a07 => .{
|
||||
.undocumented_opcodes = true,
|
||||
.indirect_jump_bug = true,
|
||||
},
|
||||
|
||||
.wdc65c02 => .{
|
||||
.decimal_arithmetic = true,
|
||||
.cmos_instructions = true,
|
||||
.fixed_indirect_jump = true,
|
||||
.wait_and_stop = true,
|
||||
},
|
||||
|
||||
.r65c02 => .{
|
||||
.decimal_arithmetic = true,
|
||||
.cmos_instructions = true,
|
||||
@@ -72,6 +72,24 @@ pub const Model = enum {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn instructionTable(self: Model) *const [256]Instruction {
|
||||
return switch (self) {
|
||||
.mos6502, .mos6507, .mos6510, .ricoh2a03, .ricoh2a07 => &_opcode.nmos6502.instructions,
|
||||
.wdc65c02, .r65c02 => &_opcode.wdc65c02.instructions,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn instruction(self: Model, opcode: u8) Instruction {
|
||||
return self.instructionTable()[opcode];
|
||||
}
|
||||
|
||||
pub fn addressMask(self: Model) u16 {
|
||||
return switch (self) {
|
||||
.mos6507 => 0x1fff,
|
||||
else => 0xffff,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const CpuFeatures = packed struct(u8) {
|
||||
@@ -82,5 +100,33 @@ pub const CpuFeatures = packed struct(u8) {
|
||||
fixed_indirect_jump: bool = false,
|
||||
wait_and_stop: bool = false,
|
||||
|
||||
// remaining bit fields reserved for packed struct byte layout
|
||||
_reserved: u2 = 0,
|
||||
};
|
||||
|
||||
test "CPU Model Features & Opcode Map Verification" {
|
||||
const testing = @import("std").testing;
|
||||
|
||||
// MOS 6502 family
|
||||
try testing.expect(Model.mos6502.features().decimal_arithmetic);
|
||||
try testing.expect(Model.mos6507.features().decimal_arithmetic);
|
||||
try testing.expect(Model.mos6510.features().decimal_arithmetic);
|
||||
try testing.expect(Model.mos6502.features().undocumented_opcodes);
|
||||
|
||||
// Ricoh family (No BCD)
|
||||
try testing.expect(!Model.ricoh2a03.features().decimal_arithmetic);
|
||||
try testing.expect(!Model.ricoh2a07.features().decimal_arithmetic);
|
||||
try testing.expect(Model.ricoh2a07.features().undocumented_opcodes);
|
||||
try testing.expect(Model.ricoh2a07.features().indirect_jump_bug);
|
||||
|
||||
// CMOS family
|
||||
try testing.expect(Model.wdc65c02.features().cmos_instructions);
|
||||
try testing.expect(Model.r65c02.features().cmos_instructions);
|
||||
try testing.expect(Model.wdc65c02.features().wait_and_stop);
|
||||
try testing.expect(!Model.r65c02.features().wait_and_stop);
|
||||
|
||||
// Opcode mapping sanity checks
|
||||
try testing.expectEqual(Model.mos6502.instruction(0xEA).operation, .nop);
|
||||
try testing.expectEqual(Model.ricoh2a07.instruction(0xEA).operation, .nop);
|
||||
try testing.expectEqual(Model.r65c02.instruction(0x80).operation, .bra);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user