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.
@@ -0,0 +1,6 @@
1
+ START
2
+ OUT STR,LEN
3
+ RET
4
+ STR DC 'Hello'
5
+ LEN DC 5
6
+ END
@@ -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
@@ -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..
@@ -0,0 +1,17 @@
1
+ START
2
+ IN STR,LEN
3
+ OUT STR,LEN
4
+ IN STR,LEN
5
+ OUT STR,LEN
6
+ IN STR,LEN
7
+ OUT STR,LEN
8
+ IN STR,LEN
9
+ OUT STR,LEN
10
+ RET
11
+ STR DS 4
12
+ LEN DS 1
13
+ END
14
+ __END__
15
+ a
16
+
17
+ c
@@ -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
@@ -0,0 +1,2 @@
1
+ #!/bin/sh
2
+ echo *.csl | xargs -n 1 ../bin/rasl -pm
@@ -0,0 +1,7 @@
1
+ LD GR0,A
2
+ ADDA GR0,B
3
+ ST GR0,C
4
+ RET
5
+ A DC 1
6
+ B DC 2
7
+ C DS 1
@@ -0,0 +1,7 @@
1
+ 0000 1000 0007 LD GR0, #0007
2
+ 0002 2000 0008 ADDA GR0, #0008
3
+ 0004 1100 0009 ST GR0, #0009
4
+ 0006 8100 RET
5
+ 0007 0001 DC 1
6
+ 0008 0002 DC 2
7
+ 0009 0000 DC 0
@@ -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
@@ -0,0 +1,8 @@
1
+ MAIN START
2
+ LAD GR1,1
3
+ LAD GR2,2
4
+ PUSH 0,GR1
5
+ LD GR1,GR2
6
+ POP GR2
7
+ RET
8
+ END
@@ -0,0 +1,6 @@
1
+ 0000 1210 0001 LAD GR1, #0001
2
+ 0002 1220 0002 LAD GR2, #0002
3
+ 0004 7001 0000 PUSH #0000, GR1
4
+ 0006 1412 LD GR1, GR2
5
+ 0007 7120 POP GR2
6
+ 0008 8100 RET
@@ -0,0 +1,2 @@
1
+ RET
2
+ DC 'あ'
@@ -0,0 +1,4 @@
1
+ 0000 8100 RET
2
+ 0001 00E3 DC 227
3
+ 0002 0081 DC 129
4
+ 0003 0082 DC 130
@@ -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