scasm 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/examples/data.scasm +1 -0
- data/examples/loop.scasm +3 -0
- data/examples/macro.scasm +6 -0
- data/examples/readme1.scasm +7 -0
- data/lib/scasm/assembler.rb +32 -53
- data/lib/scasm/version.rb +1 -1
- data/test/test_assembler.rb +0 -20
- metadata +54 -30
data/.gitignore
CHANGED
data/examples/data.scasm
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
data 1, 16, 64, 65535
|
data/examples/loop.scasm
ADDED
data/lib/scasm/assembler.rb
CHANGED
@@ -5,7 +5,7 @@ require 'scasm/value'
|
|
5
5
|
|
6
6
|
module SCASM
|
7
7
|
|
8
|
-
class Assembler <
|
8
|
+
class Assembler < Object
|
9
9
|
def initialize
|
10
10
|
@stmts = []
|
11
11
|
@relocations = []
|
@@ -17,11 +17,13 @@ class Assembler < BasicObject
|
|
17
17
|
|
18
18
|
def assemble
|
19
19
|
resolve_labels
|
20
|
-
io =
|
20
|
+
io = StringIO.new
|
21
21
|
@stmts.each { |stmt| stmt.assemble io }
|
22
22
|
io.string
|
23
23
|
end
|
24
24
|
|
25
|
+
## Statements
|
26
|
+
|
25
27
|
def inst opsym, a, b
|
26
28
|
a = parse_value a
|
27
29
|
b = parse_value b
|
@@ -29,22 +31,25 @@ class Assembler < BasicObject
|
|
29
31
|
end
|
30
32
|
|
31
33
|
def label name
|
32
|
-
|
34
|
+
raise "label names must be strings" unless name.is_a? String
|
33
35
|
@stmts << Label.new(name)
|
34
36
|
end
|
35
37
|
|
36
|
-
def
|
37
|
-
|
38
|
+
def data *words
|
39
|
+
@stmts << Data.new(words)
|
38
40
|
end
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
+
# Add a method for each instruction
|
43
|
+
BASIC_OPCODES.each do |opsym,opcode|
|
44
|
+
define_method(opsym) { |a,b| inst opsym, a, b }
|
42
45
|
end
|
43
46
|
|
44
|
-
|
45
|
-
|
47
|
+
EXTENDED_OPCODES.each do |opsym,opcode|
|
48
|
+
define_method(opsym) { |a| inst opsym, a, nil }
|
46
49
|
end
|
47
50
|
|
51
|
+
## Values
|
52
|
+
|
48
53
|
def pop
|
49
54
|
Pop.new
|
50
55
|
end
|
@@ -69,32 +74,6 @@ class Assembler < BasicObject
|
|
69
74
|
O.new
|
70
75
|
end
|
71
76
|
|
72
|
-
def imem imm
|
73
|
-
ImmediateMemory.new imm
|
74
|
-
end
|
75
|
-
|
76
|
-
def imm imm
|
77
|
-
Immediate.new imm
|
78
|
-
end
|
79
|
-
|
80
|
-
def l name
|
81
|
-
::Kernel.raise "label names must be strings" unless name.is_a? ::String
|
82
|
-
ImmediateLabel.new(name).tap { |x| @relocations << x }
|
83
|
-
end
|
84
|
-
|
85
|
-
def data *words
|
86
|
-
@stmts << Data.new(words)
|
87
|
-
end
|
88
|
-
|
89
|
-
# Add a method for each instruction
|
90
|
-
BASIC_OPCODES.each do |opsym,opcode|
|
91
|
-
define_method(opsym) { |a,b| inst opsym, a, b }
|
92
|
-
end
|
93
|
-
|
94
|
-
EXTENDED_OPCODES.each do |opsym,opcode|
|
95
|
-
define_method(opsym) { |a| inst opsym, a, nil }
|
96
|
-
end
|
97
|
-
|
98
77
|
# Add a constant for each register
|
99
78
|
REGISTERS.each do |regsym,regnum|
|
100
79
|
const_set regsym, regsym
|
@@ -124,41 +103,41 @@ private
|
|
124
103
|
end
|
125
104
|
|
126
105
|
@relocations.each do |x|
|
127
|
-
addr = label_addrs[x.name] or
|
106
|
+
addr = label_addrs[x.name] or raise "undefined label #{x.name.inspect}"
|
128
107
|
x.resolve addr
|
129
108
|
end
|
130
109
|
end
|
131
110
|
|
132
|
-
#
|
111
|
+
# Create explicit Values from the shorthand syntax
|
133
112
|
def parse_value x
|
134
113
|
case x
|
135
|
-
when Value,
|
114
|
+
when Value, NilClass
|
136
115
|
x
|
137
|
-
when
|
116
|
+
when Array
|
138
117
|
x1, x2, = x
|
139
|
-
if x1.is_a?
|
118
|
+
if x1.is_a? Symbol and x2 == nil
|
140
119
|
# [reg]
|
141
|
-
|
142
|
-
elsif x1.is_a?
|
120
|
+
RegisterMemory.new x1
|
121
|
+
elsif x1.is_a? Symbol and x2.is_a? Integer
|
143
122
|
# [reg, imm]
|
144
|
-
|
145
|
-
elsif x1.is_a?
|
123
|
+
OffsetRegisterMemory.new x1, x2
|
124
|
+
elsif x1.is_a? Integer
|
146
125
|
# [imm]
|
147
|
-
|
126
|
+
ImmediateMemory.new x1
|
148
127
|
else
|
149
|
-
|
128
|
+
fail "invalid memory access syntax"
|
150
129
|
end
|
151
|
-
when
|
130
|
+
when Symbol
|
152
131
|
# register
|
153
|
-
|
154
|
-
when
|
132
|
+
Register.new x
|
133
|
+
when String
|
155
134
|
# label
|
156
|
-
|
157
|
-
when
|
135
|
+
ImmediateLabel.new(x).tap { |v| @relocations << v }
|
136
|
+
when Integer
|
158
137
|
# immediate
|
159
|
-
|
138
|
+
Immediate.new x
|
160
139
|
else
|
161
|
-
|
140
|
+
raise "unexpected value class #{x.class}"
|
162
141
|
end
|
163
142
|
end
|
164
143
|
end
|
data/lib/scasm/version.rb
CHANGED
data/test/test_assembler.rb
CHANGED
@@ -34,13 +34,6 @@ class AssemblerTest < Test::Unit::TestCase
|
|
34
34
|
0x1c61,
|
35
35
|
]
|
36
36
|
|
37
|
-
check <<-EOS
|
38
|
-
set reg(A), reg(B)
|
39
|
-
set reg(C), reg(X)
|
40
|
-
set reg(Y), reg(Z)
|
41
|
-
set reg(I), reg(J)
|
42
|
-
EOS
|
43
|
-
|
44
37
|
check <<-EOS
|
45
38
|
set A, B
|
46
39
|
set C, X
|
@@ -51,13 +44,11 @@ class AssemblerTest < Test::Unit::TestCase
|
|
51
44
|
|
52
45
|
def test_regmem
|
53
46
|
expect [0x0cb1]
|
54
|
-
check "set regmem(X), reg(X)"
|
55
47
|
check "set [X], X"
|
56
48
|
end
|
57
49
|
|
58
50
|
def test_iregmem
|
59
51
|
expect [0x0d31, 0x002a]
|
60
|
-
check 'set iregmem(X, 42), reg(X)'
|
61
52
|
check 'set [X,42], X'
|
62
53
|
end
|
63
54
|
|
@@ -83,21 +74,17 @@ class AssemblerTest < Test::Unit::TestCase
|
|
83
74
|
|
84
75
|
def test_imem
|
85
76
|
expect [0x7801, 0x1000]
|
86
|
-
check 'set reg(A), imem(0x1000)'
|
87
77
|
check 'set A, [0x1000]'
|
88
78
|
end
|
89
79
|
|
90
80
|
def test_imm
|
91
81
|
expect [0xfc01]
|
92
|
-
check "set reg(A), imm(31)"
|
93
82
|
check "set A, 31"
|
94
83
|
|
95
84
|
expect [0x7c01, 0x0020]
|
96
|
-
check "set reg(A), imm(32)"
|
97
85
|
check "set A, 32"
|
98
86
|
|
99
87
|
expect [0x7df1, 0xffff, 0x0020]
|
100
|
-
check "set imm(65535), imm(32)"
|
101
88
|
check "set 65535, 32"
|
102
89
|
end
|
103
90
|
|
@@ -108,13 +95,6 @@ class AssemblerTest < Test::Unit::TestCase
|
|
108
95
|
0x7dc1, 0x0001,
|
109
96
|
]
|
110
97
|
|
111
|
-
check <<-EOS
|
112
|
-
set reg(A), imm(13)
|
113
|
-
label 'loop'
|
114
|
-
add reg(A), imm(1)
|
115
|
-
set pc, l('loop')
|
116
|
-
EOS
|
117
|
-
|
118
98
|
check <<-EOS
|
119
99
|
set A, 13
|
120
100
|
label 'loop'
|
metadata
CHANGED
@@ -1,36 +1,47 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: scasm
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Rich Lane
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-04-05 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: trollop
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
22
32
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
email:
|
33
|
+
version_requirements: *id001
|
34
|
+
description: ""
|
35
|
+
email:
|
27
36
|
- rlane@club.cc.cmu.edu
|
28
|
-
executables:
|
37
|
+
executables:
|
29
38
|
- scasm
|
30
39
|
- scasm-disassemble
|
31
40
|
extensions: []
|
41
|
+
|
32
42
|
extra_rdoc_files: []
|
33
|
-
|
43
|
+
|
44
|
+
files:
|
34
45
|
- .gitignore
|
35
46
|
- Gemfile
|
36
47
|
- LICENSE
|
@@ -38,6 +49,10 @@ files:
|
|
38
49
|
- Rakefile
|
39
50
|
- bin/scasm
|
40
51
|
- bin/scasm-disassemble
|
52
|
+
- examples/data.scasm
|
53
|
+
- examples/loop.scasm
|
54
|
+
- examples/macro.scasm
|
55
|
+
- examples/readme1.scasm
|
41
56
|
- examples/spec.scasm
|
42
57
|
- lib/scasm/assembler.rb
|
43
58
|
- lib/scasm/isa.rb
|
@@ -49,28 +64,37 @@ files:
|
|
49
64
|
- test/test_assembler.rb
|
50
65
|
homepage: https://github.com/rlane/scasm
|
51
66
|
licenses: []
|
67
|
+
|
52
68
|
post_install_message:
|
53
69
|
rdoc_options: []
|
54
|
-
|
70
|
+
|
71
|
+
require_paths:
|
55
72
|
- lib
|
56
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
74
|
none: false
|
58
|
-
requirements:
|
59
|
-
- -
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
|
62
|
-
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
hash: 3
|
79
|
+
segments:
|
80
|
+
- 0
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
83
|
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
68
91
|
requirements: []
|
92
|
+
|
69
93
|
rubyforge_project:
|
70
94
|
rubygems_version: 1.8.17
|
71
95
|
signing_key:
|
72
96
|
specification_version: 3
|
73
97
|
summary: A Ruby DSL for DCPU-16 assembly code
|
74
|
-
test_files:
|
98
|
+
test_files:
|
75
99
|
- test/foo.scasm
|
76
100
|
- test/test_assembler.rb
|