summaryrefslogtreecommitdiff
path: root/asm.myr
diff options
context:
space:
mode:
authorJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2019-12-27 16:49:08 -0500
committerJakob L. Kreuze <zerodaysfordays@sdf.lonestar.org>2019-12-27 17:00:18 -0500
commitcfcc77e723ccb9aa023e35d3d0172161d4907bed (patch)
tree5f01a8a0a9e7461505e753a2e26ecd1b43bb11e3 /asm.myr
parentdcc1eec086c8f66c623394325f69eadb29c3a917 (diff)
Implement syntax for address/label dereferencing.
Diffstat (limited to 'asm.myr')
-rw-r--r--asm.myr50
1 files 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")