import sys from string import Template TWOWAY = { "ir": "001", "pm": "010", "pc": "011", "hr": "101", "grx": "110", } # to bus: source TB = TWOWAY | { "ar": "100", # "styrord": "111", } # from bus: destination FB = TWOWAY | { "asr": "111" } def compile(lines): addr = 0 labels = {} compiled = [] todo = [] for line in lines: if not line: # empty line, ignore continue if line.startswith(";"): # comment continue if line.endswith(":"): # label labels[line.split(":")[0]] = addr continue if line.startswith("!"): # inline compiled.append(line[1:]) addr += 1 continue for inst in line.split(", "): alu = "0000" tb = "000" fb = "000" s = "0" p = "0" lc = "00" seq = "0000" myadr = "0000000" if "->" in inst: # move a value fr, to = inst.split("->") # via bus if fr in TB: tb = TB[fr] if to in FB: fb = FB[to] if "gr" in fr and len(fr) == 3: tb = TB["grx"] if "gr" in to and len(to) == 3: fb = FB["grx"] if to == "lc": lc = "10" # load alu if to == "ar": alu = "0001" # alu addition if "+" in fr: if "+'" in fr: # ignore flags other = fr.split("+'")[1] alu = "1000" else: other = fr.split("+")[1] alu = "0100" tb = TB[other] # alu subtraction if "-" in fr: other = fr.split("-")[1] tb = TB[other] alu = "0101" if "&" in fr: other = fr.split("&")[1] tb = TB[other] alu = "0110" if inst == "pc++": p = "1" if inst == "k1->upc": seq = "0001" if inst == "k2->upc": seq = "0010" if inst == "0->upc": seq = "0011" if inst == "halt": seq = "1111" if inst == "lc--": lc = "01" if inst == "lsr": alu = "1101" if "?" in inst: cond, to = inst.split("? ") if cond == "l=1": seq = "1100" elif cond == "z=1": seq = "1000" elif cond == "n=1": seq = "1001" elif cond == "o=1": seq = "1011" else: assert False myadr = f"<{to}>" if inst.startswith("b "): seq = "0110" #TODO 0101? myadr = "<{}>".format(inst.split("b ")[1]) compiled.append((inst, (alu, tb, fb, s, p, lc, seq, myadr))) addr += 1 linked = [] for addr, line in enumerate(compiled): if type(line) is str: linked.append((addr, line)) continue inst, (alu, tb, fb, s, p, lc, seq, myadr) = line if myadr != "0000000": for label, label_line in labels.items(): myadr = myadr.replace(f"<{label}>", str(bin(label_line)[2:]).zfill(7)) first = alu[0] rest = alu[1:] + tb + fb + s + p + lc + seq + myadr hs = "".join([f"{int(first):01x}"] + [f"{int(rest[i:i+4], 2):01x}" for i in range(0, len(rest), 4)]) linked.append((addr, hs)) if hs == "0000000": todo.append(inst) if todo: print("todo", file=sys.stderr) print("\n".join(todo), file=sys.stderr) assert False return ["{:02x}: {}".format(addr, line) for addr, line in linked], labels def write(prog, labels): #with open("template.mia", "r") as f: # template = Template(f.read()) ucode_pad = 0x80 - len(prog) ucode = "\n".join(prog + [f"{len(prog)+n:02x}: 0000000" for n in range(ucode_pad)]) insts = [ "load", "store", "add", "sub", "and", "lsr", "bra", "bne", "halt", "cmp", "bge", "beq", ] inst_pad = 0x10 - len(insts) inst_locations = "\n".join([f"{i:02x}: {labels[inst]:02x}" for i, inst in enumerate(insts)] + [f"{n+len(insts):02x}: 00" for n in range(inst_pad)]) print("MyM:") print(ucode) print() print("K1:") print(inst_locations) #print(template.safe_substitute(pm)) print("K2:") if __name__ == "__main__": write(*compile([line.strip() for line in sys.stdin]))