summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--asm.py154
-rw-r--r--r1b.txt70
-rw-r--r--test.r167
3 files changed, 291 insertions, 0 deletions
diff --git a/asm.py b/asm.py
new file mode 100644
index 0000000..7a20f8b
--- /dev/null
+++ b/asm.py
@@ -0,0 +1,154 @@
+mnems = """
+nop
+rot
+nrt
+dup
+swp
+ovr
+drp
+tck
+nip
+equ
+neq
+add
+sub
+mul
+div
+neg
+slt
+ult
+sle
+ule
+lod
+sto
+psh
+pop
+""".split()
+mnems.extend(['???']*(64-len(mnems)))
+def opws(kw):
+ for k in range(16):
+ mnems.append(kw + str(k))
+opws("mark") # who is mark
+opws("loc")
+opws("ret")
+opws("lit")
+
+# print(mnems)
+import sys
+
+import collections
+
+pc = 0
+labels = {}
+local_labels = {}
+# map of labelname -> (dest, ifn)
+label_wants = collections.defaultdict(set)
+local_label_wants = collections.defaultdict(set)
+output = bytearray()
+
+class Wrong(Exception):
+ def __init__(self, lineno, msg):
+ self.lineno = lineno
+ self.msg = msg
+ def __str__(self):
+ return f"{self.lineno}: {self.msg}"
+
+def assemble_line(args, lineno):
+
+ match args:
+ case ["c", label] if label in labels:
+ emit_call(labels[label])
+ case ["c", label]:
+ label_wants[label].add((pc,call_instr))
+ emit(0)
+ case ['b', label] if label in local_labels:
+ emit_obranch(local_labels[label])
+ case ['b', label]:
+ local_label_wants[label].add((pc, obranch_instr))
+ case ['j', label] if label in local_labels:
+ emit_jump(local_labels[label])
+ case ['j', label]:
+ local_label_wants[label].add((pc, jump_instr))
+
+ case ["i", i1]:
+ assemble_line(["i", i1, "nop"], lineno)
+ case ["i", i1, i2]:
+ opc1 = mnems.index(i1)
+ opc2 = mnems.index(i2)
+ emit_instrs(opc1, opc2)
+ case ["l", val]:
+ emit_lit(int(val))
+ case [':', label]:
+ if label in labels:
+ raise Wrong(lineno, "label defined twice "+label)
+ labels[label] = pc
+ for (dest, ifn) in label_wants[label]:
+ put_at(dest, ifn(pc, dest))
+ del label_wants[label]
+
+ local_labels.clear()
+ for u,v in local_label_wants.items():
+ raise Wrong(lineno, "unfulfilled local label "+u)
+ local_label_wants.clear()
+
+ case ['%', label]:
+ if label in local_labels:
+ raise Wrong(lineno, "local label defined twice "+label)
+ local_labels[label] = pc
+ for (dest, ifn) in local_label_wants[label]:
+ put_at(dest, ifn(pc, dest))
+ del local_label_wants[label]
+
+ case []: pass
+
+
+ case _:
+ raise Wrong(lineno, "unknown wordtype")
+
+def emit_call(addr):
+ emit(call_instr(addr))
+def emit_instrs(opc1, opc2):
+ emit(instrs_instr(opc1, opc2))
+def emit_lit(val):
+ emit(lit_instr(val))
+def emit_obranch(addr):
+ emit(obranch_instr(addr, origin=pc))
+def emit_jump(addr):
+ emit(jump_instr(addr, origin=pc))
+
+def emit(word):
+ output.extend(word.to_bytes(2))
+ global pc
+ pc += 2
+
+def put_at(addr, word):
+ output[addr:addr+1] = word.to_bytes(2)
+
+def lit_instr(val):
+ return (val&0b1111111111111) | 0b0110000000000000
+def instrs_instr(opc1, opc2):
+ return (opc1 << 7) | opc2
+def call_instr(addr,*_):
+ return (addr>>1)|0b1000000000000000
+def obranch_instr(target, origin):
+ rel = target - origin + 2048
+ return (rel&0b111111111111)|0b0101000000000000
+def jump_instr(target, origin):
+ rel = target - origin + 2048
+ return (rel&0b111111111111)|0b0100000000000000
+
+
+
+
+import sys
+def main():
+ for ix, line in enumerate(sys.stdin):
+ line = line.strip()
+ args = line.split()
+ assemble_line(args, ix+1)
+
+ for u,v in label_wants.items():
+ print("unfulfilled global label",u, file=sys.stderr)
+ sys.stdout.buffer.write(output)
+
+if __name__ == "__main__": main()
diff --git a/r1b.txt b/r1b.txt
new file mode 100644
index 0000000..7baa9c8
--- /dev/null
+++ b/r1b.txt
@@ -0,0 +1,70 @@
+nop
+rot (abc-bca)
+-rot (abc-cab)
+dup (x-xx)
+swap (xy-yx)
+over (xy-xyx)
+drop (xy-x)
+tuck (xy-yxy)
+nip (xy-y)
+lit (-l)
+equal (xy-f)
+nequal (xy-f)
+add (xy-z)
+sub (xy-z)
+mul
+div
+neg
+slt
+ult
+sle
+ule
+lod (a-d)
+sto (da-)
+push
+pop
+
+
+
+what abotu either
+
+1[addr:15] : call
+0
+01 literal
+
+
+want:
+calls (15 bits)
+j, cj, relative addr, 8 bits
+lit, 4 or 8 or 16 bits
+mark,loc,ret, + 4bit arg
+regular op, no arg (between 16 and 32 of these)
+
+CALL (addr:15)
+or
+JMP (cond?:1) (rdst:rest)
+or
+(mark/loc/ret/lit4) (arg:4)
+or
+
+regular op (7 bits)
+
+
+
+OPW:7: 1 T:2 arg:4
+OPR:7: 0 opcode:6
+ 00 - 3f regular opcodes (64 of them)
+ 4x mark x
+ 5x loc x
+ 6x ret x
+ 7x lit4 x
+
+I: 0 0 (OPW|OPR) (OPW|OPR)
+J: 0 1 0 cond? raddr:12
+L: 0 1 1 value:13
+C: 1 addr:15
+
+
+
+
+
diff --git a/test.r1 b/test.r1
new file mode 100644
index 0000000..8a51d81
--- /dev/null
+++ b/test.r1
@@ -0,0 +1,67 @@
+: sqrt
+i mark2 dup
+i loc0 sto
+c /2
+i loc1 sto
+% loop
+i loc0 lod
+i loc1 lod
+c newton
+i dup loc1
+c replace!
+c thresh
+c close?
+b loop
+i loc1 lod
+i ret2
+
+: newton
+c tuck
+c square
+i add div
+c /2
+i ret0
+
+: square
+i dup mul
+i ret0
+: tuck
+i dup nrt
+i ret0
+
+: replace!
+i dup lod
+i nrt sto
+i ret0
+
+: close?
+i nrt
+c absdiff
+i swp sle
+i ret0
+
+: /2
+i lit2 div
+i ret0
+
+: thresh
+i lit4 ret0
+
+: absdiff
+i sub
+
+: abs
+i lit0 slt
+b f1
+i neg
+% f1
+i ret0
+
+
+: hypot
+c square
+i swp
+c square
+i add
+c sqrt
+i ret0