from enum import IntEnum class AddrMode(IntEnum): Imp = 1, Acc = 2, Imm = 3, Zp = 4, ZpX = 5, ZpY = 6, Rel = 7, Abs = 8, AbsX = 9, AbsY = 10, Ind = 11, IzX = 12, IzY = 13, Zpr = 14, Izp = 15, IaX = 16 Instructions = ( (0x00, "brk", AddrMode.Imp), (0x01, "ora", AddrMode.IzX), (0x02, "nop", AddrMode.Imm), (0x03, "nop", AddrMode.Imp), (0x04, "tsb", AddrMode.Zp), (0x05, "ora", AddrMode.Zp), (0x06, "asl", AddrMode.Zp), (0x07, "rmb0", AddrMode.Zp), (0x08, "php", AddrMode.Imp), (0x09, "ora", AddrMode.Imm), (0x0a, "asl", AddrMode.Acc), (0x0b, "nop", AddrMode.Imp), (0x0c, "tsb", AddrMode.Abs), (0x0d, "ora", AddrMode.Abs), (0x0e, "asl", AddrMode.Abs), (0x0f, "bbr0", AddrMode.Zpr), (0x10, "bpl", AddrMode.Rel), (0x11, "ora", AddrMode.IzY), (0x12, "ora", AddrMode.Izp), (0x13, "nop", AddrMode.Imp), (0x14, "trb", AddrMode.Zp), (0x15, "ora", AddrMode.ZpX), (0x16, "asl", AddrMode.ZpX), (0x17, "rmb1", AddrMode.Zp), (0x18, "clc", AddrMode.Imp), (0x19, "ora", AddrMode.AbsY), (0x1a, "inc", AddrMode.Acc), (0x1b, "nop", AddrMode.Imp), (0x1c, "trb", AddrMode.Abs), (0x1d, "ora", AddrMode.AbsX), (0x1e, "asl", AddrMode.AbsX), (0x1f, "bbr1", AddrMode.Zpr), (0x20, "jsr", AddrMode.Abs), (0x21, "and", AddrMode.IzX), (0x22, "nop", AddrMode.Imm), (0x23, "nop", AddrMode.Imp), (0x24, "bit", AddrMode.Zp), (0x25, "and", AddrMode.Zp), (0x26, "rol", AddrMode.Zp), (0x27, "rmb2", AddrMode.Zp), (0x28, "plp", AddrMode.Imp), (0x29, "and", AddrMode.Imm), (0x2a, "rol", AddrMode.Acc), (0x2b, "nop", AddrMode.Imp), (0x2c, "bit", AddrMode.Abs), (0x2d, "and", AddrMode.Abs), (0x2e, "rol", AddrMode.Abs), (0x2f, "bbr2", AddrMode.Zpr), (0x30, "bmi", AddrMode.Rel), (0x31, "and", AddrMode.IzY), (0x32, "and", AddrMode.Izp), (0x33, "nop", AddrMode.Imp), (0x34, "bit", AddrMode.ZpX), (0x35, "and", AddrMode.ZpX), (0x36, "rol", AddrMode.ZpX), (0x37, "rmb3", AddrMode.Zp), (0x38, "sec", AddrMode.Imp), (0x39, "and", AddrMode.AbsY), (0x3a, "dec", AddrMode.Acc), (0x3b, "nop", AddrMode.Imp), (0x3c, "bit", AddrMode.AbsX), (0x3d, "and", AddrMode.AbsX), (0x3e, "rol", AddrMode.AbsX), (0x3f, "bbr3", AddrMode.Zpr), (0x40, "rti", AddrMode.Imp), (0x41, "eor", AddrMode.IzX), (0x42, "nop", AddrMode.Imm), (0x43, "nop", AddrMode.Imp), (0x44, "nop", AddrMode.Zp), (0x45, "eor", AddrMode.Zp), (0x46, "lsr", AddrMode.Zp), (0x47, "rmb4", AddrMode.Zp), (0x48, "pha", AddrMode.Imp), (0x49, "eor", AddrMode.Imm), (0x4a, "lsr", AddrMode.Acc), (0x4b, "nop", AddrMode.Imp), (0x4c, "jmp", AddrMode.Abs), (0x4d, "eor", AddrMode.Abs), (0x4e, "lsr", AddrMode.Abs), (0x4f, "bbr4", AddrMode.Zpr), (0x50, "bvc", AddrMode.Rel), (0x51, "eor", AddrMode.IzY), (0x52, "eor", AddrMode.Izp), (0x53, "nop", AddrMode.Imp), (0x54, "nop", AddrMode.ZpX), (0x55, "eor", AddrMode.ZpX), (0x56, "lsr", AddrMode.ZpX), (0x57, "rmb5", AddrMode.Zp), (0x58, "cli", AddrMode.Imp), (0x59, "eor", AddrMode.AbsY), (0x5a, "phy", AddrMode.Imp), (0x5b, "nop", AddrMode.Imp), (0x5c, "nop", AddrMode.Abs), (0x5d, "eor", AddrMode.AbsX), (0x5e, "lsr", AddrMode.AbsX), (0x5f, "bbr5", AddrMode.Zpr), (0x60, "rts", AddrMode.Imp), (0x61, "adc", AddrMode.IzX), (0x62, "nop", AddrMode.Imm), (0x63, "nop", AddrMode.Imp), (0x64, "stz", AddrMode.Zp), (0x65, "adc", AddrMode.Zp), (0x66, "ror", AddrMode.Zp), (0x67, "rmb6", AddrMode.Zp), (0x68, "pla", AddrMode.Imp), (0x69, "adc", AddrMode.Imm), (0x6a, "ror", AddrMode.Acc), (0x6b, "nop", AddrMode.Imp), (0x6c, "jmp", AddrMode.Ind), (0x6d, "adc", AddrMode.Abs), (0x6e, "ror", AddrMode.Abs), (0x6f, "bbr6", AddrMode.Zpr), (0x70, "bvs", AddrMode.Rel), (0x71, "adc", AddrMode.IzY), (0x72, "adc", AddrMode.Izp), (0x73, "nop", AddrMode.Imp), (0x74, "stz", AddrMode.ZpX), (0x75, "adc", AddrMode.ZpX), (0x76, "ror", AddrMode.ZpX), (0x77, "rmb7", AddrMode.Zp), (0x78, "sei", AddrMode.Imp), (0x79, "adc", AddrMode.AbsY), (0x7a, "ply", AddrMode.Imp), (0x7b, "nop", AddrMode.Imp), (0x7c, "jmp", AddrMode.IaX), (0x7d, "adc", AddrMode.AbsX), (0x7e, "ror", AddrMode.AbsX), (0x7f, "bbr7", AddrMode.Zpr), (0x80, "bra", AddrMode.Rel), (0x81, "sta", AddrMode.IzX), (0x82, "nop", AddrMode.Imm), (0x83, "nop", AddrMode.Imp), (0x84, "sty", AddrMode.Zp), (0x85, "sta", AddrMode.Zp), (0x86, "stx", AddrMode.Zp), (0x87, "smb0", AddrMode.Zp), (0x88, "dey", AddrMode.Imp), (0x89, "bit", AddrMode.Imm), (0x8a, "txa", AddrMode.Imp), (0x8b, "nop", AddrMode.Imp), (0x8c, "sty", AddrMode.Abs), (0x8d, "sta", AddrMode.Abs), (0x8e, "stx", AddrMode.Abs), (0x8f, "bbs0", AddrMode.Zpr), (0x90, "bcc", AddrMode.Rel), (0x91, "sta", AddrMode.IzY), (0x92, "sta", AddrMode.Izp), (0x93, "nop", AddrMode.Imp), (0x94, "sty", AddrMode.ZpX), (0x95, "sta", AddrMode.ZpX), (0x96, "stx", AddrMode.ZpY), (0x97, "smb1", AddrMode.Zp), (0x98, "tya", AddrMode.Imp), (0x99, "sta", AddrMode.AbsY), (0x9a, "txs", AddrMode.Imp), (0x9b, "nop", AddrMode.Imp), (0x9c, "stz", AddrMode.Abs), (0x9d, "sta", AddrMode.AbsX), (0x9e, "stz", AddrMode.AbsX), (0x9f, "bbs1", AddrMode.Zpr), (0xa0, "ldy", AddrMode.Imm), (0xa1, "lda", AddrMode.IzX), (0xa2, "ldx", AddrMode.Imm), (0xa3, "nop", AddrMode.Imp), (0xa4, "ldy", AddrMode.Zp), (0xa5, "lda", AddrMode.Zp), (0xa6, "ldx", AddrMode.Zp), (0xa7, "smb2", AddrMode.Zp), (0xa8, "tay", AddrMode.Imp), (0xa9, "lda", AddrMode.Imm), (0xaa, "tax", AddrMode.Imp), (0xab, "nop", AddrMode.Imp), (0xac, "ldy", AddrMode.Abs), (0xad, "lda", AddrMode.Abs), (0xae, "ldx", AddrMode.Abs), (0xaf, "bbs2", AddrMode.Zpr), (0xb0, "bcs", AddrMode.Rel), (0xb1, "lda", AddrMode.IzY), (0xb2, "lda", AddrMode.Izp), (0xb3, "nop", AddrMode.Imp), (0xb4, "ldy", AddrMode.ZpX), (0xb5, "lda", AddrMode.ZpX), (0xb6, "ldx", AddrMode.ZpY), (0xb7, "smb3", AddrMode.Zp), (0xb8, "clv", AddrMode.Imp), (0xb9, "lda", AddrMode.AbsY), (0xba, "tsx", AddrMode.Imp), (0xbb, "nop", AddrMode.Imp), (0xbc, "ldy", AddrMode.AbsX), (0xbd, "lda", AddrMode.AbsX), (0xbe, "ldx", AddrMode.AbsY), (0xbf, "bbs3", AddrMode.Zpr), (0xc0, "cpy", AddrMode.Imm), (0xc1, "cmp", AddrMode.IzX), (0xc2, "nop", AddrMode.Imm), (0xc3, "nop", AddrMode.Imp), (0xc4, "cpy", AddrMode.Zp), (0xc5, "cmp", AddrMode.Zp), (0xc6, "dec", AddrMode.Zp), (0xc7, "smb4", AddrMode.Zp), (0xc8, "iny", AddrMode.Imp), (0xc9, "cmp", AddrMode.Imm), (0xca, "dex", AddrMode.Imp), (0xcb, "wai", AddrMode.Imp), (0xcc, "cpy", AddrMode.Abs), (0xcd, "cmp", AddrMode.Abs), (0xce, "dec", AddrMode.Abs), (0xcf, "bbs4", AddrMode.Zpr), (0xd0, "bne", AddrMode.Rel), (0xd1, "cmp", AddrMode.IzY), (0xd2, "cmp", AddrMode.Izp), (0xd3, "nop", AddrMode.Imp), (0xd4, "nop", AddrMode.ZpX), (0xd5, "cmp", AddrMode.ZpX), (0xd6, "dec", AddrMode.ZpX), (0xd7, "smb5", AddrMode.Zp), (0xd8, "cld", AddrMode.Imp), (0xd9, "cmp", AddrMode.AbsY), (0xda, "phx", AddrMode.Imp), (0xdb, "stp", AddrMode.Imp), (0xdc, "nop", AddrMode.Abs), (0xdd, "cmp", AddrMode.AbsX), (0xde, "dec", AddrMode.AbsX), (0xdf, "bbs5", AddrMode.Zpr), (0xe0, "cpx", AddrMode.Imm), (0xe1, "sbc", AddrMode.IzX), (0xe2, "nop", AddrMode.Imm), (0xe3, "nop", AddrMode.Imp), (0xe4, "cpx", AddrMode.Zp), (0xe5, "sbc", AddrMode.Zp), (0xe6, "inc", AddrMode.Zp), (0xe7, "smb6", AddrMode.Zp), (0xe8, "inx", AddrMode.Imp), (0xe9, "sbc", AddrMode.Imm), (0xea, "nop", AddrMode.Imp), (0xeb, "nop", AddrMode.Imp), (0xec, "cpx", AddrMode.Abs), (0xed, "sbc", AddrMode.Abs), (0xee, "inc", AddrMode.Abs), (0xef, "bbs6", AddrMode.Zpr), (0xf0, "beq", AddrMode.Rel), (0xf1, "sbc", AddrMode.IzY), (0xf2, "sbc", AddrMode.Izp), (0xf3, "nop", AddrMode.Imp), (0xf4, "nop", AddrMode.ZpX), (0xf5, "sbc", AddrMode.ZpX), (0xf6, "inc", AddrMode.ZpX), (0xf7, "smb7", AddrMode.Zp), (0xf8, "sed", AddrMode.Imp), (0xf9, "sbc", AddrMode.AbsY), (0xfa, "plx", AddrMode.Imp), (0xfb, "nop", AddrMode.Imp), (0xfc, "nop", AddrMode.AbsX), (0xfd, "sbc", AddrMode.AbsX), (0xfe, "inc", AddrMode.AbsX), (0xff, "bbs7", AddrMode.Zpr) ) InstructionsByName = {} for ins in Instructions: if ins[1] not in InstructionsByName: InstructionsByName[ins[1]] = {ins[2]: ins[0]} else: InstructionsByName[ins[1]][ins[2]] = ins[0] InstructionsByMode = {} for ins in Instructions: if ins[2] not in InstructionsByMode: InstructionsByMode[ins[2]] = [(ins[1], ins[0])] else: InstructionsByMode[ins[2]].append((ins[1], ins[0])) # build the name->modes table print(" .cpu \"65c02\"") print("cx16 .block") print(" r0 = $02") print(" .bend") print("; addressing modes:") for mode in AddrMode: print(";", mode.value, "=", mode.name) print() print(""" * = $2000 .enc "petscii" ;define an ascii to petscii encoding .cdef " @", 32 ;characters .cdef "AZ", $c1 .cdef "az", $41 .cdef "[[", $5b .cdef "]]", $5d .edef "", [];replace with no bytes test_get_opcode: phx lda addrmode sta cx16.r0 lda opcode ldx opcode+1 ldy opcode+2 jsr get_opcode ; result is pointer to i_xxx in AY (or $0000 if not found) sta $4000 sty $4001 plx rts opcode: .text "sta",0 addrmode: .byte 9 """) for instr in sorted(InstructionsByName.items()): print("i_" + instr[0] + ":\n\t.byte ", end="") if len(instr[1]) == 1: # many instructions have just 1 addressing mode, save space for those info = instr[1].popitem() print("1,", info[0].value,",", info[1]) else: print("0,0, ", end='') mode_opcodes = [] for mode in AddrMode: if mode in instr[1]: mode_opcodes.append(instr[1][mode]) else: mode_opcodes.append(0) print(",".join(str(o) for o in mode_opcodes), end="") print() mnemonics = list(sorted(set(ins[1] for ins in Instructions))) def first_letters(mnem): return list(sorted(set(m[0] for m in mnemonics))) def second_letters(firstletter): return list(sorted(set(m[1] for m in mnemonics if m[0] == firstletter))) def third_letters(firstletter, secondletter): return list(sorted(set(m[2] for m in mnemonics if m[0] == firstletter and m[1] == secondletter))) def fourth_letters(firstletter, secondletter, thirdletter): longmnem = [m for m in mnemonics if len(m) > 3] return list( sorted(set(m[3] for m in longmnem if m[0] == firstletter and m[1] == secondletter and m[2] == thirdletter))) def make_tree(): tree = {} for first in first_letters(mnemonics): tree[first] = { secondletter: { thirdletter: { fourthletter: {} for fourthletter in fourth_letters(first, secondletter, thirdletter) } for thirdletter in third_letters(first, secondletter) } for secondletter in second_letters(first) } return tree tree = make_tree() print("get_opcode:") for first in tree: print(" cmp #'%s'" % first) print(" bne _not_%s" % first) for second in tree[first]: print(" cpx #'%s'" % second) print(" bne _not_%s%s" % (first,second)) for third in tree[first][second]: print(" cpy #'%s'" % third) print(" bne _not_%s%s%s" % (first, second, third)) if tree[first][second][third]: for fourth in tree[first][second][third]: print(" pha") print(" lda opcode+3") print(" cmp #'%s'" % fourth) print(" bne _not_%s%s%s%s" % (first, second, third, fourth)) print(" pla") print(" lda #i_%s%s%s%s" % (first, second, third, fourth)) print(" rts") print("_not_%s%s%s%s:" % (first, second, third, fourth)) print(" pla") else: print(" lda #i_%s%s%s" % (first, second, third)) print(" rts") print("_not_%s%s%s:" % (first, second, third)) print("_not_%s%s:" % (first, second)) print("_not_%s:" % first) print(" lda #0") print(" ldy #0") print(" rts")