aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2023-04-10 17:30:25 +0300
committerJan Tuomi <jans.tuomi@gmail.com>2023-04-10 17:30:25 +0300
commit56fd37c60eb0d58ed4762340ddc85b74347bcd71 (patch)
treed4d6362cb591ddb9658536d831f8c4433089189f /src
parent16b4fbd209d71bdb1a066bacd03a9ccd1cf3d16c (diff)
Do stuff
Diffstat (limited to 'src')
-rwxr-xr-xsrc/assembler.py38
-rw-r--r--src/assembler_eval.py15
-rw-r--r--src/assembler_ops.py56
-rw-r--r--src/ext_std.py24
-rw-r--r--src/test_fibo.atk1619
5 files changed, 81 insertions, 71 deletions
diff --git a/src/assembler.py b/src/assembler.py
index 8a53a5c..a4ddde4 100755
--- a/src/assembler.py
+++ b/src/assembler.py
@@ -48,11 +48,7 @@ def parse(line: str) -> list[str]:
return list(filter(lambda x: len(x) > 0, result))
# 1st pass, gather labels, set options, eval operations
-
-options: dict[str, str] = {
- "stack_pointer": "6", # RG
- "csr_scratch": "5", # RF
-}
+options = Options()
address: int = 0
for (lineNo, line) in enumerate(src_lines):
@@ -65,11 +61,14 @@ for (lineNo, line) in enumerate(src_lines):
continue
case "@label":
labels[args[0]] = address
+ # todo bugi: 1st pass ei ota monirivisiä käskyjä huomioon
continue
case "@opt":
- opt_name = args[0]
- opt_value = constants.get(args[1], args[1])
- options[opt_name] = opt_value
+ opt_name, opt_value = args
+ match opt_name:
+ case "stack_pointer": options.stack_pointer = opt_value
+ case "csr_scratch": options.csr_scratch = opt_value
+ case _: raise Exception("Unknown @opt: " + opt_name)
case "@use":
module_name, ops = args[0].split(":")
ops_split = ops.split(",")
@@ -86,13 +85,6 @@ for (lineNo, line) in enumerate(src_lines):
# 2nd pass
-# def make_spu(reg: str) -> list[int]:
-# stack_pointer = options["stack_pointer"]
-# reg = eval_symbol(reg)
-# words_inc: list[int] = make_inc(stack_pointer, stack_pointer)
-# words_str: list[int] = make_str(reg, stack_pointer)
-# return words_inc + words_str
-
address: int = 0
nop = bytearray([0b1000_0000, 0])
result = bytearray()
@@ -104,8 +96,12 @@ for (lineNo, line) in enumerate(src_lines):
if line == "": continue
keyword, *args = parse(line.lower())
+ meta = Meta(
+ address=address,
+ options=options
+ )
if keyword in operations:
- words = operations[keyword](address, *args)
+ words = operations[keyword](meta, *args)
else:
match keyword:
# Directives
@@ -122,18 +118,20 @@ for (lineNo, line) in enumerate(src_lines):
except:
raise Exception(f"Invalid assembly at {infile_path}:{lineNo + 1}\n\n{line}")
- if len(result) < 2 * address + 1:
- result.extend((2 * address + 1 - len(result)) * nop)
-
for (label, label_addr) in labels.items():
if address == label_addr:
print(f"{label}:")
+ line_printed = False
for word in words:
- print(f"{address:>08x} 0x{word:>04x} {line}")
+ if len(result) < 2 * address + 1:
+ result.extend((2 * address + 1 - len(result)) * nop)
+
+ print(f"{address:>08x} 0x{word:>04x} {line if not line_printed else '...'}")
result[2 * address + 0] = ((word >> 8) & 0xff)
result[2 * address + 1] = ((word >> 0) & 0xff)
address += 1
+ line_printed = True
with open(outfile_path, "wb") as f:
f.write(result)
diff --git a/src/assembler_eval.py b/src/assembler_eval.py
index 7255572..07f22e7 100644
--- a/src/assembler_eval.py
+++ b/src/assembler_eval.py
@@ -5,8 +5,9 @@ constants: dict[str, str] = {
"rb": "2",
"rc": "3",
"rd": "4",
- "rf": "5",
- "rg": "6",
+ "re": "5",
+ "rf": "6",
+ "rg": "7",
# ALU instructions
"al_plus": "0",
"al_minus": "1",
@@ -25,6 +26,10 @@ constants: dict[str, str] = {
labels: dict[str, int] = {}
+def check_size(bits: int, val: int) -> None:
+ if val >= 2 ** bits:
+ raise Exception(f"Value does not fit in {bits} bits: {val}")
+
def eval_symbol(c: str) -> str:
if c in labels:
return str(labels[c])
@@ -34,6 +39,8 @@ def eval_symbol(c: str) -> str:
return c
-def eval_expr(expr: str) -> int:
+def eval_expr(expr: str, bits: int = 16) -> int:
expr = eval_symbol(expr)
- return eval(expr, labels.copy()) # eval as Python expr
+ ret = eval(expr, labels.copy()) # eval as Python expr
+ check_size(bits, ret)
+ return ret
diff --git a/src/assembler_ops.py b/src/assembler_ops.py
index 0177140..2313bfd 100644
--- a/src/assembler_ops.py
+++ b/src/assembler_ops.py
@@ -3,16 +3,21 @@ from assembler_eval import *
from dataclasses import dataclass
@dataclass
+class Options:
+ stack_pointer = "RG"
+ csr_scratch = "RF"
+
+@dataclass
class Meta:
address: int
- options: dict[str, str]
+ options: Options
def make_alr(meta: Meta, alu_op: str, left: str, right: str, target: str) -> list[int]:
"""ALR 0000 TTTL LLRR RSSS"""
- target_e = eval_expr(target)
- left_e = eval_expr(left)
- right_e = eval_expr(right)
- alu_op_e = eval_expr(alu_op)
+ target_e = eval_expr(target, bits=3)
+ left_e = eval_expr(left, bits=3)
+ right_e = eval_expr(right, bits=3)
+ alu_op_e = eval_expr(alu_op, bits=3)
word = (0b0000 << 12) + \
(target_e << 9) + \
(left_e << 6) + \
@@ -22,12 +27,10 @@ def make_alr(meta: Meta, alu_op: str, left: str, right: str, target: str) -> lis
def make_ali(meta: Meta, alu_op: str, left: str, imm: str, target: str) -> list[int]:
"""ALI 0001 TTTL LLII ISSS"""
- target_e = eval_expr(target)
- left_e = eval_expr(left)
- imm_e = eval_expr(imm)
- if imm_e >= 2**3:
- raise Exception("ALI immediate value does not fit in 3 bits: " + str(imm_e))
- alu_op_e = eval_expr(alu_op)
+ target_e = eval_expr(target, bits=3)
+ left_e = eval_expr(left, bits=3)
+ imm_e = eval_expr(imm, bits=3)
+ alu_op_e = eval_expr(alu_op, bits=3)
word = (0b0001 << 12) + \
(target_e << 9) + \
(left_e << 6) + \
@@ -37,8 +40,8 @@ def make_ali(meta: Meta, alu_op: str, left: str, imm: str, target: str) -> list[
def make_ldr(meta: Meta, to_reg: str, addr_reg: str) -> list[int]:
"""LDR 0010 TTTR RRXX XXXX"""
- to_reg_e = eval_expr(to_reg)
- addr_reg_e = eval_expr(addr_reg)
+ to_reg_e = eval_expr(to_reg, bits=3)
+ addr_reg_e = eval_expr(addr_reg, bits=3)
word = (0b0010 << 12) + \
(to_reg_e << 9) + \
(addr_reg_e << 6)
@@ -46,8 +49,8 @@ def make_ldr(meta: Meta, to_reg: str, addr_reg: str) -> list[int]:
def make_str(meta: Meta, from_reg: str, addr_reg: str) -> list[int]:
"""STR 0011 TTTR RRXX XXXX"""
- from_reg_e = eval_expr(from_reg)
- addr_reg_e = eval_expr(addr_reg)
+ from_reg_e = eval_expr(from_reg, bits=3)
+ addr_reg_e = eval_expr(addr_reg, bits=3)
word = (0b0011 << 12) + \
(from_reg_e << 9) + \
(addr_reg_e << 6)
@@ -55,8 +58,8 @@ def make_str(meta: Meta, from_reg: str, addr_reg: str) -> list[int]:
def make_ldi(meta: Meta, to_reg: str, imm: str) -> list[int]:
"""LDI 0100 TTTI IIII IIII"""
- to_reg_e = eval_expr(to_reg)
- imm_e = eval_expr(imm)
+ to_reg_e = eval_expr(to_reg, bits=3)
+ imm_e = eval_expr(imm, bits=9)
word = (0b0100 << 12) + \
(to_reg_e << 9) + \
imm_e
@@ -64,26 +67,23 @@ def make_ldi(meta: Meta, to_reg: str, imm: str) -> list[int]:
def make_jpr(meta: Meta, addr_reg: str) -> list[int]:
"""JPR 0101 XXXR RRXX XXXX"""
- addr_reg_e = eval_expr(addr_reg)
+ addr_reg_e = eval_expr(addr_reg, bits=3)
word = (0b0101 << 12) + \
(addr_reg_e << 6)
return [word]
def make_jpi(meta: Meta, imm: str) -> list[int]:
"""JPI 0110 XXXI IIII IIII"""
- imm_e = eval_expr(imm)
+ imm_e = eval_expr(imm, bits=9)
imm_e = imm_e - meta.address - 1
- if imm_e >= 2**9:
- raise Exception("JPI relative value does not fit in 9 bits: " + str(imm_e))
-
word = (0b0110 << 12) + \
imm_e
return [word]
def make_brr(meta: Meta, flag_s: str, addr_reg: str) -> list[int]:
"""brr 0111 XFFR RRXX XXXX"""
- flag_s_e = eval_expr(flag_s)
- addr_reg_e = eval_expr(addr_reg)
+ flag_s_e = eval_expr(flag_s, bits=2)
+ addr_reg_e = eval_expr(addr_reg, bits=3)
word = (0b0111 << 12) + \
(flag_s_e << 9) + \
(addr_reg_e << 6)
@@ -91,11 +91,9 @@ def make_brr(meta: Meta, flag_s: str, addr_reg: str) -> list[int]:
def make_bri(meta: Meta, flag_s: str, imm: str) -> list[int]:
"""BRI 1000 XFFI IIII IIII"""
- flag_s_e = eval_expr(flag_s)
- imm_e = eval_expr(imm)
+ flag_s_e = eval_expr(flag_s, bits=2)
+ imm_e = eval_expr(imm, bits=9)
imm_e = imm_e - meta.address - 1
- if imm_e >= 2**9:
- raise Exception("BRI relative value does not fit in 9 bits: " + str(imm_e))
word = (0b1000 << 12) + \
(flag_s_e << 9) + \
imm_e
@@ -103,7 +101,7 @@ def make_bri(meta: Meta, flag_s: str, imm: str) -> list[int]:
def make_lpc(meta: Meta, target: str) -> list[int]:
"""LPC 1001 TTTX XXXX XXXX"""
- target_e = eval_expr(target)
+ target_e = eval_expr(target, bits=3)
word = (0b1001 << 12) + \
(target_e << 9)
return [word]
diff --git a/src/ext_std.py b/src/ext_std.py
index c0a53c1..e78f5cc 100644
--- a/src/ext_std.py
+++ b/src/ext_std.py
@@ -6,6 +6,12 @@ def make_add(meta: Meta, left: str, right: str, target: str) -> list[int]:
def make_sub(meta: Meta, left: str, right: str, target: str) -> list[int]:
return make_alr(meta, "al_minus", left, right, target)
+def make_addi(meta: Meta, left: str, imm: str, target: str) -> list[int]:
+ return make_ali(meta, "al_plus", left, imm, target)
+
+def make_subi(meta: Meta, left: str, imm: str, target: str) -> list[int]:
+ return make_ali(meta, "al_minus", left, imm, target)
+
def make_and(meta: Meta, left: str, right: str, target: str) -> list[int]:
return make_alr(meta, "al_and", left, right, target)
@@ -43,37 +49,39 @@ def make_mov(meta: Meta, from_reg: str, to_reg: str) -> list[int]:
return make_ali(meta, "al_plus", from_reg, "0", to_reg)
def make_spu(meta: Meta, reg: str) -> list[int]:
- sp_reg = meta.options["stack_pointer"]
+ sp_reg = meta.options.stack_pointer
str_word = make_str(meta, reg, sp_reg)
inc_word = make_inc(meta, sp_reg)
return str_word + inc_word
def make_spo(meta: Meta, reg: str) -> list[int]:
- sp_reg = meta.options["stack_pointer"]
+ sp_reg = meta.options.stack_pointer
dec_word = make_dec(meta, sp_reg)
ldr_word = make_ldr(meta, reg, sp_reg)
return dec_word + ldr_word
def make_csr(meta: Meta, addr_reg: str) -> list[int]:
- lpc_word = make_lpc(meta, meta.options["csr_scratch"])
- spu_word = make_spu(meta, meta.options["csr_scratch"])
+ lpc_word = make_lpc(meta, meta.options.csr_scratch)
+ spu_word = make_spu(meta, meta.options.csr_scratch)
jpr_word = make_jpr(meta, addr_reg)
return lpc_word + spu_word + jpr_word
def make_csi(meta: Meta, addr_imm: str) -> list[int]:
- lpc_word = make_lpc(meta, meta.options["csr_scratch"])
- spu_word = make_spu(meta, meta.options["csr_scratch"])
+ lpc_word = make_lpc(meta, meta.options.csr_scratch)
+ spu_word = make_spu(meta, meta.options.csr_scratch)
jpi_word = make_jpi(meta, addr_imm)
return lpc_word + spu_word + jpi_word
def make_rsr(meta: Meta) -> list[int]:
- spo_word = make_spo(meta, meta.options["csr_scratch"])
- jpr_word = make_jpr(meta, meta.options["csr_scratch"])
+ spo_word = make_spo(meta, meta.options.csr_scratch)
+ jpr_word = make_jpr(meta, meta.options.csr_scratch)
return spo_word + jpr_word
operations = {
"add": make_add,
"sub": make_sub,
+ "addi": make_addi,
+ "subi": make_subi,
"and": make_and,
"or": make_or,
"xor": make_xor,
diff --git a/src/test_fibo.atk16 b/src/test_fibo.atk16
index 7f1abb9..a03f14b 100644
--- a/src/test_fibo.atk16
+++ b/src/test_fibo.atk16
@@ -1,9 +1,12 @@
@opt stack_pointer RG
+@opt csr_scratch RF
+
+@use ext_std:*
@label program
; call fibo subroutine with parameter 10
ldi RA 10
- csr fibo
+ csi fibo
hlt
@label fibo
@@ -13,24 +16,21 @@
; return value:
; RA fibo(n) : u16
- spu RB ; prelude
+ spu RB ; prelude
spu RC
- ldi RC 2 ; if n < 2, return n
- sub RA RC RA
+ subi RA 2 RA ; if n < 2, return n
bri f_sign fibo_early
spu RD ; prelude
- spu RE
- ldi RE 1 ; constant 1
ldi RB 0 ; a = 0
ldi RC 1 ; b = 1
@label fibo_loop
add RB RC RD ; v = a + b
mov RC RB ; a = b
mov RD RC ; b = v
- sub RA RE RA ; n -= 1
+ dec RA ; n -= 1
bri f_zero fibo_done ; loop while n > 0
jpi fibo_loop
@@ -39,9 +39,8 @@
spo RB
rsr
@label fibo_done
- ldr RD RA
- spo RE
- spo RD
+ mov RD RA
+ spo RD ; restore registers
spo RC
spo RB
rsr