aboutsummaryrefslogtreecommitdiffstats
path: root/asm.py
blob: cd6a94d483ae987d39513ff0f635a7b05d503342 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
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)
"""