summaryrefslogtreecommitdiff
path: root/asm.rb
diff options
context:
space:
mode:
authorJulian Blake Kongslie2021-03-29 13:59:45 -0700
committerJulian Blake Kongslie2021-03-29 13:59:45 -0700
commit135fbf911740e88b802d340fe3e747dd39966ec4 (patch)
tree9f3bf2b39e4b71ca4169ccb45f332b1a33551887 /asm.rb
parentTrivial cleanup of initial memory image. (diff)
downloadnoncpu-135fbf911740e88b802d340fe3e747dd39966ec4.tar.xz
Trivial assembler.
Diffstat (limited to '')
-rwxr-xr-xasm.rb64
1 files changed, 64 insertions, 0 deletions
diff --git a/asm.rb b/asm.rb
new file mode 100755
index 0000000..9ba1e04
--- /dev/null
+++ b/asm.rb
@@ -0,0 +1,64 @@
1#!/usr/bin/ruby -w
2
3OPCODES = {
4 "acc=" => 0x000,
5 "load" => 0x100,
6 "store" => 0x200,
7 "ifeq" => 0x300,
8 "jmp" => 0x400,
9 "++acc" => 0xf01,
10 "--acc" => 0xf02,
11 "++idx" => 0xf04,
12 "--idx" => 0xf08,
13 "swap" => 0xf10,
14 "idx" => 0xf20,
15 "tx" => 0xf40,
16 "halt" => 0xf80,
17 }
18
19Line = Struct.new(:opcode, :refs, :code)
20
21$labels = {}
22$code = []
23ARGF.each_line() do | line |
24 line.chomp!()
25 next unless line =~ /\S/
26 op = 0x000
27 refs = []
28 line.scan(/\S+/).each() do | word |
29 if word =~ /^0(\d+)$/
30 op |= $1.to_i(8)
31 elsif word =~ /^-0(\d+)$/
32 op |= 0x100 - $1.to_i(8)
33 elsif word =~ /^(\d+)$/
34 op |= $1.to_i(10)
35 elsif word =~ /^-(\d+)$/
36 op |= 0x100 - $1.to_i(10)
37 elsif word =~ /^0x([0-9a-f]+)$/i
38 op |= $1.to_i(16)
39 elsif word =~ /^-0x([0-9a-f]+)$/i
40 op |= 0x100 - $1.to_i(16)
41 elsif OPCODES.key?(word)
42 op |= OPCODES[word]
43 elsif word =~ /^(.+):$/
44 $labels[$1] = $code.size()
45 else
46 refs << word
47 end
48 end
49 $code << Line.new(op, refs, line)
50end
51
52$code.each_with_index() do | line, i |
53 op = line.opcode
54 line.refs.each() do | ref |
55 if $labels.key?(ref)
56 target = $labels[ref] - (i + 1)
57 target += 0x100 if target < 0
58 op |= target
59 else
60 throw "I don't understand #{ref.inspect()}"
61 end
62 end
63 $stdout.write("#{op.to_s(16).rjust(3, "0")} // #{line.code}\n")
64end