emulator/emulator.py

96 lines
3.6 KiB
Python

#!/usr/bin/env python3
asm = open("instructions", "r").read().split("\n")
asm = [[int(part, 16) if part[:2] == "0x" else part for part in instruction.split("#")[0].strip().split()] for instruction in asm if len(instruction) > 0]
rs = dict([[item, 0] for item in ["ax", "bx", "cx", "dx", "ip", "sp", "sb", "fl"]])
ram = [0 for i in range(1024)]
def debug():
# prints the registers and the first 10 values in ram
print("Registers: " + str(rs));
i = len(ram) - 1
while ram[i] == 0: i -= 1
print("Ram: " + str(ram[:i+1])[:-1] + ", ...]")
def handle_three(i):
instruction = i[0]
first = i[1]
second = i[2]
if instruction == "add": rs[second] += rs[first]
if instruction == "addi": rs[second] += first
if instruction == "sub": rs[second] -= rs[first]
if instruction == "subi": rs[second] -= first
if instruction == "ls": rs[second] <<= rs[first]
if instruction == "lsi": rs[second] <<= first
if instruction == "rs": rs[second] >>= rs[first]
if instruction == "rsi": rs[second] >>= first
if instruction == "xor": rs[second] ^= rs[first]
if instruction == "xori": rs[second] ^= first
if instruction == "and": rs[second] &= rs[first]
if instruction == "andi": rs[second] &= first
if instruction == "mov": rs[second] = rs[first]
if instruction == "movi": rs[second] = first
if instruction == "test":
if rs[second] == rs[first]: rs["fl"] = 0b001
elif rs[second] < rs[first]: rs["fl"] = 0b010
else: rs["fl"] = 0b100
if instruction == "testi":
if rs[second] == first: rs["fl"] = 0b001
elif rs[second] < first: rs["fl"] = 0b010
else: rs["fl"] = 0b100
if instruction == "lea": rs[second] = ram[rs[first]]
if instruction == "leai": rs[second] = ram[first]
if instruction == "sea": ram[rs[first]] = rs[second]
if instruction == "seai": ram[first] = rs[second]
def handle_two(i):
instruction = i[0]
arg = i[1]
if instruction == "call":
handle_two(["pushi", rs["ip"]])
instruction = "jmp"
if instruction == "je":
if rs["fl"] & 0b001 > 0: instruction = "jmp"
if instruction == "jne":
if rs["fl"] & 0b001 == 0: instruction = "jmp"
if instruction == "jl":
if rs["fl"] & 0b100 > 0: instruction = "jmp"
if instruction == "jle":
if rs["fl"] & 0b101 > 0: instruction = "jmp"
if instruction == "jg":
if rs["fl"] & 0b010 > 0: instruction = "jmp"
if instruction == "jge":
if rs["fl"] & 0b011 > 0: instruction = "jmp"
if instruction == "jmp":
rs["ip"] = asm.index([arg + ":"]) - 1
if instruction == "push":
ram[rs["sp"]] = rs[arg]
rs["sp"] += 1
if instruction == "pushi":
ram[rs["sp"]] = arg
rs["sp"] += 1
if instruction == "pop":
rs["sp"] -= 1
rs[arg] = ram[rs["sp"]]
while True:
if rs["ip"] >= len(asm):
print("Out of instructions")
break;
instruction = asm[rs["ip"]]
if len(instruction) == 3: handle_three(instruction)
elif len(instruction) == 2: handle_two(instruction)
elif len(instruction) == 1:
instruction = instruction[0]
if instruction == "debug":
debug()
if instruction == "abort":
print("Aborted at " + str(rs["ip"]))
break
if instruction == "ret":
rs["sp"] -= 1
rs["ip"] = ram[rs["sp"]]
elif len(instruction) != 0:
print("Found suspiciously long instruction \"" + " ".join(instruction) + "\"")
rs["ip"] += 1
if rs["sp"] != 0:
print("WARNING - Stack was not empty at program exit")
debug()