From c328e9018c92cdd2b7c5101edf8fb601b9db46f5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 18 Jan 2021 01:38:33 +0100 Subject: [PATCH] cx16 assembler was moved into its own github repo --- compiler/res/prog8lib/diskio.p8 | 2 +- examples/cx16/assembler/Makefile | 8 - examples/cx16/assembler/assem.p8 | 733 ------------------ .../cx16/assembler/benchmark-treematch.p8 | 167 ---- examples/cx16/assembler/gen_opcodes.py | 506 ------------ examples/cx16/assembler/hashes.py | 17 - examples/cx16/assembler/perfecthash.py | 152 ---- examples/cx16/assembler/testload.asm | 72 -- 8 files changed, 1 insertion(+), 1656 deletions(-) delete mode 100644 examples/cx16/assembler/Makefile delete mode 100644 examples/cx16/assembler/assem.p8 delete mode 100644 examples/cx16/assembler/benchmark-treematch.p8 delete mode 100644 examples/cx16/assembler/gen_opcodes.py delete mode 100644 examples/cx16/assembler/hashes.py delete mode 100644 examples/cx16/assembler/perfecthash.py delete mode 100644 examples/cx16/assembler/testload.asm diff --git a/compiler/res/prog8lib/diskio.p8 b/compiler/res/prog8lib/diskio.p8 index 07ea6bca5..191019ec4 100644 --- a/compiler/res/prog8lib/diskio.p8 +++ b/compiler/res/prog8lib/diskio.p8 @@ -72,7 +72,7 @@ io_error: str list_filename = "?" * 32 - ; ----- get a list of files (uses iteration functions internally ----- + ; ----- get a list of files (uses iteration functions internally) ----- sub list_files(ubyte drivenumber, uword pattern_ptr, uword name_ptrs, ubyte max_names) -> ubyte { ; -- fill the array 'name_ptrs' with (pointers to) the names of the files requested. diff --git a/examples/cx16/assembler/Makefile b/examples/cx16/assembler/Makefile deleted file mode 100644 index 7412c743a..000000000 --- a/examples/cx16/assembler/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -all: perfecthash.c opcodes.asm - -perfecthash.c: gen_opcodes.py - python gen_opcodes.py --mnemlist | gperf --no-strlen --null-strings -7 -C -D -E -m 100 > perfecthash.c - -opcodes.asm: gen_opcodes.py - python gen_opcodes.py --parser > opcodes.asm - diff --git a/examples/cx16/assembler/assem.p8 b/examples/cx16/assembler/assem.p8 deleted file mode 100644 index a8228c2fd..000000000 --- a/examples/cx16/assembler/assem.p8 +++ /dev/null @@ -1,733 +0,0 @@ -%target cx16 -%import textio -%import diskio -%import string -%import test_stack -%zeropage basicsafe -%option no_sysinit - -; raw file loading of the large assembly file $c000-$ffff: 372 jiffies -; time loading and actually processing it: 700 jiffies - -main { - - sub start() { - txt.print("\ncommander-x16 65c02 file based assembler.\n\nfilename or enter for interactive: ") - - str filename = "?" * 20 - if txt.input_chars(filename) - file_input(filename) - else - user_input() - - cx16.rombank(4) ; switch back to basic rom - - test_stack.test() - } - - sub user_input() { - txt.lowercase() - parser.print_emit_bytes = true - parser.program_counter = $4000 - txt.print("\nEmpty line to stop.\n") - repeat { - ubyte input_length = 0 - txt.chrout('A') - txt.print_uwhex(parser.program_counter, 1) - txt.print(": ") - ; simulate user always having at least one space at the start - parser.input_line[0] = ' ' - input_length = txt.input_chars(&parser.input_line+1) - txt.nl() - - if not input_length { - txt.print("exit\n") - return - } - - if not parser.process_line() - break - } - parser.done() - } - - sub file_input(uword filename) { - parser.print_emit_bytes = false - ubyte success = false - - txt.print("\nreading ") - txt.print(filename) - txt.spc() - - cx16.rombank(0) ; switch to kernal rom for faster file i/o - - if diskio.f_open(8, filename) { - c64.SETTIM(0,0,0) - uword line=0 - repeat { - void diskio.f_readline(parser.input_line) - line++ - - if not lsb(line) - txt.chrout('.') - - if not parser.process_line() { - txt.print("\nerror. last line was ") - txt.print_uw(line) - txt.print(": ") - txt.print(parser.word_addrs[0]) - if parser.word_addrs[1] { - txt.spc() - txt.print(parser.word_addrs[1]) - } - if parser.word_addrs[2] { - txt.spc() - txt.print(parser.word_addrs[2]) - } - txt.nl() - break - } - if c64.READST() { - success = c64.READST()&64==64 ; end of file? - break - } - if c64.STOP2() { - txt.print("?break\n") - break - } - } - diskio.f_close() - parser.done() - - if success - print_summary(line, parser.pc_min, parser.pc_max) - } else { - txt.print(diskio.status(8)) - } - } - - sub print_summary(uword lines, uword start_address, uword end_address) { - txt.print("\n\nstart address: ") - txt.print_uwhex(start_address, 1) - txt.print("\n end address: ") - txt.print_uwhex(end_address, 1) - txt.print("\n lines: ") - txt.print_uw(lines) - - txt.print("\n time (sec): ") - uword current_time = c64.RDTIM16() - uword secs = current_time / 60 - current_time = (current_time - secs*60)*1000/60 - txt.print_uw(secs) - txt.chrout('.') - if current_time<10 - txt.chrout('0') - if current_time<100 - txt.chrout('0') - txt.print_uw(current_time) - txt.nl() - } -} - -parser { - ; byte counts per address mode id: - ubyte[17] operand_size = [$ff, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 2, 1, 2] - - str input_line = "?" * 160 - uword[3] word_addrs - uword program_counter = $ffff - ubyte print_emit_bytes - uword pc_min = $ffff - uword pc_max = $0000 - - sub process_line() -> ubyte { - string.lower(input_line) - preprocess_assignment_spacing() - split_input() - - if word_addrs[1] and @(word_addrs[1])=='=' - return do_assign() - else - return do_label_andor_instr() - - return false - } - - sub done() { - if program_counter>pc_max - pc_max = program_counter - } - - sub do_assign() -> ubyte { - ; target is in word_addrs[0], value is in word_addrs[2] ('=' is in word_addrs[1]) - if not word_addrs[2] { - txt.print("?syntax error\n") - return false - } - ubyte valid_operand=false - if @(word_addrs[2])=='*' { - cx16.r15 = program_counter - valid_operand = true - } else { - ubyte nlen = conv.any2uword(word_addrs[2]) - valid_operand = nlen and @(word_addrs[2]+nlen)==0 - } - - if valid_operand { - if string.compare(word_addrs[0], "*")==0 { - program_counter = cx16.r15 - txt.print("\n* = ") - txt.print_uwhex(program_counter, true) - txt.nl() - if program_counterpc_max - pc_max = program_counter - } else { - symbols.setvalue(word_addrs[0], cx16.r15) - } - return true - } - txt.print("?invalid operand\n") - return false - } - - sub do_label_andor_instr() -> ubyte { - uword label_ptr = 0 - uword instr_ptr = 0 - uword operand_ptr = 0 - ubyte starts_with_whitespace = input_line[0]==' ' or input_line[0]==9 or input_line[0]==160 - - if word_addrs[2] { - label_ptr = word_addrs[0] - instr_ptr = word_addrs[1] - operand_ptr = word_addrs[2] - } else if word_addrs[1] { - if starts_with_whitespace { - instr_ptr = word_addrs[0] - operand_ptr = word_addrs[1] - } else { - label_ptr = word_addrs[0] - instr_ptr = word_addrs[1] - } - } else if word_addrs[0] { - if starts_with_whitespace - instr_ptr = word_addrs[0] - else - label_ptr = word_addrs[0] - } - - if label_ptr { - uword lastlabelchar = label_ptr + string.length(label_ptr)-1 - if @(lastlabelchar) == ':' - @(lastlabelchar) = 0 - if instructions.match(label_ptr) { - txt.print("?label cannot be a mnemonic\n") - return false - } - symbols.setvalue(label_ptr, program_counter) - } - if instr_ptr { - if @(instr_ptr)=='.' - return process_assembler_directive(instr_ptr, operand_ptr) - - return assemble_instruction(instr_ptr, operand_ptr) - } - - return true ; empty line - } - - sub assemble_instruction(uword instr_ptr, uword operand_ptr) -> ubyte { - uword instruction_info_ptr = instructions.match(instr_ptr) - if instruction_info_ptr { - ; we got a mnemonic match, now process the operand (and its value, if applicable, into cx16.r15) - ubyte addr_mode = parse_operand(operand_ptr) - - if addr_mode { - ubyte opcode = instructions.opcode(instruction_info_ptr, addr_mode) - if_cc { - ; most likely an invalid instruction BUT could also be a branchin instruction - ; that needs its "absolute" operand recalculated as relative. - ubyte retry = false - when addr_mode { - instructions.am_Abs -> { - if @(instr_ptr)=='b' { - addr_mode = instructions.am_Rel - if not calc_relative_branch_into_r14() - return false - cx16.r15 = cx16.r14 - retry = true - } - } - instructions.am_Imp -> { - addr_mode = instructions.am_Acc - retry = true - } - instructions.am_Izp -> { - addr_mode = instructions.am_Ind - retry = true - } - instructions.am_Zp -> { - addr_mode = instructions.am_Abs - retry = true - } - } - - if retry - opcode = instructions.opcode(instruction_info_ptr, addr_mode) - - if not opcode { - txt.print("?invalid instruction\n") - return false - } - } - - if addr_mode==instructions.am_Zpr { - ; instructions like BBR4 $zp,$aaaa (dual-operand) - uword comma = string.find(operand_ptr,',') - if comma { - comma++ - cx16.r13 = cx16.r15 - if parse_operand(comma) { - program_counter++ - if not calc_relative_branch_into_r14() - return false - program_counter-- - cx16.r15 = (cx16.r14 << 8) | lsb(cx16.r13) - } else { - txt.print("?invalid operand\n") - return false - } - } else { - txt.print("?invalid operand\n") - return false - } - } - - ubyte num_operand_bytes = operand_size[addr_mode] - if print_emit_bytes { - txt.spc() - txt.print_uwhex(program_counter, 1) - txt.print(" ") - } - emit(opcode) - if num_operand_bytes==1 { - emit(lsb(cx16.r15)) - } else if num_operand_bytes == 2 { - emit(lsb(cx16.r15)) - emit(msb(cx16.r15)) - } - if print_emit_bytes - txt.nl() - return true - } - txt.print("?invalid operand\n") - return false - } - txt.print("?invalid instruction\n") - return false - } - - sub calc_relative_branch_into_r14() -> ubyte { - cx16.r14 = cx16.r15 - program_counter - 2 - if msb(cx16.r14) { - if cx16.r14 < $ff80 { - txt.print("?branch out of range\n") - return false - } - } else if cx16.r14 > $007f { - txt.print("?branch out of range\n") - return false - } - return true - } - - sub parse_operand(uword operand_ptr) -> ubyte { - ; parses the operand. Returns 2 things: - ; - addressing mode id as result value or 0 (am_Invalid) when error - ; - operand numeric value in cx16.r15 (if applicable) - - ubyte @zp firstchr = @(operand_ptr) - ubyte parsed_len - when firstchr { - 0 -> return instructions.am_Imp - '#' -> { - ; lda #$99 Immediate - operand_ptr++ - parsed_len = conv.any2uword(operand_ptr) - if parsed_len { - operand_ptr += parsed_len - if @(operand_ptr)==0 - return instructions.am_Imm - } - } - 'a' -> { - if not @(operand_ptr+1) - return instructions.am_Acc ; Accumulator - no value. - - ; TODO its a symbol/label, immediate or indexed addressing - txt.print("TODO symbol: ") - txt.print(operand_ptr) - txt.nl() - } - '(' -> { - ; various forms of indirect - operand_ptr++ - parsed_len = conv.any2uword(operand_ptr) - if parsed_len { - operand_ptr+=parsed_len - if msb(cx16.r15) { - ; absolute indirects - if str_is1(operand_ptr, ')') - return instructions.am_Ind - if str_is3(operand_ptr, ",x)") - return instructions.am_IaX - } else { - ; zero page indirects - if str_is1(operand_ptr, ')') - return instructions.am_Izp - if str_is3(operand_ptr, ",x)") - return instructions.am_IzX - if str_is3(operand_ptr, "),y") - return instructions.am_IzY - } - } - } - '$', '%', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> { - ; address optionally followed by ,x or ,y or ,address - parsed_len = conv.any2uword(operand_ptr) - if parsed_len { - operand_ptr += parsed_len - if msb(cx16.r15) { - ; absolute or abs indirects - if @(operand_ptr)==0 - return instructions.am_Abs - if str_is2(operand_ptr, ",x") - return instructions.am_AbsX - if str_is2(operand_ptr, ",y") - return instructions.am_AbsY - } else { - ; zero page or zp indirects - if @(operand_ptr)==0 - return instructions.am_Zp - if str_is2(operand_ptr, ",x") - return instructions.am_ZpX - if str_is2(operand_ptr, ",y") - return instructions.am_ZpY - if @(operand_ptr)==',' { - ; assume BBR $zp,$aaaa or BBS $zp,$aaaa - return instructions.am_Zpr - } - } - } - } - } - return instructions.am_Invalid - } - - sub process_assembler_directive(uword directive, uword operand) -> ubyte { - ; we only recognise .byte right now - if string.compare(directive, ".byte")==0 { - if operand { - ubyte length - length = conv.any2uword(operand) - if length { - if msb(cx16.r15) { - txt.print("?byte value too large\n") - return false - } - if print_emit_bytes { - txt.spc() - txt.print_uwhex(program_counter, 1) - txt.print(" ") - } - emit(lsb(cx16.r15)) - operand += length - while @(operand)==',' { - operand++ - length = conv.any2uword(operand) - if not length - break - if msb(cx16.r15) { - txt.print("?byte value too large\n") - return false - } - emit(lsb(cx16.r15)) - operand += length - } - if print_emit_bytes - txt.nl() - return true - } - } - } - txt.print("?syntax error\n") - return false - } - - asmsub str_is1(uword st @R0, ubyte char @A) clobbers(Y) -> ubyte @A { - %asm {{ - cmp (cx16.r0) - bne + - ldy #1 - lda (cx16.r0),y - bne + - lda #1 - rts -+ lda #0 - rts - }} - } - - asmsub str_is2(uword st @R0, uword compare @AY) clobbers(Y) -> ubyte @A { - %asm {{ - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldy #0 - jmp str_is3._is_2_entry - }} - } - - asmsub str_is3(uword st @R0, uword compare @AY) clobbers(Y) -> ubyte @A { - %asm {{ - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda (cx16.r0) - cmp (P8ZP_SCRATCH_W1) - bne + - ldy #1 -_is_2_entry - lda (cx16.r0),y - cmp (P8ZP_SCRATCH_W1),y - bne + - iny - lda (cx16.r0),y - cmp (P8ZP_SCRATCH_W1),y - bne + - iny - lda (cx16.r0),y - bne + - lda #1 - rts -+ lda #0 - rts - }} - } - - sub emit(ubyte value) { - @(program_counter) = value - program_counter++ - - if print_emit_bytes { - txt.print_ubhex(value, 0) - txt.spc() - } - } - - sub dummy(uword operand_ptr) -> uword { - uword a1=rndw() - uword a6=a1+operand_ptr - return a6 - } - - sub split_input() { - ; first strip the input string of extra whitespace and comments - ubyte copying_word = false - ubyte word_count - ubyte @zp char_idx = 0 - - word_addrs[0] = 0 - word_addrs[1] = 0 - word_addrs[2] = 0 - - ubyte @zp char - for char in input_line { - when char { - ' ', 9, 160 -> { - if copying_word - input_line[char_idx] = 0; terminate word - copying_word = false - } - ';', 0 -> { - ; terminate line on comment char or end-of-string - break - } - else -> { - if not copying_word { - if word_count==3 - break - word_addrs[word_count] = &input_line + char_idx - word_count++ - } - copying_word = true - } - } - char_idx++ - } - - char = input_line[char_idx] - if char==' ' or char==9 or char==160 or char==';' - input_line[char_idx] = 0 - } - - sub debug_print_words() { ; TODO remove - txt.print("(debug:) words: ") - uword word_ptr - for word_ptr in word_addrs { - txt.chrout('[') - txt.print(word_ptr) - txt.print("] ") - } - txt.nl() - } - - sub preprocess_assignment_spacing() { - if not string.find(input_line, '=') - return - - ; split the line around the '=' - str input_line2 = "?" * 40 - uword src = &input_line - uword dest = &input_line2 - ubyte @zp cc - for cc in input_line { - if cc=='=' { - @(dest) = ' ' - dest++ - @(dest) = '=' - dest++ - cc = ' ' - } - @(dest) = cc - dest++ - } - @(dest)=0 - void string.copy(input_line2, src) - } -} - -symbols { - sub setvalue(uword symbolname_ptr, uword value) { - txt.print("symbol: ") - txt.print(symbolname_ptr) - txt.chrout('=') - txt.print_uwhex(value, true) - txt.nl() - } -} - -instructions { - const ubyte am_Invalid = 0 - const ubyte am_Imp = 1 - const ubyte am_Acc = 2 - const ubyte am_Imm = 3 - const ubyte am_Zp = 4 - const ubyte am_ZpX = 5 - const ubyte am_ZpY = 6 - const ubyte am_Rel = 7 - const ubyte am_Abs = 8 - const ubyte am_AbsX = 9 - const ubyte am_AbsY = 10 - const ubyte am_Ind = 11 - const ubyte am_IzX = 12 - const ubyte am_IzY = 13 - const ubyte am_Zpr = 14 - const ubyte am_Izp = 15 - const ubyte am_IaX = 16 - - ; TODO: explore (benchmark) hash based matchers. Faster (although the bulk of the time is not in the mnemonic matching)? Less memory? - - asmsub match(uword mnemonic_ptr @AY) -> uword @AY { - ; -- input: mnemonic_ptr in AY, output: pointer to instruction info structure or $0000 in AY - %asm {{ - phx - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - lda (P8ZP_SCRATCH_W1) - and #$7f ; lowercase - pha - ldy #1 - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - pha - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - pha - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - sta cx16.r4 ; fourth letter in R4 (only exists for the few 4-letter mnemonics) - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - sta cx16.r5 ; fifth letter in R5 (should always be zero or whitespace for a valid mnemonic) - pla - tay - pla - tax - pla - jsr get_opcode_info - plx - rts - }} - } - - asmsub opcode(uword instr_info_ptr @AY, ubyte addr_mode @X) clobbers(X) -> ubyte @A, ubyte @Pc { - ; -- input: instruction info struct ptr @AY, desired addr_mode @X - ; output: opcode @A, valid @carrybit - %asm {{ - cpy #0 - beq _not_found - sta P8ZP_SCRATCH_W2 - sty P8ZP_SCRATCH_W2+1 - stx cx16.r5 - - ; debug result address - ;sec - ;jsr txt.print_uwhex - ;lda #13 - ;jsr c64.CHROUT - - lda (P8ZP_SCRATCH_W2) - beq _multi_addrmodes - ldy #1 - lda (P8ZP_SCRATCH_W2),y - cmp cx16.r5 ; check single possible addr.mode - bne _not_found - iny - lda (P8ZP_SCRATCH_W2),y ; get opcode - sec - rts - -_not_found lda #0 - clc - rts - -_multi_addrmodes - ldy cx16.r5 - lda (P8ZP_SCRATCH_W2),y ; check opcode for addr.mode - bne _valid - ; opcode $00 usually means 'invalid' but for "brk" it is actually valid so check for "brk" - lda (P8ZP_SCRATCH_W1) - and #$7f ; lowercase - cmp #'b' - bne _not_found - ldy #1 - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - cmp #'r' - bne _not_found - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - cmp #'k' - bne _not_found - lda #0 -_valid sec - rts - }} - } - - %asminclude "opcodes.asm", "" -} diff --git a/examples/cx16/assembler/benchmark-treematch.p8 b/examples/cx16/assembler/benchmark-treematch.p8 deleted file mode 100644 index 5bbfbbccd..000000000 --- a/examples/cx16/assembler/benchmark-treematch.p8 +++ /dev/null @@ -1,167 +0,0 @@ -%target cx16 -%import test_stack -%import textio -%zeropage basicsafe -%option no_sysinit - - -main { - - sub start() { - txt.print("\nassembler benchmark - tree match routine\n") - - benchmark.benchmark() - - test_stack.test() - } - -} - -benchmark { - sub benchmark() { - str[20] mnemonics = ["lda", "ldx", "ldy", "jsr", "bcs", "rts", "lda", "ora", "and", "eor", "wai", "nop", "wai", "nop", "wai", "nop", "wai", "nop", "wai", "nop"] - ubyte[20] modes = [3, 4, 8, 8, 7, 1, 12, 13, 5, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - uword valid = 0 - - const uword iterations = 40000 / len(mnemonics) - const uword amount = iterations * len(mnemonics) - - txt.print("matching ") - txt.print_uw(amount) - txt.print(" mnemonics") - - c64.SETTIM(0,0,0) - - uword total = 0 - repeat iterations { - if lsb(total)==0 - txt.chrout('.') - ubyte idx - for idx in 0 to len(mnemonics)-1 { - uword instr_info = instructions.match(mnemonics[idx]) - ubyte opcode = instructions.opcode(instr_info, modes[idx]) - if_cs - valid++ - total++ - } - } - - uword current_time = c64.RDTIM16() - txt.print("\nvalid: ") - txt.print_uw(valid) - txt.print("\ninvalid: ") - txt.print_uw(amount-valid) - txt.print("\ntotal: ") - txt.print_uw(total) - txt.print("\n\nseconds:") - uword secs = current_time / 60 - current_time = (current_time - secs*60)*1000/60 - txt.print_uw(secs) - txt.chrout('.') - if current_time<10 - txt.chrout('0') - if current_time<100 - txt.chrout('0') - txt.print_uw(current_time) - txt.nl() - } -} - -instructions { - asmsub match(uword mnemonic_ptr @AY) -> uword @AY { - ; -- input: mnemonic_ptr in AY, output: pointer to instruction info structure or $0000 in AY - %asm {{ - phx - sta P8ZP_SCRATCH_W1 - sty P8ZP_SCRATCH_W1+1 - ldy #0 - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - pha - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - pha - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - pha - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - sta cx16.r4 ; fourth letter in R4 (only exists for the few 4-letter mnemonics) - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - sta cx16.r5 ; fifth letter in R5 (should always be zero or whitespace for a valid mnemonic) - pla - tay - pla - tax - pla - jsr get_opcode_info - plx - rts - }} - } - - asmsub opcode(uword instr_info_ptr @AY, ubyte addr_mode @X) clobbers(X) -> ubyte @A, ubyte @Pc { - ; -- input: instruction info struct ptr @AY, desired addr_mode @X - ; output: opcode @A, valid @carrybit - %asm {{ - cpy #0 - beq _not_found - sta P8ZP_SCRATCH_W2 - sty P8ZP_SCRATCH_W2+1 - stx cx16.r15 - - ; debug result address - ;sec - ;jsr txt.print_uwhex - ;lda #13 - ;jsr c64.CHROUT - - ldy #0 - lda (P8ZP_SCRATCH_W2),y - beq _multi_addrmodes - iny - lda (P8ZP_SCRATCH_W2),y - cmp cx16.r15 ; check single possible addr.mode - bne _not_found - iny - lda (P8ZP_SCRATCH_W2),y ; get opcode - sec - rts - -_not_found lda #0 - clc - rts - -_multi_addrmodes - ldy cx16.r15 - lda (P8ZP_SCRATCH_W2),y ; check opcode for addr.mode - bne _valid - ; opcode $00 usually means 'invalid' but for "brk" it is actually valid so check for "brk" - ldy #0 - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - cmp #'b' - bne _not_found - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - cmp #'r' - bne _not_found - iny - lda (P8ZP_SCRATCH_W1),y - and #$7f ; lowercase - cmp #'k' - bne _not_found - lda #0 -_valid sec - rts - }} - } - - %asminclude "opcodes.asm", "" -} diff --git a/examples/cx16/assembler/gen_opcodes.py b/examples/cx16/assembler/gen_opcodes.py deleted file mode 100644 index d34ba41b3..000000000 --- a/examples/cx16/assembler/gen_opcodes.py +++ /dev/null @@ -1,506 +0,0 @@ -import sys -from collections import Counter -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 - - -AllInstructions = [ - (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) -] - -# NOP is weird, it is all over the place. -# For the 'common' immediate NOP, keep only the $EA opcode (this was the original NOP on the 6502) -Instructions = [ins for ins in AllInstructions if ins[1] != "nop"] + [(0xea, "nop", AddrMode.Imp)] - - -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])) - - -def generate_mnemonics_parser(): - print("; generated by opcodes.py") - print("; addressing modes:") - for mode in AddrMode: - print(";", mode.value, "=", mode.name) - print() - - print(""" - .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 - """) - - 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, ", 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() - - def determine_mnemonics(): - mnemonics = list(sorted(set(ins[1] for ins in Instructions))) - - # opcodes histogram (ordered by occurrence) (in kernal + basic roms of the c64): - opcode_occurrences = [ - (32, 839), (133, 502), (165, 488), (0, 429), (208, 426), (169, 390), (76, 324), (240, 322), (2, 314), (160, 245), - (96, 228), (3, 201), (1, 191), (255, 186), (144, 182), (170, 175), (162, 169), (177, 165), (104, 159), (164, 158), - (132, 157), (201, 156), (72, 151), (141, 150), (200, 146), (173, 144), (166, 139), (176, 139), (16, 138), - (134, 138), (73, 127), (24, 119), (101, 113), (69, 109), (13, 107), (34, 104), (145, 103), (4, 102), (168, 101), - (221, 98), (230, 93), (48, 91), (189, 87), (41, 86), (6, 86), (9, 86), (8, 85), (79, 85), (138, 80), (10, 80), - (7, 79), (185, 77), (56, 75), (44, 75), (78, 74), (105, 73), (5, 73), (174, 73), (220, 71), (198, 69), (232, 69), - (36, 69), (202, 67), (152, 67), (95, 67), (100, 65), (102, 65), (247, 65), (188, 64), (136, 64), (84, 64), - (122, 62), (128, 61), (80, 61), (186, 60), (82, 59), (97, 58), (15, 57), (70, 57), (229, 56), (19, 55), (40, 54), - (183, 54), (65, 54), (233, 53), (180, 53), (12, 53), (171, 53), (197, 53), (83, 52), (248, 52), (112, 51), - (237, 51), (89, 50), (11, 50), (158, 50), (74, 49), (224, 48), (20, 47), (238, 47), (108, 46), (234, 46), - (251, 46), (254, 46), (184, 45), (14, 44), (163, 44), (226, 43), (211, 43), (88, 43), (98, 42), (17, 42), - (153, 42), (243, 41), (228, 41), (99, 41), (253, 41), (209, 41), (187, 39), (123, 39), (67, 39), (196, 38), - (68, 38), (35, 38), (172, 38), (175, 38), (161, 38), (85, 38), (191, 37), (113, 37), (182, 37), (151, 37), - (71, 36), (181, 35), (214, 35), (121, 35), (157, 35), (178, 35), (77, 35), (42, 34), (212, 33), (18, 33), - (127, 33), (241, 33), (21, 33), (249, 32), (23, 31), (245, 30), (142, 30), (55, 29), (140, 29), (46, 29), - (192, 29), (179, 29), (252, 29), (115, 29), (22, 29), (43, 28), (215, 28), (45, 28), (246, 28), (38, 28), - (86, 27), (225, 27), (25, 26), (239, 26), (58, 26), (167, 26), (147, 26), (217, 26), (149, 25), (30, 25), - (206, 25), (28, 24), (47, 24), (37, 24), (155, 24), (129, 23), (148, 23), (111, 23), (29, 23), (39, 23), - (51, 22), (193, 22), (236, 22), (120, 22), (64, 22), (204, 21), (210, 21), (244, 21), (52, 21), (66, 21), - (114, 20), (250, 20), (106, 20), (93, 19), (199, 19), (218, 19), (154, 19), (205, 19), (50, 19), (159, 19), - (194, 19), (49, 19), (190, 19), (103, 18), (216, 18), (213, 18), (107, 18), (131, 18), (63, 18), (94, 18), - (91, 17), (242, 17), (109, 17), (53, 16), (227, 16), (139, 16), (31, 16), (75, 16), (60, 16), (195, 15), - (231, 15), (62, 15), (59, 15), (87, 14), (207, 14), (27, 14), (90, 14), (110, 13), (223, 13), (57, 13), - (118, 12), (26, 12), (203, 12), (81, 12), (156, 12), (54, 12), (235, 12), (146, 11), (135, 11), (126, 11), - (150, 11), (130, 11), (143, 10), (61, 10), (219, 10), (124, 9), (222, 9), (125, 9), (119, 7), (137, 7), - (33, 7), (117, 5), (92, 4), (116, 3) - ] - - cnt = Counter() - for opcode, amount in opcode_occurrences: - cnt[AllInstructions[opcode][1]] += amount - cnt["nop"] = 13 - cnt["tsb"] = 13 - - four_letter_mnemonics = list(sorted([ins[1] for ins in AllInstructions if len(ins[1])>3])) - for ins4 in four_letter_mnemonics: - del cnt[ins4] - cnt[ins4] = 1 - mnem2 = [c[0] for c in cnt.most_common()] - if len(mnem2)!=len(mnemonics): - raise ValueError("mnem count mismatch") - return mnem2 - - mnemonics = determine_mnemonics() - - def first_letters(): - firstletters = {m[0]: 0 for m in mnemonics} - return firstletters.keys() - - def second_letters(firstletter): - secondletters = {m[1]: 0 for m in mnemonics if m[0] == firstletter} - return secondletters.keys() - - def third_letters(firstletter, secondletter): - thirdletters = {m[2]: 0 for m in mnemonics if m[0] == firstletter and m[1] == secondletter} - return thirdletters.keys() - - def fourth_letters(firstletter, secondletter, thirdletter): - longmnem = [m for m in mnemonics if len(m) > 3] - fourthletters = {m[3]: 0 for m in longmnem if m[0] == firstletter and m[1] == secondletter and m[2] == thirdletter} - return fourthletters.keys() - - def make_tree(): - tree = {} - for first in first_letters(): - 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_info .proc") - print("_mnem_fourth_letter = cx16.r4") - print("_mnem_fifth_letter = cx16.r5") - 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)) - fourth = tree[first][second][third] - if fourth: - if "".join(fourth.keys()) != "01234567": - raise ValueError("fourth", fourth.keys()) - print(" bra _check_%s%s%s" % (first, second, third)) - else: - print(" lda _mnem_fourth_letter") # check that the fourth letter is not present - print(" bne _invalid") - 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("_invalid:") - print(" lda #0") - print(" ldy #0") - print(" rts") - - # the 4-letter mnemonics are: - # smb[0-7] - # bbr[0-7] - # rmb[0-7] - # bbs[0-7] - for fourlettermnemonic in ["smb", "bbr", "rmb", "bbs"]: - print("_check_%s" % fourlettermnemonic) - print(" lda #<_tab_%s" % fourlettermnemonic) - print(" ldy #>_tab_%s" % fourlettermnemonic) - print(""" sta P8ZP_SCRATCH_W2 - sty P8ZP_SCRATCH_W2+1 - bra _check4""") - - print("""_check4 - lda _mnem_fourth_letter - cmp #'0' - bcc _invalid - cmp #'8' - bcs _invalid - lda _mnem_fifth_letter ; must have no fifth letter - bne _invalid - lda _mnem_fourth_letter - sec - sbc #'0' - asl a - tay - lda (P8ZP_SCRATCH_W2),y - pha - iny - lda (P8ZP_SCRATCH_W2),y - tay - pla - rts""") - - for fourlettermnemonic in ["smb", "bbr", "rmb", "bbs"]: - print("_tab_%s" % fourlettermnemonic) - for ii in "01234567": - print(" .word i_%s%s" % (fourlettermnemonic, ii)) - - print(" .pend") - - -def generate_mnem_list(): - for m in sorted(InstructionsByName): - print(m.upper()) - - -if __name__=="__main__": - if sys.argv[1]=="--mnemlist": - generate_mnem_list() - elif sys.argv[1]=="--parser": - generate_mnemonics_parser() - else: - print("invalid arg") diff --git a/examples/cx16/assembler/hashes.py b/examples/cx16/assembler/hashes.py deleted file mode 100644 index 84f2b7df3..000000000 --- a/examples/cx16/assembler/hashes.py +++ /dev/null @@ -1,17 +0,0 @@ -import re - -hashcode = open("perfecthash.c", "rt").read() - -entries = hashcode.split("wordlist")[1].split("{")[1].split("}")[0].strip().split(",") - -max_hash_value = int(re.search(r"MAX_HASH_VALUE = (\d+)", hashcode).group(1)) - -if len(entries) != max_hash_value+1: - raise ValueError("inconsistent number of entries parsed") - - -entries = [e.strip() for e in entries] -entries = [None if e.endswith('0') else e.strip('"') for e in entries] - -for ix, entry in enumerate(entries): - print(ix, entry or "-") diff --git a/examples/cx16/assembler/perfecthash.py b/examples/cx16/assembler/perfecthash.py deleted file mode 100644 index a4c32f8a8..000000000 --- a/examples/cx16/assembler/perfecthash.py +++ /dev/null @@ -1,152 +0,0 @@ - -def in_word_set(string: str) -> bool: - length = len(string) - - wordlist = [ - "PHP", - "ROR", - "STP", - "RTS", - "RTI", - "TXS", - "PHY", - "TRB", - "EOR", - "STY", - "PHX", - "TSB", - "TAY", - "STX", - "BRK", - "LSR", - "TAX", - "TSX", - "PHA", - "PLP", - "BRA", - "STA", - "ROL", - "BCS", - "SEI", - "TXA", - "LDY", - "PLY", - "INY", - "LDX", - "PLX", - "NOP", - "INX", - "CLI", - "ASL", - "SBC", - "BMI", - "LDA", - "PLA", - "ORA", - "BNE", - "ADC", - "BBS7", - "BBR7", - "CMP", - "CPY", - "INC", - "SEC", - "BCC", - "CPX", - "BPL", - "DEY", - "TYA", - "CLV", - "DEX", - "CLC", - "BBS6", - "BBR6", - "BBS5", - "BBR5", - "SMB7", - "RMB7", - "STZ", - "SED", - "BBS4", - "BBR4", - "DEC", - "BBS3", - "BBR3", - "BBS2", - "BBR2", - "AND", - "CLD", - "BBS1", - "BBR1", - "BEQ", - "SMB6", - "RMB6", - "SMB5", - "RMB5", - "BBS0", - "BBR0", - "BVS", - "WAI", - "SMB4", - "RMB4", - "JSR", - "SMB3", - "RMB3", - "SMB2", - "RMB2", - "BIT", - "SMB1", - "RMB1", - "SMB0", - "RMB0", - "BVC", - "JMP" - ] - - lookup = [ - -1, 0, -1, 1, 2, 3, -1, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, -1, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, -1, 50, - 51, 52, -1, 53, 54, 55, -1, 56, 57, 58, 59, -1, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, -1, 83, 84, 85, 86, 87, - 88, 89, 90, 91, -1, -1, 92, 93, -1, -1, -1, -1, -1, 94, - 95, -1, -1, -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, 97 - ] - - asso_values = [ - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 73, 66, - 61, 59, 56, 49, 47, 30, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 10, 3, 13, 23, 9, - 25, 126, 126, 1, 90, 7, 12, 22, 35, 23, - 0, 28, 1, 0, 4, 4, 12, 88, 6, 4, - 33, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, - 126, 126, 126, 126, 126, 126, 126, 126, 126 - ] - - print(len(lookup)) - print(len(asso_values)) - - def hash(string: str, length: len) -> int: - return asso_values[ord(string[2])] + \ - asso_values[ord(string[1])+1] + \ - asso_values[ord(string[0])] + \ - asso_values[ord(string[length - 1])] - - MAX_HASH_VALUE = 125 - - if 3<=length<=4: - key = hash(string, length) - if key <= MAX_HASH_VALUE: - index = lookup[key] - if index>=0: - word = wordlist[index] - return word==string - return False diff --git a/examples/cx16/assembler/testload.asm b/examples/cx16/assembler/testload.asm deleted file mode 100644 index da06c823a..000000000 --- a/examples/cx16/assembler/testload.asm +++ /dev/null @@ -1,72 +0,0 @@ -; program to test the loading speed - -.cpu "65c02" -*=$0801 - ; 10 sys 2061 - .byte $0b, $08, $0a, $00, $9e, $32, $30, $36 - .byte $31, $00, $00, $00 - -start - - stz $9f60 ; switch to kernal bank for faster i/o - phx - - ldx #<_filename - ldy #>_filename - lda #10 - jsr $FFBD ; SETNAM - jmp _go -_filename - .text "romdis.asm" - -_go - lda #0 - tax - tay - jsr $FFDB ; SETTIM 0,0,0 - - lda #1 - ldx #8 - ldy #0 - jsr $FFBA ; SETLFS 1,8,0 - jsr $FFC0 ; OPEN - ldx #1 - jsr $FFC6 ; CHKIN, use #1 as output channel - ;lda #'.' - ;jsr $FFD2 ; CHROUT - - ; load the file .... -_loop - jsr $ffb7 ;READST - bne _eof - jsr $FFCF ;CHRIN - sta $02 ; store... - jmp _loop - -_eof - ; close stuff - jsr $FFCC ;CLRCHN - lda #1 - jsr $FFC3 ;CLOSE - - lda #4 - sta $9f60 - - ; print the time taken - jsr $FFDE ; RDTIM -> A,X,Y - tay - txa - jsr $fe03 ; GIVAYF - jsr $fe81 ; FOUT - sta 2 - sty 3 - ldy #0 -_printlp - lda (2),y - beq _endstr - jsr $FFD2 ; CHROUT - iny - bne _printlp -_endstr - plx - rts