Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
ianklatzco committed Jan 1, 2019
1 parent 7bace0a commit 67353eb
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 67 deletions.
87 changes: 39 additions & 48 deletions 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.
Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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")

##############################################################################

Expand Down
37 changes: 18 additions & 19 deletions 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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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) )

0 comments on commit 67353eb

Please sign in to comment.