From 67353ebb50367430a7d2921d701ea92aa2f0968e Mon Sep 17 00:00:00 2001 From: Ian Klatzco Date: Mon, 31 Dec 2018 20:12:00 -0900 Subject: [PATCH] refactoring --- lc3.py | 87 ++++++++++++++++++++++++----------------------------- lc3disas.py | 37 +++++++++++------------ 2 files changed, 57 insertions(+), 67 deletions(-) diff --git a/lc3.py b/lc3.py index a1dd94f..dc3fa4a 100644 --- a/lc3.py +++ b/lc3.py @@ -1,14 +1,5 @@ # usage: python3 lc3.py ./second.obj -from ctypes import c_uint16, c_int16 -from enum import IntEnum -from struct import unpack -from sys import exit, stdin, stdout, argv -from signal import signal, SIGINT - -class UnimpError(Exception): - pass - # https://justinmeiners.github.io/lc3-vm/ # Load one instruction from memory at the address of the PC register. @@ -24,8 +15,21 @@ class UnimpError(Exception): # c++'s templates. # i am curious if you could do it with python decorators. +# i tried this and it was mostly just an excuse to learn decorators, but it +# isn't the right tool. + +from ctypes import c_uint16, c_int16 +from enum import IntEnum +from struct import unpack +from sys import exit, stdin, stdout, argv +from signal import signal, SIGINT +import lc3disas # in same dir + DEBUG = False +class UnimpError(Exception): + pass + def signal_handler(signal, frame): print("\nbye!") exit() @@ -248,9 +252,6 @@ def op_str_impl(self, instruction): def op_trap_impl(self, instruction): trap_vector = instruction & 0xff - # self.registers.gprs[7] = self.registers.pc.value - # self.registers.pc.value= self.memory[trap_vector] - if trap_vector == 0x20: # getc c = stdin.buffer.read(1)[0] self.registers.gprs[0] = c @@ -295,45 +296,35 @@ def start(self): opcode = instruction >> 12 if DEBUG: - print(opcodes(opcode)) - print(hex(instruction)) + print("instruction: {}".format(hex(instruction))) + print("disassembly: {}".format(lc3disas.single_ins(self.registers.pc.value, instruction))) self.dump_state() input() - if opcode == opcodes.op_add: - self.op_add_impl(instruction) - elif opcode == opcodes.op_and: - self.op_and_impl(instruction) - elif opcode == opcodes.op_not: - self.op_not_impl(instruction) - elif opcode == opcodes.op_br: - self.op_br_impl(instruction) - elif opcode == opcodes.op_jmp: - self.op_jmp_impl(instruction) - elif opcode == opcodes.op_jsr: - self.op_jsr_impl(instruction) - elif opcode == opcodes.op_ld: - self.op_ld_impl(instruction) - elif opcode == opcodes.op_ldi: - self.op_ldi_impl(instruction) - elif opcode == opcodes.op_ldr: - self.op_ldr_impl(instruction) - elif opcode == opcodes.op_lea: - self.op_lea_impl(instruction) - elif opcode == opcodes.op_st: - self.op_st_impl(instruction) - elif opcode == opcodes.op_sti: - self.op_sti_impl(instruction) - elif opcode == opcodes.op_str: - self.op_str_impl(instruction) - elif opcode == opcodes.op_trap: - self.op_trap_impl(instruction) - elif opcode == opcodes.op_res: - self.op_res_impl(instruction) - elif opcode == opcodes.op_rti: - self.op_rti_impl(instruction) - else: - raise Error("invalid opcode") + opcode_dict = \ + { + opcodes.op_add: self.op_add_impl, + opcodes.op_and: self.op_and_impl, + opcodes.op_not: self.op_not_impl, + opcodes.op_br: self.op_br_impl, + opcodes.op_jmp: self.op_jmp_impl, + opcodes.op_jsr: self.op_jsr_impl, + opcodes.op_ld: self.op_ld_impl, + opcodes.op_ldi: self.op_ldi_impl, + opcodes.op_ldr: self.op_ldr_impl, + opcodes.op_lea: self.op_lea_impl, + opcodes.op_st: self.op_st_impl, + opcodes.op_sti: self.op_sti_impl, + opcodes.op_str: self.op_str_impl, + opcodes.op_trap:self.op_trap_impl, + opcodes.op_res: self.op_res_impl, + opcodes.op_rti: self.op_rti_impl + } + + try: + opcode_dict[opcode](instruction) + except KeyError: + raise UnimpError("invalid opcode") ############################################################################## diff --git a/lc3disas.py b/lc3disas.py index b8d20ab..34cfb3f 100644 --- a/lc3disas.py +++ b/lc3disas.py @@ -1,6 +1,9 @@ # print ("usage: python3 lc3.py code.obj") # one warning: lc3 doesn't have section labels, so there's no way to distinguish code and data. +# here there be dragons (this is "learning" code and not "high-quality" code so +# it has silly patterns) + import functools from struct import unpack from sys import argv, exit @@ -72,7 +75,7 @@ def single_ins(pc, instr, *, self = 3): # asterisk: everything after this is kw return '{opcode} R{dr}, R{sr1}, #{sr2}'.format(opcode=opcode, dr=self.dr, sr1=self.sr1, sr2=self.sr2) if opcode == 'BR': - return '{opcode}{n}{z}{p} {label}'.format(opcode=opcode, n=self.n, z=self.z, p=self.p, label=pc+self.pc_offset_9) + return '{opcode}{n}{z}{p} {addr:x}'.format(opcode=opcode, n=self.n, z=self.z, p=self.p, addr=pc+self.pc_offset_9) if opcode == 'JMP': if self.baser == 7: # ret @@ -82,27 +85,27 @@ def single_ins(pc, instr, *, self = 3): # asterisk: everything after this is kw if opcode == 'JSR': if self.jsr_bit: - return 'JSR {addr}'.format(addr=pc+self.pc_offset_11) + return 'JSR {addr:x}'.format(addr=pc+self.pc_offset_11) else: return 'JSRR R{reg}'.format(reg=self.baser) if opcode == 'LD': - return 'LD R{reg}, {addr}'.format(reg=self.dr, addr=pc+self.pc_offset_9) + return 'LD R{reg}, {addr:x}'.format(reg=self.dr, addr=pc+self.pc_offset_9) if opcode == 'LDI': - return 'LDI R{reg}, {addr}'.format(reg=self.dr, addr=self.pc_offset_9) + return 'LDI R{reg}, {addr:x}'.format(reg=self.dr, addr=self.pc_offset_9) if opcode == 'LDR': return 'LDR R{dr}, R{baser}, #{offset}'.format(dr=self.dr, baser=self.baser, offset=self.pc_offset_6) if opcode == 'LEA': - return 'LEA R{dr}, {addr}'.format(dr=self.dr, addr=pc+self.pc_offset_9) + return 'LEA R{dr}, {addr:x}'.format(dr=self.dr, addr=pc+self.pc_offset_9) if opcode == 'NOT': return 'NOT R{dr}, R{sr}'.format(dr=self.dr, sr=self.sr) if opcode == 'ST' or opcode == 'STI': - return '{opcode} R{sr}, {addr}'.format(opcode=opcode, sr=self.sr, addr=pc+self.pc_offset_9) + return '{opcode} R{sr}, {addr:x}'.format(opcode=opcode, sr=self.sr, addr=pc+self.pc_offset_9) if opcode == 'STR': return 'STR R{sr}, R{baser}, #{offset}'.format(sr=self.sr, baser=self.baser, offset=self.pc_offset_6) @@ -129,18 +132,14 @@ def read_file(filename): return li -# ADD R1, R2, #3 - -if len(argv) < 2: - print ("usage: python3 lc3.py code.obj") - exit(255) - -h = read_file(argv[1]) -# h = read_file("second.obj") - -for index,inst in enumerate(h): - pc = index + 1 + 3000 - print( single_ins(pc, inst) ) - +if __name__ == 'main': + if len(argv) < 2: + print ("usage: python3 lc3.py code.obj") + exit(255) + h = read_file(argv[1]) + # h = read_file("second.obj") + for index,inst in enumerate(h): + pc = index + 1 + 3000 + print( single_ins(pc, inst) )