aboutsummaryrefslogtreecommitdiffstats
path: root/asm/creole.py
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-18 16:05:09 +0000
committerGravatar Peter McGoron 2023-02-18 16:05:09 +0000
commit48827c5b747eca6d56555f69cae37291feb5fcda (patch)
tree063bc21af510fe961a7002678e0cdf9dbb8bc228 /asm/creole.py
parentadd data, remove labels and make jumps absolute (diff)
adjust python assembler to new API
Diffstat (limited to 'asm/creole.py')
-rw-r--r--asm/creole.py78
1 files changed, 57 insertions, 21 deletions
diff --git a/asm/creole.py b/asm/creole.py
index 8bf609a..559d663 100644
--- a/asm/creole.py
+++ b/asm/creole.py
@@ -65,6 +65,24 @@ class Argument:
""" Returns the high bits that the argument would have
in the opcode. """
return int(self.sign) << 1 | (self.at == ArgType.REG)
+ def __call__(self):
+ l = 2 if self.val < 0x80 else None
+ return encode_pseudo_utf8(self.val, self.high_bits(), l)
+
+class StringArgument(Argument):
+ def __init__(self, *args, **kwargs):
+ super().__init__(self, *args, **kwargs)
+ def __bytes__(self):
+ b = bytes()
+ for v in self.val:
+ b = b + Argument(ArgType.IMM, v)()
+ return b
+
+class LabelArgument(Argument):
+ def __init__(self, *args, **kwargs):
+ super().__init__(self, *args, **kwargs)
+ def load_label(self, labels):
+ self.val = labels[val]
class ArgType(Enum):
""" Class denoting the type of an argument to an instruction. """
@@ -78,8 +96,17 @@ class ArgType(Enum):
VAL = 3
""" Type that denotes either immediate values or registers. """
- LAB = 4
- """ Type of labels. """
+ DAT = 4
+ """ Type of data label. """
+
+ STR = 5
+ """ Type of a string of 32 bit integers. """
+
+ LAB = 6
+ """ Type of a label (.name). """
+
+ def is_number(t):
+ return t == ArgType.IMM or t == ArgType.REG
def gettype(s):
""" Parses the type of the argument represented as a string
@@ -97,14 +124,18 @@ class ArgType(Enum):
:return: The Argument object representing the argument.
:raises MalformedArgument:
"""
- if s.isnumeric():
+ if type(s) is list:
+ return StringArgument(ArgType.STR, s)
+ elif s.isnumeric():
return Argument(ArgType.IMM, int(s))
elif s[0] == "-" and s[1:].isnumeric():
return Argument(ArgType.IMM, word_2c(int(s[1:])), True)
elif s[0] == 'r' and s[1:].isnumeric():
return Argument(ArgType.REG, int(s[1:]))
- elif s[0] == 'l' and s[1:].isnumeric():
- return Argument(ArgType.LAB, int(s[1:]))
+ elif s[0] == 'd' and s[1:].isnumeric():
+ return Argument(ArgType.DAT, int(s[1:]))
+ elif s[0] == '.':
+ return Argument(ArgType.LAB, s[1:])
else:
raise MalformedArgument(s)
@@ -168,14 +199,14 @@ class Instruction(Enum):
DIV = 5, "_render_default", ArgType.REG, ArgType.VAL, ArgType.VAL
SDIV = "DIV", "_render_change_args", ArgType.REG, ArgType.VAL, ArgType.VAL
SYS = 6, "_render_default", ArgType.VAL
- CLB = 7, "_render_default", ArgType.LAB
- JL = 8, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
+ JL = 7, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
JLS = "JL", "_render_change_args", ArgType.LAB, ArgType.VAL, ArgType.VAL
- JLE = 9, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
+ JLE = 8, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
JLES = "JLE", "_render_change_args", ArgType.LAB, ArgType.VAL, ArgType.VAL
- JE = 10, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
+ JE = 9, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
J = "JE", "_render_j", ArgType.LAB
- JNE = 11, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
+ JNE = 10, "_render_default", ArgType.LAB, ArgType.VAL, ArgType.VAL
+ DB = 11, "_render_default", ArgType.DAT, ArgType.STR
def __int__(self):
""" Returns the opcode associated with the Instruction.
@@ -244,16 +275,14 @@ class Instruction(Enum):
def _render_change_args(self, args):
for i in range(0,len(args)):
- if args[i].at != ArgType.LAB:
+ if ArgType.is_number(args[i].at):
args[i].sign = True
return Instruction[self.opcode].render(args)
def _render_default(self, args):
b = bytes([self.opcode])
for a in args:
- l = 2 if a.val < 0x80 else None
- bex = encode_pseudo_utf8(a.val, a.high_bits(), l)
- b = b + bex
+ b = b + a()
return b + bytes([0])
encoding_types = {
@@ -314,12 +343,11 @@ class Line:
raise RangeCheckException(a.at,
a.val,
reglen)
- elif a.at == ArgType.LAB:
- if a.val < 0 or a.val >= lablen:
- raise RangeCheckException(a.at,
- a.val,
- reglen)
+ def load_label(self, labels):
+ for a in self.args:
+ if a.at == ArgType.LAB:
+ a.load_label(labels)
def __call__(self):
return self.ins.render(self.args)
@@ -332,10 +360,13 @@ class Program:
self.asm.append(l)
def parse_asm_line(self, line):
- line = line.split()
+ line = line.strip().split()
line[0] = line[0].casefold()
+ if line[0][0] == '.':
+ self.asm.append(line[0][1:])
+ return None
+
try:
- # TODO: is there no better way to do this in Python?
ins = Instruction[line[0].upper()]
except Exception as e:
raise InstructionNotFoundException(line[0])
@@ -349,7 +380,12 @@ class Program:
def __call__(self):
b = bytes()
+ labels = {}
for line in self.asm:
+ if type(line) is str:
+ labels[line] = len(b)
+ continue
+ line.load_label(labels)
b = b + line()
return b