Exemple #1
0
class LC3:
    mem_size = 0xFFFF
    word_size = 16
    num_registers = 8
    kbsr = 0xFE00
    kbdr = 0xFE02
    dsr = 0xFE04
    ddr = 0xFE06
    mcr = 0xFFFE

    def __init__(self):
        self.memory = []
        self.registers = []
        self.pc = 0
        self.psr = 0
        self.instr = None
        self.inputs = ''
        self.ssp = 0x3000
        self.zero_registers()
        self.isr_registers = []
        self.assembler = Assembler()
        self.instrs = [
            self.BR, self.ADD, self.LD, self.ST, self.JSR, self.AND,
            self.LDR, self.STR, self.RTI, self.NOT, self.LDI,
            self.STI, self.JMP, None, self.LEA, self.TRAP
        ]

    def reset_device_registers(self):
        self.memory[LC3.kbsr] = 0
        self.memory[LC3.dsr] = -1
        self.memory[LC3.kbdr] = 0
        self.memory[LC3.ddr] = 0
        self.memory[LC3.mcr] = 1

    def zero_memory(self):
        self.memory = [0] * LC3.mem_size

    def randomize_memory(self):
        self.memory = [randint(0, 1 << LC3.word_size)
                       for _ in range(LC3.mem_size)]

    def zero_registers(self):
        self.registers = [0] * LC3.num_registers

    def randomize_registers(self):
        self.registers = [
            randint(0, 1 << LC3.word_size) for _ in range(LC3.num_registers)
        ]

    def listen_for_input(self):
        def read_input():
            self.inputs += input()
            self.listen_for_input()
        t = threading.Thread(target=read_input)
        t.daemon = True
        t.start()

    def exec_file(self, filename):
        self.exec_memory(self.assembler.assemble_file(filename))

    def exec_lines(self, lines):
        self.exec_memory(self.assembler.assemble(lines))

    def exec_memory(self, memory, origin=0x3000):
        self.memory = memory
        self.reset_device_registers()
        self.pc = origin

        self.listen_for_input()

        key_delay = 0
        while self.memory[LC3.mcr] != 0:
            key_delay += 1
            if self.memory[LC3.dsr] < 0 and self.memory[LC3.ddr] != 0:
                sys.stdout.write(chr(self.memory[LC3.ddr]))
                sys.stdout.flush()
                self.memory[LC3.dsr] = 1
                self.memory[LC3.ddr] = 0
            else:
                self.memory[LC3.dsr] = -1

            self.instr = self.memory[self.pc]
            self.pc += 1

            opcode = (self.instr >> 12) & 0xF

            if self.instrs[opcode] is None:
                raise Exception('IllegalOpcodeException')
            else:
                self.instrs[opcode]()  # execute the current instruction

            if self.inputs:
                cur_input = ord(self.inputs[0])
                self.inputs = self.inputs[1:]
                self.memory[LC3.kbsr] |= 0x8000
                self.memory[LC3.kbdr] = cur_input
                key_delay = 0
            elif key_delay > 2:
                self.memory[LC3.kbsr] &= 0x7FFF

    def set_cc(self, v):
        self.psr &= 0xFFF8
        if v == 0:
            self.psr |= 0b010
        elif v & 0x8000 == 0:
            self.psr |= 0b001
        else:
            self.psr |= 0b100

    def ADD(self):
        mode = bit_range(self.instr, 5, 1)
        sr1 = bit_range(self.instr, 6, 3)
        dr = bit_range(self.instr, 9, 3)
        if not mode:
            sr2 = bit_range(self.instr, 0, 3)
            dr_val = self.registers[sr1] + self.registers[sr2]
        else:
            imm = sext_bit_range(self.instr, 0, 5)
            dr_val = self.registers[sr1] + imm
        self.registers[dr] = dr_val
        self.set_cc(dr_val)

    def AND(self):
        mode = bit_range(self.instr, 5, 1)
        sr1 = bit_range(self.instr, 6, 3)
        dr = bit_range(self.instr, 9, 3)
        if not mode:
            sr2 = bit_range(self.instr, 0, 3)
            dr_val = self.registers[sr1] & self.registers[sr2]
        else:
            imm = sext_bit_range(self.instr, 0, 5)
            dr_val = self.registers[sr1] & imm
        self.registers[dr] = dr_val
        self.set_cc(dr_val)

    def BR(self):
        if bit_range(self.instr, 9, 3) & self.psr != 0:
            pc_offset_9 = sext_bit_range(self.instr, 0, 9)
            self.pc += pc_offset_9

    def JMP(self):
        base_r = bit_range(self.instr, 6, 3)
        self.pc = self.registers[base_r]

    def JSR(self):
        self.registers[7] = self.pc
        mode = bit_range(self.instr, 11, 1)
        if not mode:
            base_r = bit_range(self.instr, 6, 3)
            self.pc = self.registers[base_r]
        else:
            pc_offset_11 = sext_bit_range(self.instr, 0, 11)
            self.pc += pc_offset_11

    def LD(self):
        dr = bit_range(self.instr, 9, 3)
        pc_offset_9 = sext_bit_range(self.instr, 0, 9)
        self.registers[dr] = self.memory[self.pc + pc_offset_9]
        self.set_cc(self.registers[dr])

    def LDI(self):
        dr = bit_range(self.instr, 9, 3)
        pc_offset_9 = sext_bit_range(self.instr, 0, 9)
        self.registers[dr] = self.memory[self.memory[self.pc + pc_offset_9]]
        self.set_cc(self.registers[dr])

    def LDR(self):
        dr = bit_range(self.instr, 9, 3)
        base_r = bit_range(self.instr, 6, 3)
        pc_offset_6 = sext_bit_range(self.instr, 0, 6)
        self.registers[dr] = self.memory[self.registers[base_r] + pc_offset_6]
        self.set_cc(self.registers[dr])

    def LEA(self):
        dr = bit_range(self.instr, 9, 3)
        pc_offset_9 = sext_bit_range(self.instr, 0, 9)
        self.registers[dr] = self.pc + pc_offset_9
        self.set_cc(self.registers[dr])

    def NOT(self):
        dr = bit_range(self.instr, 9, 3)
        sr = bit_range(self.instr, 6, 3)
        self.registers[dr] = ~self.registers[sr]
        self.set_cc(self.registers[dr])

    def RTI(self):
        if bit_range(self.psr, 15, 1) == 0:
            self.pc = self.memory[self.registers[6]]
            self.registers[6] += 1
            temp = self.memory[self.registers[6]]
            self.registers[6] += 1
            self.psr = temp
        else:
            raise Exception('Privilege Mode Exception')

    def ST(self):
        sr = bit_range(self.instr, 9, 3)
        pc_offset_9 = sext_bit_range(self.instr, 0, 9)
        self.memory[self.pc + pc_offset_9] = self.registers[sr]

    def STI(self):
        sr = bit_range(self.instr, 9, 3)
        pc_offset_9 = sext_bit_range(self.instr, 0, 9)
        self.memory[self.memory[self.pc + pc_offset_9]] = self.registers[sr]

    def STR(self):
        sr = bit_range(self.instr, 9, 3)
        base_r = bit_range(self.instr, 6, 3)
        pc_offset_6 = sext_bit_range(self.instr, 0, 6)
        self.memory[self.registers[base_r] + pc_offset_6] = self.registers[sr]

    def TRAP(self):
        self.registers[7] = self.pc
        trap_vect_8 = bit_range(self.instr, 0, 8)
        self.pc = self.memory[trap_vect_8]