start assembler
This commit is contained in:
parent
aa1ed8a06e
commit
a7308280cb
|
@ -21,3 +21,10 @@ The first four bytes determine the type:
|
||||||
All other values are reserved. Overlong values are allowed, and for some
|
All other values are reserved. Overlong values are allowed, and for some
|
||||||
argument values they are necessary. All lines are terminated by a byte
|
argument values they are necessary. All lines are terminated by a byte
|
||||||
of all zeros.
|
of all zeros.
|
||||||
|
|
||||||
|
## Design Philsophy
|
||||||
|
|
||||||
|
Creole is small but not minimal. It is easy to add instructions, and
|
||||||
|
the amount of labels, registers, and stack space can changed at runtime.
|
||||||
|
System calls can be added dynamically, but static instructions that take
|
||||||
|
at most 3 arguments should be hard-coded.
|
||||||
|
|
|
@ -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)
|
||||||
|
"""
|
Loading…
Reference in New Issue