rasl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.org +221 -0
- data/Rakefile +6 -0
- data/bin/rasl +3 -0
- data/examples/fnumb.casl +22 -0
- data/examples/fnumb.map +20 -0
- data/examples/hanoi.casl +48 -0
- data/examples/hanoi.map +61 -0
- data/examples/hanoi.rb +124 -0
- data/examples/hello.casl +6 -0
- data/examples/hello.map +14 -0
- data/examples/hello.rb +41 -0
- data/examples/in_out.casl +17 -0
- data/examples/in_out.map +62 -0
- data/examples/run_all.sh +2 -0
- data/examples/sum.casl +7 -0
- data/examples/sum.map +7 -0
- data/examples/sum.rb +27 -0
- data/examples/swap.casl +8 -0
- data/examples/swap.map +6 -0
- data/examples/utf8.casl +2 -0
- data/examples/utf8.map +4 -0
- data/lib/rasl.rb +1657 -0
- data/lib/rasl/version.rb +3 -0
- data/rasl.gemspec +29 -0
- data/spec/rasl_spec.rb +700 -0
- data/spec/spec_helper.rb +11 -0
- metadata +163 -0
data/examples/hello.casl
ADDED
data/examples/hello.map
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
0000 7001 0000 PUSH #0000, GR1
|
2
|
+
0002 7002 0000 PUSH #0000, GR2
|
3
|
+
0004 1210 000D LAD GR1, #000D
|
4
|
+
0006 1220 0012 LAD GR2, #0012
|
5
|
+
0008 F000 0001 SVC #0001
|
6
|
+
000A 7120 POP GR2
|
7
|
+
000B 7110 POP GR1
|
8
|
+
000C 8100 RET
|
9
|
+
000D 0048 DC 72 ; 'H'
|
10
|
+
000E 0065 DC 101 ; 'e'
|
11
|
+
000F 006C DC 108 ; 'l'
|
12
|
+
0010 006C DC 108 ; 'l'
|
13
|
+
0011 006F DC 111 ; 'o'
|
14
|
+
0012 0005 DC 5
|
data/examples/hello.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "../lib/rasl"
|
2
|
+
|
3
|
+
app = Rasl::Processor.new
|
4
|
+
app.assemble <<-SOURCE
|
5
|
+
; Hello, world.
|
6
|
+
MAIN START
|
7
|
+
OUT STR, LEN
|
8
|
+
RET
|
9
|
+
STR DC 'Hello, world.'
|
10
|
+
LEN DC 13
|
11
|
+
SOURCE
|
12
|
+
puts app.disassemble
|
13
|
+
app.go
|
14
|
+
app.code_dump
|
15
|
+
# >> 0000 7001 0000 PUSH #0000, GR1
|
16
|
+
# >> 0002 7002 0000 PUSH #0000, GR2
|
17
|
+
# >> 0004 1210 000D LAD GR1, #000D
|
18
|
+
# >> 0006 1220 001A LAD GR2, #001A
|
19
|
+
# >> 0008 F000 0001 SVC #0001
|
20
|
+
# >> 000A 7120 POP GR2
|
21
|
+
# >> 000B 7110 POP GR1
|
22
|
+
# >> 000C 8100 RET
|
23
|
+
# >> 000D 0048 DC 72 ; 'H'
|
24
|
+
# >> 000E 0065 DC 101 ; 'e'
|
25
|
+
# >> 000F 006C DC 108 ; 'l'
|
26
|
+
# >> 0010 006C DC 108 ; 'l'
|
27
|
+
# >> 0011 006F DC 111 ; 'o'
|
28
|
+
# >> 0012 002C DC 44 ; ','
|
29
|
+
# >> 0013 0020 DC 32 ; ' '
|
30
|
+
# >> 0014 0077 DC 119 ; 'w'
|
31
|
+
# >> 0015 006F DC 111 ; 'o'
|
32
|
+
# >> 0016 0072 DC 114 ; 'r'
|
33
|
+
# >> 0017 006C DC 108 ; 'l'
|
34
|
+
# >> 0018 0064 DC 100 ; 'd'
|
35
|
+
# >> 0019 002E DC 46 ; '.'
|
36
|
+
# >> 001A 000D DC 13
|
37
|
+
# >> Hello, world.
|
38
|
+
# >> 0000: 7001 0000 7002 0000 1210 000D 1220 001A ........
|
39
|
+
# >> 0008: F000 0001 7120 7110 8100 0048 0065 006C .....Hel
|
40
|
+
# >> 0010: 006C 006F 002C 0020 0077 006F 0072 006C lo, worl
|
41
|
+
# >> 0018: 0064 002E 000D d..
|
data/examples/in_out.map
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
0000 7001 0000 PUSH #0000, GR1
|
2
|
+
0002 7002 0000 PUSH #0000, GR2
|
3
|
+
0004 1210 0061 LAD GR1, #0061
|
4
|
+
0006 1220 0065 LAD GR2, #0065
|
5
|
+
0008 F000 0000 SVC #0000
|
6
|
+
000A 7120 POP GR2
|
7
|
+
000B 7110 POP GR1
|
8
|
+
000C 7001 0000 PUSH #0000, GR1
|
9
|
+
000E 7002 0000 PUSH #0000, GR2
|
10
|
+
0010 1210 0061 LAD GR1, #0061
|
11
|
+
0012 1220 0065 LAD GR2, #0065
|
12
|
+
0014 F000 0001 SVC #0001
|
13
|
+
0016 7120 POP GR2
|
14
|
+
0017 7110 POP GR1
|
15
|
+
0018 7001 0000 PUSH #0000, GR1
|
16
|
+
001A 7002 0000 PUSH #0000, GR2
|
17
|
+
001C 1210 0061 LAD GR1, #0061
|
18
|
+
001E 1220 0065 LAD GR2, #0065
|
19
|
+
0020 F000 0000 SVC #0000
|
20
|
+
0022 7120 POP GR2
|
21
|
+
0023 7110 POP GR1
|
22
|
+
0024 7001 0000 PUSH #0000, GR1
|
23
|
+
0026 7002 0000 PUSH #0000, GR2
|
24
|
+
0028 1210 0061 LAD GR1, #0061
|
25
|
+
002A 1220 0065 LAD GR2, #0065
|
26
|
+
002C F000 0001 SVC #0001
|
27
|
+
002E 7120 POP GR2
|
28
|
+
002F 7110 POP GR1
|
29
|
+
0030 7001 0000 PUSH #0000, GR1
|
30
|
+
0032 7002 0000 PUSH #0000, GR2
|
31
|
+
0034 1210 0061 LAD GR1, #0061
|
32
|
+
0036 1220 0065 LAD GR2, #0065
|
33
|
+
0038 F000 0000 SVC #0000
|
34
|
+
003A 7120 POP GR2
|
35
|
+
003B 7110 POP GR1
|
36
|
+
003C 7001 0000 PUSH #0000, GR1
|
37
|
+
003E 7002 0000 PUSH #0000, GR2
|
38
|
+
0040 1210 0061 LAD GR1, #0061
|
39
|
+
0042 1220 0065 LAD GR2, #0065
|
40
|
+
0044 F000 0001 SVC #0001
|
41
|
+
0046 7120 POP GR2
|
42
|
+
0047 7110 POP GR1
|
43
|
+
0048 7001 0000 PUSH #0000, GR1
|
44
|
+
004A 7002 0000 PUSH #0000, GR2
|
45
|
+
004C 1210 0061 LAD GR1, #0061
|
46
|
+
004E 1220 0065 LAD GR2, #0065
|
47
|
+
0050 F000 0000 SVC #0000
|
48
|
+
0052 7120 POP GR2
|
49
|
+
0053 7110 POP GR1
|
50
|
+
0054 7001 0000 PUSH #0000, GR1
|
51
|
+
0056 7002 0000 PUSH #0000, GR2
|
52
|
+
0058 1210 0061 LAD GR1, #0061
|
53
|
+
005A 1220 0065 LAD GR2, #0065
|
54
|
+
005C F000 0001 SVC #0001
|
55
|
+
005E 7120 POP GR2
|
56
|
+
005F 7110 POP GR1
|
57
|
+
0060 8100 RET
|
58
|
+
0061 0000 DC 0
|
59
|
+
0062 0000 DC 0
|
60
|
+
0063 0000 DC 0
|
61
|
+
0064 0000 DC 0
|
62
|
+
0065 0000 DC 0
|
data/examples/run_all.sh
ADDED
data/examples/sum.casl
ADDED
data/examples/sum.map
ADDED
data/examples/sum.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "../lib/rasl"
|
3
|
+
|
4
|
+
app = Rasl::Processor.new
|
5
|
+
app.assemble <<-SOURCE
|
6
|
+
MAIN START
|
7
|
+
LD GR0,=1
|
8
|
+
LD GR1,=2
|
9
|
+
ADDA GR0,GR1
|
10
|
+
ST GR0,RESULT
|
11
|
+
RET
|
12
|
+
RESULT DS 1
|
13
|
+
END
|
14
|
+
SOURCE
|
15
|
+
app.go
|
16
|
+
app.gr[:gr0].value # => 3
|
17
|
+
app.labels["MAIN"] # => {"RESULT"=>8}
|
18
|
+
app.memory[app.labels["MAIN"]["RESULT"]] # => 3
|
19
|
+
puts app.disassemble
|
20
|
+
# >> 0000 1000 0009 LD GR0, #0009
|
21
|
+
# >> 0002 1010 000A LD GR1, #000A
|
22
|
+
# >> 0004 2401 ADDA GR0, GR1
|
23
|
+
# >> 0005 1100 0008 ST GR0, #0008
|
24
|
+
# >> 0007 8100 RET
|
25
|
+
# >> 0008 0003 DC 3
|
26
|
+
# >> 0009 0001 DC 1
|
27
|
+
# >> 000A 0002 DC 2
|
data/examples/swap.casl
ADDED
data/examples/swap.map
ADDED
data/examples/utf8.casl
ADDED
data/examples/utf8.map
ADDED
data/lib/rasl.rb
ADDED
@@ -0,0 +1,1657 @@
|
|
1
|
+
# CASL Assembler / Simulator
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'pathname'
|
5
|
+
require 'readline'
|
6
|
+
require 'kconv'
|
7
|
+
|
8
|
+
require 'active_support/core_ext/string'
|
9
|
+
require 'active_support/configurable'
|
10
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
11
|
+
require 'active_support/hash_with_indifferent_access'
|
12
|
+
|
13
|
+
require 'active_model'
|
14
|
+
|
15
|
+
require_relative 'rasl/version'
|
16
|
+
|
17
|
+
module Rasl
|
18
|
+
include ActiveSupport::Configurable
|
19
|
+
|
20
|
+
config.spec = 2
|
21
|
+
config.bit = 16
|
22
|
+
config.memory_size = 65536
|
23
|
+
config.disassemble_rows = 8
|
24
|
+
config.ds_init_value = 0
|
25
|
+
config.memory_defval = 0
|
26
|
+
config.bol_order = false # 最初から命令を書けるか?
|
27
|
+
config.dump_cols = 8
|
28
|
+
config.dump_rows = 4
|
29
|
+
|
30
|
+
END_OF_FILE = -1
|
31
|
+
|
32
|
+
class RaslError < StandardError
|
33
|
+
def message
|
34
|
+
[super, current_file_line].compact.join("\n")
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def current_file_line
|
40
|
+
if Rasl::Parser.line_count
|
41
|
+
if ARGF.filename == '-'
|
42
|
+
path = '<STDIN>'
|
43
|
+
else
|
44
|
+
path = ARGF.path
|
45
|
+
end
|
46
|
+
|
47
|
+
path_line = "#{path}:#{Rasl::Parser.line_count}: "
|
48
|
+
|
49
|
+
to = Rasl::Parser.scanner.pointer
|
50
|
+
Rasl::Parser.scanner.unscan rescue nil
|
51
|
+
from = Rasl::Parser.scanner.pointer
|
52
|
+
padding = ' ' * (path_line.size + from)
|
53
|
+
|
54
|
+
out = []
|
55
|
+
out << '-' * 75
|
56
|
+
out << "#{path_line}#{Rasl::Parser.raw_line.rstrip}"
|
57
|
+
if to != from
|
58
|
+
out << padding + '^' * (to - from)
|
59
|
+
else
|
60
|
+
out << padding + '^'
|
61
|
+
end
|
62
|
+
out << '-' * 75
|
63
|
+
out << Rasl::Parser.scanner.inspect
|
64
|
+
out * "\n"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# 主にアセンブル時のエラー
|
70
|
+
class SyntaxError < RaslError; end
|
71
|
+
class LabelNotFound < SyntaxError; end
|
72
|
+
class LabelDuplicate < SyntaxError; end
|
73
|
+
class InvalidIndexRegister < SyntaxError; end
|
74
|
+
class InvalidOrder < SyntaxError; end
|
75
|
+
class RegisterNotFound < SyntaxError; end
|
76
|
+
|
77
|
+
# 実行時エラー
|
78
|
+
class RunError < RaslError; end
|
79
|
+
class MemoryViolate < RunError; end
|
80
|
+
|
81
|
+
class Operand
|
82
|
+
include ActiveModel::Model
|
83
|
+
attr_accessor :key, :encode, :decode, :op_code, :printer, :with_imm, :alias
|
84
|
+
|
85
|
+
def ==(object)
|
86
|
+
case object
|
87
|
+
when Integer
|
88
|
+
op_code == object
|
89
|
+
else
|
90
|
+
match_names.include?(object.to_s.downcase)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def match_names
|
95
|
+
[key, self.alias].flatten.compact.collect(&:to_s)
|
96
|
+
end
|
97
|
+
|
98
|
+
def name
|
99
|
+
key.upcase.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
class Value
|
104
|
+
class << self
|
105
|
+
def cast_value(value, signed)
|
106
|
+
format = {8 => 'c', 16 => 's', 32 => 'l', 64 => 'q'}.fetch(Value.bit)
|
107
|
+
[value].pack(format).unpack(signed ? format : format.upcase).first
|
108
|
+
end
|
109
|
+
|
110
|
+
def signed(value)
|
111
|
+
cast_value(value, true)
|
112
|
+
end
|
113
|
+
|
114
|
+
def unsigned(value)
|
115
|
+
cast_value(value, false)
|
116
|
+
end
|
117
|
+
|
118
|
+
def lsb
|
119
|
+
1
|
120
|
+
end
|
121
|
+
|
122
|
+
def msb
|
123
|
+
1 << (bit - 1)
|
124
|
+
end
|
125
|
+
|
126
|
+
def signed_min
|
127
|
+
-1 << (bit - 1)
|
128
|
+
end
|
129
|
+
|
130
|
+
def signed_max
|
131
|
+
(1 << (bit - 1)) - 1
|
132
|
+
end
|
133
|
+
|
134
|
+
def unsigned_min
|
135
|
+
0
|
136
|
+
end
|
137
|
+
|
138
|
+
def unsigned_max
|
139
|
+
(1 << bit) - 1
|
140
|
+
end
|
141
|
+
|
142
|
+
def bit
|
143
|
+
Rasl.config.bit
|
144
|
+
end
|
145
|
+
|
146
|
+
def signed_range
|
147
|
+
signed_min .. signed_max
|
148
|
+
end
|
149
|
+
|
150
|
+
def unsigned_range
|
151
|
+
unsigned_min .. unsigned_max
|
152
|
+
end
|
153
|
+
|
154
|
+
def hex_format(value)
|
155
|
+
'%0*X' % [hex_width, unsigned(value)]
|
156
|
+
end
|
157
|
+
|
158
|
+
def hex_width
|
159
|
+
bit / 4
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def initialize(raw = 0)
|
164
|
+
@raw = raw
|
165
|
+
end
|
166
|
+
|
167
|
+
def reset
|
168
|
+
@raw = 0
|
169
|
+
end
|
170
|
+
|
171
|
+
def u_value
|
172
|
+
self.class.unsigned(@raw)
|
173
|
+
end
|
174
|
+
alias value u_value
|
175
|
+
alias logical u_value
|
176
|
+
alias unsigned u_value
|
177
|
+
|
178
|
+
def u_value=(v)
|
179
|
+
@raw = self.class.unsigned(v)
|
180
|
+
end
|
181
|
+
alias value= u_value=;
|
182
|
+
alias logical= u_value=;
|
183
|
+
alias unsigned= u_value=;
|
184
|
+
|
185
|
+
def s_value
|
186
|
+
self.class.signed(@raw)
|
187
|
+
end
|
188
|
+
alias arithmetic s_value
|
189
|
+
alias signed s_value
|
190
|
+
|
191
|
+
def s_value=(v)
|
192
|
+
@raw = self.class.signed(v)
|
193
|
+
end
|
194
|
+
alias arithmetic= s_value=;
|
195
|
+
alias signed= s_value=;
|
196
|
+
|
197
|
+
def hex_format
|
198
|
+
self.class.hex_format(@raw)
|
199
|
+
end
|
200
|
+
alias to_s hex_format
|
201
|
+
end
|
202
|
+
|
203
|
+
class Register < Value
|
204
|
+
attr_reader :key
|
205
|
+
|
206
|
+
def initialize(key, attributes = {})
|
207
|
+
super()
|
208
|
+
@key = key.to_sym
|
209
|
+
@attributes = attributes
|
210
|
+
end
|
211
|
+
|
212
|
+
def pos
|
213
|
+
@attributes[:pos]
|
214
|
+
end
|
215
|
+
|
216
|
+
def to_s
|
217
|
+
"#{name}=#{super}"
|
218
|
+
end
|
219
|
+
|
220
|
+
def useful_as_xr?
|
221
|
+
pos && pos.nonzero?
|
222
|
+
end
|
223
|
+
|
224
|
+
def name
|
225
|
+
@key.upcase.to_s
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
class NullRegister < Register
|
230
|
+
def initialize(code)
|
231
|
+
super("gr#{code}(?)")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
class FlagRegister < Register
|
236
|
+
cattr_accessor :flags_hash do
|
237
|
+
{
|
238
|
+
:of => (1 << 2),
|
239
|
+
:sf => (1 << 1),
|
240
|
+
:zf => (1 << 0),
|
241
|
+
}
|
242
|
+
end
|
243
|
+
|
244
|
+
def to_s
|
245
|
+
'%s=%s(%s)' % [name, to_s_flags, to_s_sign]
|
246
|
+
end
|
247
|
+
|
248
|
+
def to_s_flags
|
249
|
+
flags_hash.keys.collect {|key|
|
250
|
+
send("#{key}?") ? key.to_s[0].upcase : '_'
|
251
|
+
}.join
|
252
|
+
end
|
253
|
+
|
254
|
+
def to_s_sign
|
255
|
+
case
|
256
|
+
when sf?
|
257
|
+
'-'
|
258
|
+
when zf?
|
259
|
+
'0'
|
260
|
+
else
|
261
|
+
'+'
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def available_flags
|
266
|
+
flags_hash.keys.each_with_object([]) do |key, a|
|
267
|
+
if send("#{key}?")
|
268
|
+
a << key
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
flags_hash.each do |key, bit|
|
274
|
+
define_method(key) do
|
275
|
+
!!(@raw & bit).nonzero?
|
276
|
+
end
|
277
|
+
|
278
|
+
alias_method "#{key}?", key
|
279
|
+
|
280
|
+
define_method("#{key}=") do |flag|
|
281
|
+
flag.tap do
|
282
|
+
@raw &= ~bit
|
283
|
+
if flag
|
284
|
+
@raw |= bit
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
module Environment
|
292
|
+
attr_reader :gr, :memory, :labels
|
293
|
+
attr_accessor :exit_key, :code_size, :boot_pc, :data
|
294
|
+
|
295
|
+
def initialize
|
296
|
+
create_registers
|
297
|
+
|
298
|
+
@gr[:pr] = @gr[:pc]
|
299
|
+
if Rasl.config.spec == 1
|
300
|
+
@gr[:sp] = @gr.values.last
|
301
|
+
end
|
302
|
+
|
303
|
+
@memory = Array.new(Rasl.config.memory_size)
|
304
|
+
|
305
|
+
@operands = operand_list.collect{|v|Operand.new(v)}
|
306
|
+
@operands_hash = @operands.inject(ActiveSupport::HashWithIndifferentAccess.new){|h, o|h.merge(o.key => o)}
|
307
|
+
|
308
|
+
@code_size = 0
|
309
|
+
@boot_pc = 0
|
310
|
+
|
311
|
+
init_env
|
312
|
+
end
|
313
|
+
|
314
|
+
def init_env
|
315
|
+
@labels = {}
|
316
|
+
@memory.fill(Rasl.config.memory_defval)
|
317
|
+
@gr.values.each(&:reset)
|
318
|
+
@inline_addr_list = []
|
319
|
+
end
|
320
|
+
|
321
|
+
def assemble(buffer)
|
322
|
+
init_env
|
323
|
+
assemble_without_init_env(buffer)
|
324
|
+
end
|
325
|
+
|
326
|
+
def assemble_without_init_env(buffer)
|
327
|
+
@current_buffer = buffer.dup
|
328
|
+
@pass_count = 0
|
329
|
+
assemble_once
|
330
|
+
@pass_count += 1
|
331
|
+
assemble_once
|
332
|
+
self
|
333
|
+
end
|
334
|
+
|
335
|
+
def disassemble
|
336
|
+
out = ''
|
337
|
+
pc = 0
|
338
|
+
until pc >= @code_size
|
339
|
+
code_fetch(pc)
|
340
|
+
pc = @cur_code[:next_pc]
|
341
|
+
out << disasm_current << "\n"
|
342
|
+
end
|
343
|
+
out
|
344
|
+
end
|
345
|
+
|
346
|
+
def create_map_file(map_file)
|
347
|
+
Pathname(map_file).write(disassemble)
|
348
|
+
end
|
349
|
+
|
350
|
+
def gr_count
|
351
|
+
Rasl.config.spec == 1 ? 5 : 8
|
352
|
+
end
|
353
|
+
|
354
|
+
def store_object(gr: nil, imm: nil, xr: nil)
|
355
|
+
raise SyntaxError if (gr && !gr.pos) || (gr && !gr.pos)
|
356
|
+
store_prim_op(@current_op.op_code, (gr ? gr.pos : nil), (xr ? xr.pos : nil), imm)
|
357
|
+
end
|
358
|
+
|
359
|
+
def store_prim_op(op_code, r1, r2, imm = nil)
|
360
|
+
store_value((op_code << 8) | (((r1 || 0) & 0xf) << 4) | ((r2 || 0) & 0xf))
|
361
|
+
if imm
|
362
|
+
store_value(imm)
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def store_value(value)
|
367
|
+
@memory[@code_size] = value
|
368
|
+
@code_size += 1
|
369
|
+
@encoded = true
|
370
|
+
end
|
371
|
+
|
372
|
+
def code_fetch(pc)
|
373
|
+
@cur_code = prefetch(pc)
|
374
|
+
end
|
375
|
+
|
376
|
+
def disasm_current
|
377
|
+
if @cur_code[:operand] && @cur_code[:operand].decode
|
378
|
+
params = disasm_op
|
379
|
+
else
|
380
|
+
params = disasm_dc
|
381
|
+
end
|
382
|
+
('%04X %s %-*s %-7s %s' % [@cur_code[:addr], Value.hex_format(@cur_code[:raw]), Value.hex_width, *params]).strip
|
383
|
+
end
|
384
|
+
|
385
|
+
def disasm_op
|
386
|
+
arg = ''
|
387
|
+
if @cur_code[:operand].printer
|
388
|
+
arg = send(@cur_code[:operand].printer)
|
389
|
+
end
|
390
|
+
[(@cur_code[:imm] ? Value.hex_format(@cur_code[:imm]) : ''), @cur_code[:operand].name, arg]
|
391
|
+
end
|
392
|
+
|
393
|
+
def disasm_dc
|
394
|
+
arg = '%-*d' % [Value.signed_min.to_s.length, Value.signed(@cur_code[:raw])]
|
395
|
+
begin
|
396
|
+
if @cur_code[:raw].chr.match(/[[:print:]]/)
|
397
|
+
arg << " ; '#{@cur_code[:raw].chr}'"
|
398
|
+
end
|
399
|
+
rescue RangeError
|
400
|
+
end
|
401
|
+
['', 'DC', arg]
|
402
|
+
end
|
403
|
+
|
404
|
+
def code_dump(**options)
|
405
|
+
mem_dump(@memory, {:range => 0...@code_size}.merge(options))
|
406
|
+
end
|
407
|
+
|
408
|
+
def regs_info
|
409
|
+
out = []
|
410
|
+
out += gr_count.times.collect{|i|@gr["gr#{i}"]}.collect(&:to_s)
|
411
|
+
out += [@gr[:pc], @gr[:sp], @gr[:fr]].collect(&:to_s)
|
412
|
+
out << (@exit_key ? "[#{@exit_key}]" : nil)
|
413
|
+
out.join(' ').strip
|
414
|
+
end
|
415
|
+
|
416
|
+
def info
|
417
|
+
[regs_info, @labels.inspect] * "\n"
|
418
|
+
end
|
419
|
+
alias to_s info
|
420
|
+
|
421
|
+
def label_fetch(str)
|
422
|
+
((@labels[@current_namespace] || {})[str]) || ((@labels[:__global__] || {})[str])
|
423
|
+
end
|
424
|
+
|
425
|
+
def label_set(namespace, label)
|
426
|
+
@labels[namespace] ||= {}
|
427
|
+
if @labels[namespace][label] && @pass_count == 0
|
428
|
+
raise LabelDuplicate, "ラベル重複 : #{label.inspect} (namespace: #{namespace})"
|
429
|
+
end
|
430
|
+
@labels[namespace][label] = @code_size
|
431
|
+
@current_label = label
|
432
|
+
end
|
433
|
+
|
434
|
+
private
|
435
|
+
|
436
|
+
def create_registers
|
437
|
+
@gr = ActiveSupport::HashWithIndifferentAccess.new
|
438
|
+
gr_count.times do |i|
|
439
|
+
r = Register.new("gr#{i}", :pos => @gr.count)
|
440
|
+
@gr[r.key] = r
|
441
|
+
# @gr[i.to_s] = r # for CASL1
|
442
|
+
end
|
443
|
+
|
444
|
+
if Rasl.config.spec == 2
|
445
|
+
@gr[:sp] = Register.new(:sp, :pos => @gr.count)
|
446
|
+
end
|
447
|
+
|
448
|
+
@gr[:pc] = Register.new(:pc, :pos => @gr.count)
|
449
|
+
@gr[:fr] = FlagRegister.new(:fr, :pos => @gr.count)
|
450
|
+
end
|
451
|
+
|
452
|
+
def assemble_once
|
453
|
+
Rasl::Parser.line_count = nil
|
454
|
+
|
455
|
+
@code_size = 0
|
456
|
+
@boot_pc = nil
|
457
|
+
|
458
|
+
@inline_dc_list = []
|
459
|
+
@inline_index = 0
|
460
|
+
|
461
|
+
@start_index = 0
|
462
|
+
@current_namespace = :__global__
|
463
|
+
@namespaces = []
|
464
|
+
|
465
|
+
@current_buffer.lines.each.with_index do |line, i|
|
466
|
+
Rasl::Parser.raw_line = line
|
467
|
+
Rasl::Parser.line_count = i.next
|
468
|
+
line = line.sub(syntax[:comment], '').rstrip
|
469
|
+
if line.blank?
|
470
|
+
next
|
471
|
+
end
|
472
|
+
if line == '__END__'
|
473
|
+
unless @data
|
474
|
+
@data ||= @current_buffer.rstrip.lines.drop(i.next).collect(&:rstrip)
|
475
|
+
end
|
476
|
+
break
|
477
|
+
end
|
478
|
+
@scanner = StringScanner.new(line)
|
479
|
+
Rasl::Parser.scanner = @scanner
|
480
|
+
parse_label_part
|
481
|
+
skip_blank
|
482
|
+
parse_order_part
|
483
|
+
end
|
484
|
+
|
485
|
+
inline_dc_store
|
486
|
+
|
487
|
+
Rasl::Parser.scanner = nil
|
488
|
+
Rasl::Parser.line_count = nil
|
489
|
+
Rasl::Parser.raw_line = nil
|
490
|
+
end
|
491
|
+
|
492
|
+
def parse_label_part
|
493
|
+
@current_label = nil
|
494
|
+
if label = @scanner.scan(/#{syntax[:label]}:?/)
|
495
|
+
if Rasl.config.bol_order && !label.end_with?(':') && @operands.collect(&:match_names).flatten.include?(label.downcase)
|
496
|
+
@scanner.unscan
|
497
|
+
else
|
498
|
+
label = label.sub(':', '')
|
499
|
+
if label.start_with?('$')
|
500
|
+
label_set(:__global__, label)
|
501
|
+
else
|
502
|
+
label_set(@current_namespace, label)
|
503
|
+
end
|
504
|
+
end
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
def parse_order_part
|
509
|
+
if str = @scanner.scan(syntax[:symbol])
|
510
|
+
@encoded = false
|
511
|
+
skip_blank
|
512
|
+
pointer = @scanner.pointer
|
513
|
+
@operands.each do |operand|
|
514
|
+
next unless operand == str
|
515
|
+
@current_op = operand
|
516
|
+
@scanner.pointer = pointer
|
517
|
+
send operand.encode
|
518
|
+
if @encoded
|
519
|
+
break
|
520
|
+
end
|
521
|
+
end
|
522
|
+
unless @encoded
|
523
|
+
raise InvalidOrder, "無効な命令 : #{str.inspect}"
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
def mem_set(index, value)
|
529
|
+
valid_addr(index)
|
530
|
+
@memory[index] = Value.unsigned(value)
|
531
|
+
end
|
532
|
+
|
533
|
+
def mem_get(index)
|
534
|
+
valid_addr(index)
|
535
|
+
Value.unsigned(@memory[index])
|
536
|
+
end
|
537
|
+
|
538
|
+
def valid_addr(index)
|
539
|
+
unless @memory[index]
|
540
|
+
raise MemoryViolate, "メモリ外アクセス : #{index} メモリサイズ:#{@memory.size}"
|
541
|
+
end
|
542
|
+
end
|
543
|
+
|
544
|
+
def mem_dump(memory, options = {})
|
545
|
+
options = {
|
546
|
+
columns: Rasl.config.dump_cols,
|
547
|
+
range: 0...memory.size,
|
548
|
+
}.merge(options)
|
549
|
+
|
550
|
+
pos = options[:range].begin
|
551
|
+
if body = memory[options[:range]]
|
552
|
+
body.each_slice(options[:columns]) do |values|
|
553
|
+
chars = values.collect do |value|
|
554
|
+
begin
|
555
|
+
value.chr
|
556
|
+
rescue RangeError
|
557
|
+
'.'
|
558
|
+
end
|
559
|
+
end
|
560
|
+
puts '%04X: %-*s%s' % [
|
561
|
+
pos,
|
562
|
+
(Value.hex_width + 1) * options[:columns],
|
563
|
+
values.collect{|v|Value.hex_format(v)} * ' ',
|
564
|
+
chars.join.gsub(/[^[:ascii:]]/, '.').gsub(/[^[:print:]]/, '.'),
|
565
|
+
]
|
566
|
+
pos += values.length
|
567
|
+
end
|
568
|
+
end
|
569
|
+
end
|
570
|
+
|
571
|
+
def store_object(gr: nil, imm: nil, xr: nil)
|
572
|
+
raise SyntaxError if gr && !gr.pos
|
573
|
+
raise SyntaxError if xr && !xr.pos
|
574
|
+
store_prim_op(@current_op.op_code, (gr ? gr.pos : nil), (xr ? xr.pos : nil), imm)
|
575
|
+
end
|
576
|
+
|
577
|
+
def store_prim_op(op_code, r1, r2, imm = nil)
|
578
|
+
store_value((op_code << 8) | (((r1 || 0) & 0xf) << 4) | ((r2 || 0) & 0xf))
|
579
|
+
if imm
|
580
|
+
store_value(imm)
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
def store_asm(key, *args)
|
585
|
+
args = args.collect{|e|e.kind_of?(Symbol) ? @gr[e].pos : e}
|
586
|
+
store_prim_op(@operands_hash[key].op_code, *args)
|
587
|
+
end
|
588
|
+
|
589
|
+
def store_value(value)
|
590
|
+
@memory[@code_size] = value
|
591
|
+
@code_size += 1
|
592
|
+
@encoded = true
|
593
|
+
end
|
594
|
+
|
595
|
+
def code_fetch(pc)
|
596
|
+
@cur_code = prefetch(pc)
|
597
|
+
end
|
598
|
+
|
599
|
+
def prefetch(pc)
|
600
|
+
attrs = {}
|
601
|
+
|
602
|
+
attrs[:addr] = pc
|
603
|
+
attrs[:raw] = mem_get(pc)
|
604
|
+
|
605
|
+
pc += 1
|
606
|
+
attrs[:op_code] = (attrs[:raw] >> 8) & 0xff
|
607
|
+
attrs[:operand] = @operands.find{|e|e == attrs[:op_code] && e.decode}
|
608
|
+
|
609
|
+
r1_r2 = attrs[:raw] & 0xff
|
610
|
+
|
611
|
+
r1 = (r1_r2 >> 4) & 0xf
|
612
|
+
attrs[:r1] = @gr.values.find{|e|e.pos == r1} || NullRegister.new(r1)
|
613
|
+
attrs[:r] = attrs[:r1]
|
614
|
+
|
615
|
+
r2 = r1_r2 & 0xf
|
616
|
+
attrs[:r2] = @gr.values.find{|e|e.pos == r2} || NullRegister.new(r2)
|
617
|
+
attrs[:xr] = @gr.values.find{|e|e.pos == r2 && e.useful_as_xr?}
|
618
|
+
|
619
|
+
if attrs[:operand] && attrs[:operand].with_imm
|
620
|
+
attrs[:imm] = mem_get(pc)
|
621
|
+
pc += 1
|
622
|
+
|
623
|
+
attrs[:imm_xr] = attrs[:imm]
|
624
|
+
if attrs[:xr]
|
625
|
+
attrs[:imm_xr] += attrs[:xr].value
|
626
|
+
end
|
627
|
+
end
|
628
|
+
|
629
|
+
attrs[:next_pc] = pc
|
630
|
+
|
631
|
+
attrs.freeze
|
632
|
+
end
|
633
|
+
end
|
634
|
+
|
635
|
+
module OperandPresets1
|
636
|
+
private
|
637
|
+
|
638
|
+
def operand_list
|
639
|
+
[
|
640
|
+
{ key: :nop, op_code: 0x09, encode: :encode_blank, decode: :decode_nop },
|
641
|
+
|
642
|
+
{ key: :ld, op_code: 0x10, encode: :encode_rix, with_imm: true, decode: :decode_ld_rix, printer: :prt_rix },
|
643
|
+
{ key: :st, op_code: 0x11, encode: :encode_rix, with_imm: true, decode: :decode_st_rix, printer: :prt_rix },
|
644
|
+
{ key: :lad, op_code: 0x12, encode: :encode_rixf, with_imm: true, decode: :decode_lad_rix, printer: :prt_rix },
|
645
|
+
{ key: :ld, op_code: 0x14, encode: :encode_r_r, decode: :decode_ld_r_r, printer: :prt_r_r },
|
646
|
+
{ key: :lea, op_code: 0x1f, encode: :encode_rix, with_imm: true, decode: :decode_lea_rix, printer: :prt_rix },
|
647
|
+
|
648
|
+
{ key: :adda, op_code: 0x20, encode: :encode_rix, with_imm: true, decode: :decode_adda_rix, printer: :prt_rix, alias: :add },
|
649
|
+
{ key: :suba, op_code: 0x21, encode: :encode_rix, with_imm: true, decode: :decode_suba_rix, printer: :prt_rix, alias: :sub },
|
650
|
+
{ key: :addl, op_code: 0x22, encode: :encode_rix, with_imm: true, decode: :decode_addl_rix, printer: :prt_rix },
|
651
|
+
{ key: :subl, op_code: 0x23, encode: :encode_rix, with_imm: true, decode: :decode_subl_rix, printer: :prt_rix },
|
652
|
+
{ key: :adda, op_code: 0x24, encode: :encode_r_r, decode: :decode_adda_r_r, printer: :prt_r_r },
|
653
|
+
{ key: :suba, op_code: 0x25, encode: :encode_r_r, decode: :decode_suba_r_r, printer: :prt_r_r },
|
654
|
+
{ key: :addl, op_code: 0x26, encode: :encode_r_r, decode: :decode_addl_r_r, printer: :prt_r_r },
|
655
|
+
{ key: :subl, op_code: 0x27, encode: :encode_r_r, decode: :decode_subl_r_r, printer: :prt_r_r },
|
656
|
+
|
657
|
+
{ key: :and, op_code: 0x30, encode: :encode_rix, with_imm: true, decode: :decode_and_rix, printer: :prt_rix },
|
658
|
+
{ key: :or, op_code: 0x31, encode: :encode_rix, with_imm: true, decode: :decode_or_rix, printer: :prt_rix },
|
659
|
+
{ key: :xor, op_code: 0x32, encode: :encode_rix, with_imm: true, decode: :decode_xor_rix, printer: :prt_rix, alias: :eor },
|
660
|
+
{ key: :and, op_code: 0x34, encode: :encode_r_r, decode: :decode_and_r_r, printer: :prt_r_r },
|
661
|
+
{ key: :or, op_code: 0x35, encode: :encode_r_r, decode: :decode_or_r_r, printer: :prt_r_r },
|
662
|
+
{ key: :xor, op_code: 0x36, encode: :encode_r_r, decode: :decode_xor_r_r, printer: :prt_r_r },
|
663
|
+
|
664
|
+
{ key: :cpa, op_code: 0x40, encode: :encode_rix, with_imm: true, decode: :decode_cpa_rix, printer: :prt_rix },
|
665
|
+
{ key: :cpl, op_code: 0x41, encode: :encode_rix, with_imm: true, decode: :decode_cpl_rix, printer: :prt_rix },
|
666
|
+
{ key: :cpa, op_code: 0x44, encode: :encode_r_r, decode: :decode_cpa_r_r, printer: :prt_r_r },
|
667
|
+
{ key: :cpl, op_code: 0x45, encode: :encode_r_r, decode: :decode_cpl_r_r, printer: :prt_r_r },
|
668
|
+
|
669
|
+
{ key: :sla, op_code: 0x50, encode: :encode_rix, with_imm: true, decode: :decode_sla_rix, printer: :prt_rix },
|
670
|
+
{ key: :sra, op_code: 0x51, encode: :encode_rix, with_imm: true, decode: :decode_sra_rix, printer: :prt_rix },
|
671
|
+
{ key: :sll, op_code: 0x52, encode: :encode_rix, with_imm: true, decode: :decode_sll, printer: :prt_rix },
|
672
|
+
{ key: :srl, op_code: 0x53, encode: :encode_rix, with_imm: true, decode: :decode_srl, printer: :prt_rix },
|
673
|
+
|
674
|
+
{ key: :jpz, op_code: 0x60, encode: :encode_ix, with_imm: true, decode: :decode_jpz, printer: :prt_ix },
|
675
|
+
{ key: :jmi, op_code: 0x61, encode: :encode_ix, with_imm: true, decode: :decode_jmi, printer: :prt_ix },
|
676
|
+
{ key: :jnz, op_code: 0x62, encode: :encode_ix, with_imm: true, decode: :decode_jnz, printer: :prt_ix },
|
677
|
+
{ key: :jze, op_code: 0x63, encode: :encode_ix, with_imm: true, decode: :decode_jze, printer: :prt_ix },
|
678
|
+
{ key: :jump, op_code: 0x64, encode: :encode_ix, with_imm: true, decode: :decode_jump, printer: :prt_ix, alias: :jmp },
|
679
|
+
{ key: :jpl, op_code: 0x65, encode: :encode_ix, with_imm: true, decode: :decode_jpl, printer: :prt_ix },
|
680
|
+
{ key: :jov, op_code: 0x66, encode: :encode_ix, with_imm: true, decode: :decode_jov, printer: :prt_ix },
|
681
|
+
|
682
|
+
{ key: :push, op_code: 0x70, encode: :encode_ix, with_imm: true, decode: :decode_push, printer: :prt_ix },
|
683
|
+
{ key: :pop, op_code: 0x71, encode: :encode_gr, decode: :decode_pop, printer: :prt_gr },
|
684
|
+
{ key: :call, op_code: 0x80, encode: :encode_ix, with_imm: true, decode: :decode_call, printer: :prt_ix },
|
685
|
+
{ key: :ret, op_code: 0x81, encode: :encode_blank, decode: :decode_ret },
|
686
|
+
|
687
|
+
{ key: :svc, op_code: 0xf0, encode: :encode_ix, with_imm: true, decode: :decode_svc, printer: :prt_ix },
|
688
|
+
|
689
|
+
{ key: :prt, op_code: 0xe0, encode: :encode_ix, with_imm: true, decode: :decode_prt, printer: :prt_ix },
|
690
|
+
|
691
|
+
{ key: :start, encode: :encode_start },
|
692
|
+
{ key: :end, encode: :encode_end },
|
693
|
+
{ key: :ds, encode: :encode_ds },
|
694
|
+
{ key: :dc, encode: :encode_dc },
|
695
|
+
|
696
|
+
{ key: :in, encode: :encode_in },
|
697
|
+
{ key: :out, encode: :encode_out },
|
698
|
+
{ key: :exit, encode: :encode__exit },
|
699
|
+
{ key: :rpush, encode: :encode_rpush },
|
700
|
+
{ key: :rpop, encode: :encode_rpop },
|
701
|
+
|
702
|
+
{ key: :copy, encode: :encode_copy },
|
703
|
+
]
|
704
|
+
end
|
705
|
+
|
706
|
+
def encode_blank
|
707
|
+
store_object
|
708
|
+
end
|
709
|
+
|
710
|
+
def encode_r_r
|
711
|
+
r1 = scan_gr
|
712
|
+
skip_sep
|
713
|
+
if @scanner.check(register_regexp)
|
714
|
+
store_object(gr: r1, xr: scan_gr)
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
def encode_rix
|
719
|
+
r1 = scan_gr
|
720
|
+
skip_sep
|
721
|
+
unless @scanner.check(register_regexp)
|
722
|
+
store_object(gr: r1, imm: scan_imm, xr: scan_xr)
|
723
|
+
end
|
724
|
+
end
|
725
|
+
|
726
|
+
def encode_rixf
|
727
|
+
r1 = scan_gr
|
728
|
+
skip_sep
|
729
|
+
store_object(gr: r1, imm: scan_imm, xr: scan_xr)
|
730
|
+
end
|
731
|
+
|
732
|
+
def encode_gr
|
733
|
+
store_object(gr: scan_gr)
|
734
|
+
end
|
735
|
+
|
736
|
+
def encode_ix
|
737
|
+
store_object(imm: scan_imm, xr: scan_xr)
|
738
|
+
end
|
739
|
+
|
740
|
+
def encode_imm
|
741
|
+
store_object(imm: scan_imm)
|
742
|
+
end
|
743
|
+
|
744
|
+
def encode_in
|
745
|
+
encode_inout(:input)
|
746
|
+
end
|
747
|
+
|
748
|
+
def encode_out
|
749
|
+
encode_inout(:output)
|
750
|
+
end
|
751
|
+
|
752
|
+
def encode_inout(function)
|
753
|
+
store_asm :push, nil, :gr1, 0
|
754
|
+
store_asm :push, nil, :gr2, 0
|
755
|
+
store_asm :lad, :gr1, 0, scan_imm
|
756
|
+
skip_sep
|
757
|
+
store_asm :lad, :gr2, 0, scan_imm
|
758
|
+
store_asm :svc, nil, nil, svc_hash[function][:code]
|
759
|
+
store_asm :pop, :gr2, nil
|
760
|
+
store_asm :pop, :gr1, nil
|
761
|
+
end
|
762
|
+
|
763
|
+
def encode_copy
|
764
|
+
store_asm :push, nil, :gr1, 0
|
765
|
+
store_asm :push, nil, :gr2, 0
|
766
|
+
store_asm :push, nil, :gr3, 0
|
767
|
+
store_asm :lad, :gr1, 0, scan_imm
|
768
|
+
skip_sep
|
769
|
+
store_asm :lad, :gr2, 0, scan_imm
|
770
|
+
skip_sep
|
771
|
+
store_asm :lad, :gr3, 0, scan_imm
|
772
|
+
store_asm :svc, nil, nil, svc_hash[:copy][:code]
|
773
|
+
store_asm :pop, :gr3, nil
|
774
|
+
store_asm :pop, :gr2, nil
|
775
|
+
store_asm :pop, :gr1, nil
|
776
|
+
end
|
777
|
+
|
778
|
+
def encode__exit
|
779
|
+
store_prim_op(@operands_hash[:svc].op_code, nil, nil, svc_hash[:exit][:code])
|
780
|
+
end
|
781
|
+
|
782
|
+
def encode_start
|
783
|
+
@start_index += 1
|
784
|
+
|
785
|
+
@namespaces.push(@current_namespace)
|
786
|
+
if @current_label
|
787
|
+
@current_namespace = @current_label
|
788
|
+
else
|
789
|
+
@current_namespace = "__proc_#{@start_index}__"
|
790
|
+
end
|
791
|
+
|
792
|
+
v = 0
|
793
|
+
if @scanner.check(/\S+/)
|
794
|
+
v = scan_imm
|
795
|
+
end
|
796
|
+
@boot_pc ||= v
|
797
|
+
|
798
|
+
@encoded = true
|
799
|
+
end
|
800
|
+
|
801
|
+
def encode_end
|
802
|
+
inline_dc_store
|
803
|
+
@current_namespace = @namespaces.pop
|
804
|
+
@encoded = true
|
805
|
+
end
|
806
|
+
|
807
|
+
def inline_dc_store
|
808
|
+
@inline_dc_list.each do |v|
|
809
|
+
@inline_addr_list << @code_size
|
810
|
+
dc_store(v)
|
811
|
+
end
|
812
|
+
@inline_dc_list.clear
|
813
|
+
end
|
814
|
+
|
815
|
+
def encode_dc
|
816
|
+
loop do
|
817
|
+
dc_store(scan_imm_or_str)
|
818
|
+
skip_sep
|
819
|
+
if @scanner.eos?
|
820
|
+
break
|
821
|
+
end
|
822
|
+
end
|
823
|
+
@encoded = true
|
824
|
+
end
|
825
|
+
|
826
|
+
def dc_store(value)
|
827
|
+
if value.kind_of? String
|
828
|
+
value.each_byte{|ch|store_value(ch)}
|
829
|
+
else
|
830
|
+
store_value(value)
|
831
|
+
end
|
832
|
+
end
|
833
|
+
|
834
|
+
def scan_imm_or_str
|
835
|
+
if str = scan_str_literal(%{'}) || scan_str_literal(%{"})
|
836
|
+
str
|
837
|
+
else
|
838
|
+
scan_imm
|
839
|
+
end
|
840
|
+
end
|
841
|
+
|
842
|
+
def scan_str_literal(mark)
|
843
|
+
if @scanner.check(/#{mark}/)
|
844
|
+
from = @scanner.pointer
|
845
|
+
nil while @scanner.scan(/#{mark}[^#{mark}]*#{mark}/) && @scanner.check(/#{mark}/)
|
846
|
+
str = @scanner.string[from...@scanner.pointer] # 【'a''b'】
|
847
|
+
if str == ''
|
848
|
+
raise SyntaxError, "対応する #{mark} がない"
|
849
|
+
end
|
850
|
+
str = str.match(/\A.(?<str>.*).\z/)[:str] # 【a''b】
|
851
|
+
str.gsub(/#{mark}{2}/, mark) # 【a'b】
|
852
|
+
end
|
853
|
+
end
|
854
|
+
|
855
|
+
def encode_ds
|
856
|
+
scan_imm.times.each{store_value(Rasl.config.ds_init_value)}
|
857
|
+
@encoded = true
|
858
|
+
end
|
859
|
+
|
860
|
+
def decode_ld_rix
|
861
|
+
@cur_code[:r1].value = mem_get(@cur_code[:imm_xr])
|
862
|
+
set_fr(@cur_code[:r1].s_value)
|
863
|
+
@gr[:fr].of = false
|
864
|
+
end
|
865
|
+
|
866
|
+
def decode_ld_r_r
|
867
|
+
@cur_code[:r1].value = @cur_code[:r2].value
|
868
|
+
set_fr(@cur_code[:r1].s_value)
|
869
|
+
@gr[:fr].of = false
|
870
|
+
end
|
871
|
+
|
872
|
+
def decode_st_rix
|
873
|
+
mem_set(@cur_code[:imm_xr], @cur_code[:r1].value)
|
874
|
+
end
|
875
|
+
|
876
|
+
def decode_lea_rix
|
877
|
+
decode_lad_rix
|
878
|
+
set_fr(@cur_code[:r1].s_value)
|
879
|
+
end
|
880
|
+
|
881
|
+
def decode_lad_rix
|
882
|
+
@cur_code[:r1].value = @cur_code[:imm_xr]
|
883
|
+
end
|
884
|
+
|
885
|
+
def decode_adda_rix
|
886
|
+
decode_calc(:+, :rix, :signed)
|
887
|
+
end
|
888
|
+
|
889
|
+
def decode_addl_rix
|
890
|
+
decode_calc(:+, :rix, :unsigned)
|
891
|
+
end
|
892
|
+
|
893
|
+
def decode_suba_rix
|
894
|
+
decode_calc(:-, :rix, :signed)
|
895
|
+
end
|
896
|
+
|
897
|
+
def decode_subl_rix
|
898
|
+
decode_calc(:-, :rix, :unsigned)
|
899
|
+
end
|
900
|
+
|
901
|
+
def decode_adda_r_r
|
902
|
+
decode_calc(:+, :r_r, :signed)
|
903
|
+
end
|
904
|
+
|
905
|
+
def decode_suba_r_r
|
906
|
+
decode_calc(:-, :r_r, :signed)
|
907
|
+
end
|
908
|
+
|
909
|
+
def decode_addl_r_r
|
910
|
+
decode_calc(:+, :r_r, :unsigned)
|
911
|
+
end
|
912
|
+
|
913
|
+
def decode_subl_r_r
|
914
|
+
decode_calc(:-, :r_r, :unsigned)
|
915
|
+
end
|
916
|
+
|
917
|
+
def decode_and_rix
|
918
|
+
decode_logical_bit(:&, mem_get(@cur_code[:imm_xr]))
|
919
|
+
end
|
920
|
+
|
921
|
+
def decode_or_rix
|
922
|
+
decode_logical_bit(:|, mem_get(@cur_code[:imm_xr]))
|
923
|
+
end
|
924
|
+
|
925
|
+
def decode_xor_rix
|
926
|
+
decode_logical_bit(:^, mem_get(@cur_code[:imm_xr]))
|
927
|
+
end
|
928
|
+
|
929
|
+
def decode_and_r_r
|
930
|
+
decode_logical_bit(:&, @cur_code[:r2].value)
|
931
|
+
end
|
932
|
+
|
933
|
+
def decode_or_r_r
|
934
|
+
decode_logical_bit(:|, @cur_code[:r2].value)
|
935
|
+
end
|
936
|
+
|
937
|
+
def decode_xor_r_r
|
938
|
+
decode_logical_bit(:^, @cur_code[:r2].value)
|
939
|
+
end
|
940
|
+
|
941
|
+
def decode_calc(method, syntax_type, value_type)
|
942
|
+
v1 = @cur_code[:r1].value
|
943
|
+
if syntax_type == :r_r
|
944
|
+
v2 = @cur_code[:r2].value
|
945
|
+
else
|
946
|
+
v2 = mem_get(@cur_code[:imm_xr])
|
947
|
+
end
|
948
|
+
v1 = Value.send(value_type, v1)
|
949
|
+
v2 = Value.send(value_type, v2)
|
950
|
+
value = v1.send(method, v2)
|
951
|
+
@gr[:fr].of = !Value.send("#{value_type}_range").include?(value)
|
952
|
+
@cur_code[:r1].value = value
|
953
|
+
set_fr(@cur_code[:r1].s_value)
|
954
|
+
end
|
955
|
+
|
956
|
+
def decode_logical_bit(method, right_value)
|
957
|
+
@cur_code[:r1].value = @cur_code[:r1].value.send(method, right_value)
|
958
|
+
set_fr(@cur_code[:r1].s_value)
|
959
|
+
@gr[:fr].of = false
|
960
|
+
end
|
961
|
+
|
962
|
+
def decode_cpa_rix
|
963
|
+
decode_cpx(mem_get(@cur_code[:imm_xr]), :signed)
|
964
|
+
end
|
965
|
+
|
966
|
+
def decode_cpl_rix
|
967
|
+
decode_cpx(mem_get(@cur_code[:imm_xr]), :unsigned)
|
968
|
+
end
|
969
|
+
|
970
|
+
def decode_cpa_r_r
|
971
|
+
decode_cpx(@cur_code[:r2].value, :signed)
|
972
|
+
end
|
973
|
+
|
974
|
+
def decode_cpl_r_r
|
975
|
+
decode_cpx(@cur_code[:r2].value, :unsigned)
|
976
|
+
end
|
977
|
+
|
978
|
+
def decode_cpx(right_value, value_type)
|
979
|
+
set_fr(Value.send(value_type, @cur_code[:r1].value) - Value.send(value_type, right_value))
|
980
|
+
@gr[:fr].of = false
|
981
|
+
end
|
982
|
+
|
983
|
+
def set_fr(value)
|
984
|
+
@gr[:fr].zf = value.zero?
|
985
|
+
@gr[:fr].sf = value < 0
|
986
|
+
end
|
987
|
+
|
988
|
+
def set_of(value)
|
989
|
+
@gr[:fr].of = value.nonzero?
|
990
|
+
end
|
991
|
+
|
992
|
+
def decode_sla_rix
|
993
|
+
decode_sxa(:<<, :signed)
|
994
|
+
end
|
995
|
+
|
996
|
+
def decode_sra_rix
|
997
|
+
decode_sxa(:>>, :signed)
|
998
|
+
end
|
999
|
+
|
1000
|
+
def decode_sll
|
1001
|
+
decode_sxa(:<<, :unsigned)
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
def decode_srl
|
1005
|
+
decode_sxa(:>>, :unsigned)
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
def decode_sxa(method, value_type)
|
1009
|
+
shift = mem_get(@cur_code[:imm_xr])
|
1010
|
+
if shift > Value.bit
|
1011
|
+
shift = Value.bit
|
1012
|
+
end
|
1013
|
+
of_bit = (method == :<< ? Value.msb : Value.lsb)
|
1014
|
+
v = @cur_code[:r1].send(value_type)
|
1015
|
+
of = 0
|
1016
|
+
shift.times do
|
1017
|
+
of = v & of_bit
|
1018
|
+
sf_bit = (v & Value.msb)
|
1019
|
+
v = v.send(method, 1)
|
1020
|
+
if value_type == :signed
|
1021
|
+
v |= sf_bit
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
@cur_code[:r1].value = v
|
1025
|
+
set_fr(@cur_code[:r1].s_value)
|
1026
|
+
set_of(of)
|
1027
|
+
end
|
1028
|
+
|
1029
|
+
def decode_jpz
|
1030
|
+
unless @gr[:fr].sf?
|
1031
|
+
decode_jump
|
1032
|
+
end
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
def decode_jmi
|
1036
|
+
if @gr[:fr].sf?
|
1037
|
+
decode_jump
|
1038
|
+
end
|
1039
|
+
end
|
1040
|
+
|
1041
|
+
def decode_jnz
|
1042
|
+
unless @gr[:fr].zf?
|
1043
|
+
decode_jump
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
def decode_jze
|
1048
|
+
if @gr[:fr].zf?
|
1049
|
+
decode_jump
|
1050
|
+
end
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
def decode_jump
|
1054
|
+
@gr[:pc].value = @cur_code[:imm_xr]
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
def decode_push
|
1058
|
+
value_push(@cur_code[:imm_xr])
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
def value_push(value)
|
1062
|
+
@gr[:sp].value -= 1
|
1063
|
+
mem_set(@gr[:sp].value, value)
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
def value_pop
|
1067
|
+
mem_get(@gr[:sp].value).tap { @gr[:sp].value += 1 }
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
def decode_pop
|
1071
|
+
@cur_code[:r1].value = value_pop
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
def decode_call
|
1075
|
+
value_push(@gr[:pc].value)
|
1076
|
+
decode_jump
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
def decode_ret
|
1080
|
+
@gr[:pc].value = value_pop
|
1081
|
+
if @gr[:sp].value >= @memory.size || @gr[:sp].value == 0
|
1082
|
+
@exit_key = :ret
|
1083
|
+
end
|
1084
|
+
end
|
1085
|
+
|
1086
|
+
def decode_nop
|
1087
|
+
end
|
1088
|
+
|
1089
|
+
def decode_svc
|
1090
|
+
if elem = svc_list.find{|e|e[:code] == @cur_code[:imm_xr]}
|
1091
|
+
send "decode_svc_#{elem[:key]}"
|
1092
|
+
end
|
1093
|
+
end
|
1094
|
+
|
1095
|
+
def svc_list
|
1096
|
+
[
|
1097
|
+
{:key => :input, :code => 0},
|
1098
|
+
{:key => :output, :code => 1},
|
1099
|
+
{:key => :exit, :code => 2},
|
1100
|
+
{:key => :copy, :code => 3},
|
1101
|
+
]
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
def svc_hash
|
1105
|
+
svc_list.inject({}){|h, v|h.merge(v[:key] => v)}
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
def decode_svc_input
|
1109
|
+
base = @gr[:gr1].value
|
1110
|
+
sizep = @gr[:gr2].value
|
1111
|
+
if @data
|
1112
|
+
str = @data[@data_pos].tap { @data_pos += 1 }
|
1113
|
+
else
|
1114
|
+
str = $stdin.gets
|
1115
|
+
end
|
1116
|
+
if str
|
1117
|
+
str = str.chomp
|
1118
|
+
str.chars.each.with_index{|ch, i|
|
1119
|
+
mem_set(base + i, ch.ord)
|
1120
|
+
}
|
1121
|
+
mem_set(sizep, str.length)
|
1122
|
+
else
|
1123
|
+
mem_set(sizep, END_OF_FILE)
|
1124
|
+
end
|
1125
|
+
end
|
1126
|
+
|
1127
|
+
def decode_svc_output
|
1128
|
+
base = @gr[:gr1].value
|
1129
|
+
size = Value.signed(mem_get(@gr[:gr2].value))
|
1130
|
+
if size == END_OF_FILE
|
1131
|
+
return
|
1132
|
+
end
|
1133
|
+
str = size.times.collect {|i|
|
1134
|
+
v = mem_get(base + i)
|
1135
|
+
begin
|
1136
|
+
v.chr
|
1137
|
+
rescue RangeError
|
1138
|
+
"(##{Value.hex_format(v)})"
|
1139
|
+
end
|
1140
|
+
}.join
|
1141
|
+
puts str
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
def decode_svc_exit
|
1145
|
+
@exit_key = :exit
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
def decode_svc_copy
|
1149
|
+
dist = @gr[:gr1].value
|
1150
|
+
src = @gr[:gr2].value
|
1151
|
+
size = @gr[:gr3].value
|
1152
|
+
size.times do |i|
|
1153
|
+
mem_set(dist + i, mem_get(src + i))
|
1154
|
+
end
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
def decode_prt
|
1158
|
+
puts @cur_code[:imm_xr]
|
1159
|
+
end
|
1160
|
+
|
1161
|
+
def prt_r_r
|
1162
|
+
[@cur_code[:r1].name, separator, @cur_code[:r2].name].join
|
1163
|
+
end
|
1164
|
+
|
1165
|
+
def prt_rix
|
1166
|
+
[prt_gr, separator, prt_ix].join
|
1167
|
+
end
|
1168
|
+
|
1169
|
+
def prt_ix
|
1170
|
+
["##{Value.hex_format(@cur_code[:imm])}", prt_xr].join
|
1171
|
+
end
|
1172
|
+
|
1173
|
+
def prt_gr
|
1174
|
+
@cur_code[:r1].name
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
def prt_xr
|
1178
|
+
if @cur_code[:xr]
|
1179
|
+
"#{separator}#{@cur_code[:xr].name}"
|
1180
|
+
end
|
1181
|
+
end
|
1182
|
+
|
1183
|
+
def separator
|
1184
|
+
', '
|
1185
|
+
end
|
1186
|
+
|
1187
|
+
def prt_blank
|
1188
|
+
end
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
module OperandPresets2
|
1192
|
+
def decode_jpl
|
1193
|
+
if !@gr[:fr].sf? && !@gr[:fr].zf?
|
1194
|
+
decode_jump
|
1195
|
+
end
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
def decode_jov
|
1199
|
+
if @gr[:fr].of?
|
1200
|
+
decode_jump
|
1201
|
+
end
|
1202
|
+
end
|
1203
|
+
|
1204
|
+
def encode_rpush
|
1205
|
+
rpush_registers.each do |r|
|
1206
|
+
store_prim_op(@operands_hash[:push].op_code, 0, r.pos, 0)
|
1207
|
+
end
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
def encode_rpop
|
1211
|
+
rpush_registers.reverse_each do |r|
|
1212
|
+
store_prim_op(@operands_hash[:pop].op_code, r.pos, 0)
|
1213
|
+
end
|
1214
|
+
end
|
1215
|
+
|
1216
|
+
def rpush_registers
|
1217
|
+
(1 ... gr_count).collect{|i|@gr["gr#{i}"]}
|
1218
|
+
end
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
module Parser
|
1222
|
+
mattr_accessor :raw_line, :line_count, :scanner
|
1223
|
+
|
1224
|
+
private
|
1225
|
+
|
1226
|
+
def syntax
|
1227
|
+
{
|
1228
|
+
:comment => /([^\\];|\A#).*/,
|
1229
|
+
:label => /\A[$@_a-z]\w*/i,
|
1230
|
+
:symbol => /\A[_a-z]\w*/i,
|
1231
|
+
:imm => /[+-]?(#|0x|0b)?[\da-f]+/i,
|
1232
|
+
:sepalator => /[,\s]+/, # 厳密にするなら /\s*,\s*/
|
1233
|
+
:blank => /[,\s]+/, # 厳密にするなら /\s+/
|
1234
|
+
:inline_dc => /\s*=\s*/i,
|
1235
|
+
}
|
1236
|
+
end
|
1237
|
+
|
1238
|
+
def register_regexp
|
1239
|
+
Regexp.union(/\b#{@gr.keys.join('|')}\b/i)
|
1240
|
+
end
|
1241
|
+
|
1242
|
+
def scan_gr
|
1243
|
+
if str = @scanner.scan(register_regexp)
|
1244
|
+
@gr[str.downcase]
|
1245
|
+
else
|
1246
|
+
raise RegisterNotFound, 'レジスタの指定がありません'
|
1247
|
+
end
|
1248
|
+
end
|
1249
|
+
|
1250
|
+
def scan_imm
|
1251
|
+
case
|
1252
|
+
when str = @scanner.scan(syntax[:label])
|
1253
|
+
if @pass_count == 0
|
1254
|
+
undecision
|
1255
|
+
else
|
1256
|
+
v = label_fetch(str)
|
1257
|
+
unless v
|
1258
|
+
raise LabelNotFound, "ラベルが見つかりません : #{str.inspect} in #{@labels.inspect}"
|
1259
|
+
end
|
1260
|
+
v
|
1261
|
+
end
|
1262
|
+
when str = @scanner.scan(syntax[:imm])
|
1263
|
+
cast_int(str)
|
1264
|
+
when @scanner.scan(syntax[:inline_dc])
|
1265
|
+
@inline_dc_list << scan_imm_or_str
|
1266
|
+
if @pass_count == 0
|
1267
|
+
v = undecision
|
1268
|
+
else
|
1269
|
+
v = @inline_addr_list[@inline_index]
|
1270
|
+
end
|
1271
|
+
@inline_index += 1
|
1272
|
+
v
|
1273
|
+
else
|
1274
|
+
raise SyntaxError, '即値が見つかりません'
|
1275
|
+
end
|
1276
|
+
end
|
1277
|
+
|
1278
|
+
def scan_xr
|
1279
|
+
skip_sep
|
1280
|
+
if str = @scanner.scan(register_regexp)
|
1281
|
+
xr = @gr[str.downcase]
|
1282
|
+
unless xr
|
1283
|
+
raise SyntaxError, "指標レジスタの表記が間違っています : #{str.inspect}"
|
1284
|
+
end
|
1285
|
+
unless xr.useful_as_xr?
|
1286
|
+
raise InvalidIndexRegister, "指標レジスタに #{xr.name} は使えません"
|
1287
|
+
end
|
1288
|
+
end
|
1289
|
+
xr
|
1290
|
+
end
|
1291
|
+
|
1292
|
+
def imm_or_int(str)
|
1293
|
+
case
|
1294
|
+
when v = label_fetch(str)
|
1295
|
+
v
|
1296
|
+
when str.match(syntax[:imm])
|
1297
|
+
cast_int(str)
|
1298
|
+
end
|
1299
|
+
end
|
1300
|
+
|
1301
|
+
def cast_int(str)
|
1302
|
+
Integer(str.sub(/\A#/, '0x'))
|
1303
|
+
end
|
1304
|
+
|
1305
|
+
def label_or_imm_regexp
|
1306
|
+
Regexp.union(syntax[:label], syntax[:imm])
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
def skip_sep
|
1310
|
+
@scanner.skip(syntax[:sepalator])
|
1311
|
+
end
|
1312
|
+
|
1313
|
+
def skip_blank
|
1314
|
+
@scanner.skip(syntax[:blank])
|
1315
|
+
end
|
1316
|
+
|
1317
|
+
def undecision
|
1318
|
+
-1
|
1319
|
+
end
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
module Simulator
|
1323
|
+
def simulator
|
1324
|
+
command_init
|
1325
|
+
loop do
|
1326
|
+
if defined? Readline
|
1327
|
+
getline(Readline.readline('-'))
|
1328
|
+
else
|
1329
|
+
print '-'
|
1330
|
+
getline($stdin.gets)
|
1331
|
+
end
|
1332
|
+
next unless @command
|
1333
|
+
if @command == 'q'
|
1334
|
+
break
|
1335
|
+
end
|
1336
|
+
if command = command_table[@command]
|
1337
|
+
send command
|
1338
|
+
end
|
1339
|
+
end
|
1340
|
+
end
|
1341
|
+
|
1342
|
+
def go
|
1343
|
+
command_init
|
1344
|
+
command_go
|
1345
|
+
self
|
1346
|
+
end
|
1347
|
+
|
1348
|
+
def command_table
|
1349
|
+
{
|
1350
|
+
'i' => :command_init,
|
1351
|
+
'g' => :command_go,
|
1352
|
+
'r' => :command_register,
|
1353
|
+
'd' => :command_dump,
|
1354
|
+
't' => :command_trace,
|
1355
|
+
'u' => :command_disasm,
|
1356
|
+
'?' => :command_help,
|
1357
|
+
'h' => :command_help,
|
1358
|
+
}
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
def command_dump
|
1362
|
+
if @hex_args
|
1363
|
+
@dump_point = @hex_args.first
|
1364
|
+
end
|
1365
|
+
size = Rasl.config.dump_cols * Rasl.config.dump_rows
|
1366
|
+
mem_dump(@memory, :range => (@dump_point...(@dump_point + size)))
|
1367
|
+
@dump_point += size
|
1368
|
+
end
|
1369
|
+
|
1370
|
+
def command_disasm
|
1371
|
+
if @hex_args
|
1372
|
+
@unencode_point = @hex_args.first
|
1373
|
+
end
|
1374
|
+
Rasl.config.disassemble_rows.times do
|
1375
|
+
if @unencode_point >= @memory.size
|
1376
|
+
break
|
1377
|
+
end
|
1378
|
+
code_fetch(@unencode_point)
|
1379
|
+
@unencode_point = @cur_code[:next_pc]
|
1380
|
+
puts disasm_current
|
1381
|
+
end
|
1382
|
+
end
|
1383
|
+
|
1384
|
+
def command_init
|
1385
|
+
@gr.values.each(&:reset)
|
1386
|
+
before_go
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
def before_go
|
1390
|
+
@gr[:sp].value = @memory.size
|
1391
|
+
value_push(-1)
|
1392
|
+
|
1393
|
+
@boot_pc ||= 0
|
1394
|
+
@gr[:pc].value = @boot_pc
|
1395
|
+
@unencode_point = @boot_pc
|
1396
|
+
@dump_point = @boot_pc
|
1397
|
+
|
1398
|
+
@exit_key = false
|
1399
|
+
@data_pos = 0
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
def command_go
|
1403
|
+
set_pc
|
1404
|
+
until @exit_key
|
1405
|
+
command_step
|
1406
|
+
end
|
1407
|
+
end
|
1408
|
+
|
1409
|
+
def command_trace
|
1410
|
+
set_pc
|
1411
|
+
unless @exit_key
|
1412
|
+
command_step
|
1413
|
+
current_state
|
1414
|
+
end
|
1415
|
+
end
|
1416
|
+
|
1417
|
+
def command_register
|
1418
|
+
if @args
|
1419
|
+
@args.each do |arg|
|
1420
|
+
if md = arg.match(/(?<lhv>.+)=(?<rhv>.+)/)
|
1421
|
+
@gr[md[:lhv].downcase].value = imm_or_int(md[:rhv])
|
1422
|
+
end
|
1423
|
+
end
|
1424
|
+
else
|
1425
|
+
current_state
|
1426
|
+
end
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
def command_step
|
1430
|
+
code_fetch(@gr[:pc].value)
|
1431
|
+
unless @cur_code[:operand]
|
1432
|
+
raise RunError, "不明な命令のため実行できない : #{@cur_code[:raw]}"
|
1433
|
+
end
|
1434
|
+
@gr[:pc].value = @cur_code[:next_pc]
|
1435
|
+
send @cur_code[:operand].decode
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
def current_state
|
1439
|
+
code_fetch(@gr[:pc].value)
|
1440
|
+
puts regs_info
|
1441
|
+
puts disasm_current
|
1442
|
+
end
|
1443
|
+
|
1444
|
+
def post_command(s)
|
1445
|
+
getline(s)
|
1446
|
+
send command_table[@command]
|
1447
|
+
end
|
1448
|
+
|
1449
|
+
private
|
1450
|
+
|
1451
|
+
def getline(s)
|
1452
|
+
@command = nil
|
1453
|
+
@args = nil
|
1454
|
+
@hex_args = nil
|
1455
|
+
if md = s.strip.match(/(.)(.*)/)
|
1456
|
+
@command, _args = md.captures.to_a
|
1457
|
+
@command = @command.downcase
|
1458
|
+
unless _args.empty?
|
1459
|
+
@args = _args.split(/\s+|,/)
|
1460
|
+
@hex_args = @args.collect{|e|e.to_i(16)}
|
1461
|
+
end
|
1462
|
+
end
|
1463
|
+
end
|
1464
|
+
|
1465
|
+
def set_pc
|
1466
|
+
if @hex_args
|
1467
|
+
@gr[:pc].value = @hex_args.first
|
1468
|
+
end
|
1469
|
+
end
|
1470
|
+
|
1471
|
+
def command_help
|
1472
|
+
puts <<-EOT
|
1473
|
+
D[address] memory-dump
|
1474
|
+
U[address] unassemble
|
1475
|
+
G[address] go
|
1476
|
+
T[address] trace
|
1477
|
+
R[reg=n] register
|
1478
|
+
? or H usage
|
1479
|
+
I init
|
1480
|
+
Q quit
|
1481
|
+
EOT
|
1482
|
+
end
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
class Processor
|
1486
|
+
prepend Environment
|
1487
|
+
prepend OperandPresets1
|
1488
|
+
prepend OperandPresets2
|
1489
|
+
prepend Parser
|
1490
|
+
prepend Simulator
|
1491
|
+
end
|
1492
|
+
|
1493
|
+
class CLI
|
1494
|
+
def self.execute(args = ARGV)
|
1495
|
+
new.execute(args)
|
1496
|
+
end
|
1497
|
+
|
1498
|
+
def initialize
|
1499
|
+
@file = nil
|
1500
|
+
@options = {}
|
1501
|
+
end
|
1502
|
+
|
1503
|
+
def parser
|
1504
|
+
OptionParser.new do |o|
|
1505
|
+
o.version = VERSION
|
1506
|
+
o.banner = [
|
1507
|
+
"CASL Assembler / Simulator #{o.ver}\n",
|
1508
|
+
"使い方: #{o.program_name} [OPTIONS] [ファイル]\n",
|
1509
|
+
].join
|
1510
|
+
o.on("-s", "--simulator", "シミュレータ起動") do |v|
|
1511
|
+
@options[:simulator] = v
|
1512
|
+
end
|
1513
|
+
o.on("-p", "--print-map", "MAP情報の標準出力") do |v|
|
1514
|
+
@options[:print_map] = v
|
1515
|
+
end
|
1516
|
+
o.on("-m", "--output-map", "MAP情報のファイル出力。-g オプションがあるときは実行後に出力する") do |v|
|
1517
|
+
@options[:output_map] = v
|
1518
|
+
end
|
1519
|
+
o.on("-g", "--go", "実行") do |v|
|
1520
|
+
@options[:go] = v
|
1521
|
+
end
|
1522
|
+
o.on("-e CODE", "--eval=CODE", "指定コードの評価。指定があると標準入力からは読み込まない") do |v|
|
1523
|
+
@options[:eval] = v
|
1524
|
+
end
|
1525
|
+
o.on("-r", "--register", "実行後レジスタ一覧表示") do |v|
|
1526
|
+
@options[:register] = v
|
1527
|
+
end
|
1528
|
+
o.on("--in=STRING", "INマクロに対する入力文字列(__END__ 行のデータよりも優先)") do |v|
|
1529
|
+
@options[:data] = v
|
1530
|
+
end
|
1531
|
+
o.on("--memory-size=SIZE", Integer, "メモリサイズの指定(デフォルト:#{(Rasl.config.memory_size)})") do |v|
|
1532
|
+
Rasl.config.memory_size = v
|
1533
|
+
end
|
1534
|
+
o.on("--spec=NUMBER", Integer, "1:レジスタ数5個でGR4==SP 2:レジスタ数8 GR4!=SP") do |v|
|
1535
|
+
Rasl.config.spec = v
|
1536
|
+
end
|
1537
|
+
o.on("--ds-init-value=VAL","DSで領域確保したときの初期値(デフォルト:#{Rasl.config.ds_init_value})") do |v|
|
1538
|
+
Rasl.config.ds_init_value = Integer(v)
|
1539
|
+
end
|
1540
|
+
o.on("--memory-defval=VAL", "メモリの初期値(デフォルト:#{Rasl.config.memory_defval})") do |v|
|
1541
|
+
Rasl.config.memory_defval = Integer(v)
|
1542
|
+
end
|
1543
|
+
o.on("--[no-]bol-order", "命令の前に空白を書かなくてよいことにする(デフォルト:#{Rasl.config.bol_order})") do |v|
|
1544
|
+
Rasl.config.bol_order = v
|
1545
|
+
end
|
1546
|
+
end
|
1547
|
+
end
|
1548
|
+
|
1549
|
+
def execute(args)
|
1550
|
+
begin
|
1551
|
+
parser.parse!(args)
|
1552
|
+
rescue OptionParser::InvalidOption => error
|
1553
|
+
puts error
|
1554
|
+
usage
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
if File === ARGF.file
|
1558
|
+
@file = ARGF.file
|
1559
|
+
end
|
1560
|
+
|
1561
|
+
@processor = Processor.new
|
1562
|
+
|
1563
|
+
if @options[:data]
|
1564
|
+
@processor.data = @options[:data].lines.collect(&:chomp)
|
1565
|
+
end
|
1566
|
+
|
1567
|
+
if @options[:eval]
|
1568
|
+
@processor.assemble(@options[:eval])
|
1569
|
+
else
|
1570
|
+
@processor.assemble(ARGF.read.toutf8)
|
1571
|
+
end
|
1572
|
+
|
1573
|
+
if @file && @options[:output_map]
|
1574
|
+
@processor.create_map_file(file_name_of(:map))
|
1575
|
+
end
|
1576
|
+
|
1577
|
+
if @options[:go]
|
1578
|
+
@processor.go
|
1579
|
+
end
|
1580
|
+
|
1581
|
+
if @options[:print_map]
|
1582
|
+
puts @processor.disassemble
|
1583
|
+
end
|
1584
|
+
|
1585
|
+
if @options[:register]
|
1586
|
+
puts @processor.regs_info
|
1587
|
+
end
|
1588
|
+
|
1589
|
+
if @options[:simulator]
|
1590
|
+
@processor.simulator
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
|
1594
|
+
def usage
|
1595
|
+
puts "使い方: #{parser.program_name} [オプション] <ファイル>..."
|
1596
|
+
puts "`#{parser.program_name}' --help でより詳しい情報を表示します。"
|
1597
|
+
abort
|
1598
|
+
end
|
1599
|
+
|
1600
|
+
def file_name_of(extname)
|
1601
|
+
Pathname("#{Pathname(@file).basename(".*")}.#{extname}")
|
1602
|
+
end
|
1603
|
+
end
|
1604
|
+
end
|
1605
|
+
|
1606
|
+
if $0 == __FILE__
|
1607
|
+
if false
|
1608
|
+
Rasl.config.memory_size = 256
|
1609
|
+
object = Rasl::Processor.new
|
1610
|
+
object.assemble("
|
1611
|
+
A START
|
1612
|
+
RET
|
1613
|
+
A DS 1
|
1614
|
+
END
|
1615
|
+
A START
|
1616
|
+
RET
|
1617
|
+
A DS 1
|
1618
|
+
END
|
1619
|
+
|
1620
|
+
; IN A,B
|
1621
|
+
; IN A,B
|
1622
|
+
; IN A,B
|
1623
|
+
; RET
|
1624
|
+
;A DS 5
|
1625
|
+
;B DS 1
|
1626
|
+
;__END__
|
1627
|
+
;a
|
1628
|
+
;b
|
1629
|
+
")
|
1630
|
+
puts object.disassemble
|
1631
|
+
object.go
|
1632
|
+
p object.labels
|
1633
|
+
puts object.disassemble
|
1634
|
+
object.command_dump
|
1635
|
+
end
|
1636
|
+
|
1637
|
+
if true
|
1638
|
+
object = Rasl::Processor.new
|
1639
|
+
object.assemble("
|
1640
|
+
MAIN START
|
1641
|
+
CALL FGET
|
1642
|
+
RET
|
1643
|
+
END
|
1644
|
+
|
1645
|
+
FGET START
|
1646
|
+
EXIT LD GR1,GR7
|
1647
|
+
RET
|
1648
|
+
JUMP EXIT
|
1649
|
+
END
|
1650
|
+
")
|
1651
|
+
puts object.disassemble
|
1652
|
+
object.go
|
1653
|
+
p object.labels
|
1654
|
+
puts object.disassemble
|
1655
|
+
object.command_dump
|
1656
|
+
end
|
1657
|
+
end
|