aboutsummaryrefslogtreecommitdiffstats
path: root/asm.py
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-07 16:38:04 +0000
committerGravatar Peter McGoron 2023-02-07 16:38:04 +0000
commita7308280cb5daaff1f42eedbd450e6f3fc3c93b6 (patch)
tree47a88f33ecbfad452e4d182caffbddbb3f61d07c /asm.py
parentfix parse_special_byte function (diff)
start assembler
Diffstat (limited to 'asm.py')
-rw-r--r--asm.py109
1 files changed, 109 insertions, 0 deletions
diff --git a/asm.py b/asm.py
new file mode 100644
index 0000000..cd6a94d
--- /dev/null
+++ b/asm.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python3
+
+from enum import Enum
+
+class ArgType(Enum):
+ TYPE_IMM = 1
+ TYPE_REG = 2
+ TYPE_VAL = 3
+ TYPE_LAB = 4
+
+ def gettype(s):
+ if s.isnumeric():
+ return (TYPE_IMM, int(s))
+ elif s[0] == 'r' and is_num(s[1:]):
+ return (TYPE_REG, int(s[1:]))
+ elif s[0] == 'l' and is_num(s[1:]):
+ return (TYPE_LAB, int(s[1:]))
+ else:
+ return None
+
+ def typecheck(self, s):
+ t = gettype(s)
+ if t is None:
+ return None
+ if self == TYPE_VAL:
+ return t[0] == TYPE_REG or t[0] == TYPE_IMM
+ else:
+ return t[0] == self
+
+class Instruction:
+ def __init__(self, opcode, argtypes):
+ self.opcode = opcode
+ assert self.opcode < 0x80 and self.opcode >= 0
+ self.argtypes = argtypes
+ def typecheck(self, sargs):
+ rargs = []
+ if len(sargs) != len(self.argtypes):
+ return None
+ for i in range(0, len(sargs)):
+ if not self.argtypes[i].typecheck(sargs[i]):
+ return None
+ rargs.append(ArgType.gettype(sargs[i]))
+ return rargs
+
+instructions = {
+"NOP" : Instruction(0, []),
+"PUSH" : Instruction(1, [ArgType.TYPE_REG]),
+"POP" : Instruction(2, [ArgType.TYPE_REG]),
+"ADD" : Instruction(3, [ArgType.TYPE_VAL, ArgType.TYPE_VAL, ArgType.TYPE_VAL]),
+"MUL" : Instruction(4, [ArgType.TYPE_VAL, ArgType.TYPE_VAL, ArgType.TYPE_VAL]),
+"DIV" : Instruction(5, [ArgType.TYPE_VAL, ArgType.TYPE_VAL, ArgType.TYPE_VAL]),
+"JL" : Instruction(6, [ArgType.TYPE_LAB, ArgType.TYPE_VAL, ArgType.TYPE_VAL]),
+"CLB" : Instruction(7, [ArgType.TYPE_LAB]),
+"SYS" : Instruction(8, [ArgType.TYPE_VAL])
+}
+
+encoding_types = {
+# start mask A B
+ 2: (0x7F, 0xC0, 7),
+ 3: (0xFFF, 0xE0, 12),
+ 4: (0x1FFFF, 0xF0, 16),
+ 5: (0x3FFFFF, 0xF8, 21),
+ 6: (0x7FFFFFF, 0xFC, 26),
+ 7: (0xFFFFFFFF, 0xFE, 36),
+# A : number of bits in start byte
+# B : Total number of bits excluding high bits
+}
+
+def encode_pseudo_utf8(n, high_bits, to):
+ if to > 8 or to < 0:
+ return None
+ elif to == 1:
+ if n < 0x80:
+ return bytes([n])
+ else:
+ return None
+
+ (maxval, start_byte, n_tot) = encoding_types[to]
+ if n > maxval or high_bits > 15:
+ return None
+ n = n | (high_bits << n_tot)
+ all_bytes = []
+ for i in range(0, to - 1):
+ all_bytes.append(0x80 | (n & 0x3F))
+ n >>= 6
+ all_bytes.append(start_byte | n)
+ return bytes(reversed(all_bytes))
+
+"""
+class Line:
+ def __init__(self, opcode, args):
+ self.opcode = opcode
+ self.args = args
+ def render(self):
+
+class Program:
+ def asm_push_line(self, ins, args):
+ self.asm.append((ins, args))
+
+ def parse_asm_line(self, line):
+ line = line.split(' ')
+ if line[0] not in instructions:
+ raise Exception
+ else:
+ r = instructions[line[0]].typecheck(line[1:])
+ if r is None:
+ raise Exception
+ asm_push_instruction(instructions[line[0]].opcode, r)
+"""