From cfcc77e723ccb9aa023e35d3d0172161d4907bed Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Fri, 27 Dec 2019 16:49:08 -0500 Subject: Implement syntax for address/label dereferencing. --- asm.myr | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/asm.myr b/asm.myr index dda4eed..250f242 100644 --- a/asm.myr +++ b/asm.myr @@ -40,6 +40,8 @@ type literal = union `Number int `Register int `Label byte[:] + `DerefAddr int + `DerefLabel byte[:] `Invalid ;; @@ -48,16 +50,23 @@ const getnum = {s } const parselit = {s - if s[0] == ('#' : byte) + if s.len < 1 + -> `Invalid + elif s[0] == ('#' : byte) match getnum(s) |`std.Some(n): -> `Number(n) |`std.None: -> `Invalid ;; - elif s[0] == ('v' : byte) + elif s[0] == ('v' : byte) || s[0] == ('V' : byte) match getnum(s) |`std.Some(n): -> `Register(n) |`std.None: -> `Invalid ;; + elif s[0] == ('[' : byte) + match getnum(s[:s.len-1]) + |`std.Some(n): -> `DerefAddr(n) + |`std.None: -> `DerefLabel(s[:s.len-1]) + ;; else -> `Label(s) ;; @@ -82,25 +91,42 @@ const emitinstr = {p ;; match parselit(p[1]) | `Number(n): b = `std.Some([0x00 | (n & 0x0f00), (n & 0xff)]) - | `Label(l): b = `std.Some([0x20, 0x00]) + | `Label(l): b = `std.Some([0x00, 0x00]) mark = `std.Some(strdup(l)) - | `Register(_): - -> `std.Err("SYS called with register instruction") - | `Invalid: - -> `std.Err(std.fmt("invalid literal {}", p[1])) + | _: + -> `std.Err(std.fmt("invalid argument to SYS: {}", p[1])) ;; | "CALL": if p.len < 2 -> `std.Err("CALL missing subroutine address") ;; match parselit(p[1]) - | `Number(n): b = `std.Some([0x00 | (n & 0x0f00), (n & 0xff)]) + | `Number(n): b = `std.Some([0x20 | (n & 0x0f00), (n & 0xff)]) | `Label(l): b = `std.Some([0x20, 0x00]) mark = `std.Some(strdup(l)) - | `Register(_): - -> `std.Err("CALL called with register instruction") - | `Invalid: - -> `std.Err(std.fmt("invalid literal {}", p[1])) + | _: + -> `std.Err(std.fmt("invalid argument to CALL: {}", p[1])) + ;; + | "JP": + if p.len < 2 + -> `std.Err("JP missing address") + elif p.len == 2 + match parselit(p[1]) + | `Number(n): b = `std.Some([0x10 | (n & 0x0f00), (n & 0xff)]) + | `Label(l): b = `std.Some([0x10, 0x00]) + mark = `std.Some(strdup(l)) + | _: + -> `std.Err(std.fmt("invalid argument to JP: {}", p[1])) + ;; + else + match (parselit(p[1]), parselit(p[2])) + | (`Register(0), `Number(n)): + b = `std.Some([0xb0 | (n & 0x0f00), (n & 0xff)]) + | (`Register(0), `Label(l)): b = `std.Some([0xb0, 0x00]) + mark = `std.Some(strdup(l)) + | _: + -> `std.Err(std.fmt("invalid arguments to JP: {}, {}", p[1], p[2])) + ;; ;; | _: -> `std.Err("unrecognized instruction") -- cgit v1.3