#!/usr/bin/env python3

import sys, struct

B32 = 0xffffffff

def run(program):
    arrays = {}
    arrays[0] = program
    ip = 0
    reg = [0]*8
    free_arrays = []
    next_free = 1
    while True:
        instr = program[ip]
        ip += 1
        opcode = (instr >> 28) & 0xf
        c = instr & 7
        b = (instr >> 3) & 7
        a = (instr >> 6) & 7
        if opcode < 8:
            if opcode < 4:
                if opcode < 2:
                    if opcode == 0:
                        # conditional move
                        if reg[c]: reg[a] = reg[b]
                    else:
                        # read
                        reg[a] = arrays[reg[b]][reg[c]]
                else:
                    if opcode == 2:
                        # set
                        arrays[reg[a]][reg[b]] = reg[c]
                    else:
                        # add
                        reg[a] = (reg[b] + reg[c]) & B32
            else:
                if opcode < 6:
                    if opcode == 4:
                        # mul
                        reg[a] = (reg[b] * reg[c]) & B32
                    else:
                        # div
                        reg[a] = reg[b] // reg[c]
                else:
                    if opcode == 6:
                        # nand
                        reg[a] = ~(reg[b] & reg[c]) & B32
                    else:
                        # halt
                        return
        else:
            if opcode < 12:
                if opcode < 10:
                    if opcode == 8:
                        # alloc
                        if free_arrays:
                            i = free_arrays.pop()
                        else:
                            i = next_free
                            next_free += 1
                        arrays[i] = [0]*reg[c]
                        reg[b] = i
                    else:
                        # free
                        del arrays[reg[c]]
                        free_arrays.append(reg[c])
                else:
                    if opcode == 10:
                        # output
                        print("{:c}".format(reg[c] & 0xff), end="")
                        sys.stdout.flush()
                    else:
                        # input
                        reg[c] = ord(sys.stdin.read(1))
            else:
                if opcode == 12:
                    # load
                    if reg[b]:
                        program = arrays[0] = list(arrays[reg[b]])
                    ip = reg[c]
                else:
                    assert(opcode == 13)
                    # ortho
                    a = (instr >> 25) & 7
                    reg[a] = instr & 0x01ffffff

with open(sys.argv[1], "rb") as f:
    contents = f.read()
    program = []
    for i in range(0, len(contents), 4):
        word = struct.unpack_from(">I", contents, i)
        program.append(word[0])
    run(program)
