wardite 0.1.2 → 0.2.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 +4 -4
- data/Rakefile +178 -0
- data/Steepfile +1 -0
- data/examples/consts.wat +12 -0
- data/lib/wardite/alu_f32.generated.rb +250 -0
- data/lib/wardite/alu_f64.generated.rb +250 -0
- data/lib/wardite/alu_i32.generated.rb +457 -0
- data/lib/wardite/alu_i64.generated.rb +514 -0
- data/lib/wardite/convert.generated.rb +234 -0
- data/lib/wardite/instruction.rb +82 -33
- data/lib/wardite/leb128.rb +1 -1
- data/lib/wardite/value.rb +627 -0
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +6 -4
- data/lib/wardite.rb +192 -115
- data/scripts/gen_alu.rb +750 -0
- data/scripts/gen_conv.rb +76 -0
- data/scripts/templates/alu_module.rb.tmpl +18 -0
- data/scripts/templates/conv_module.rb.tmpl +18 -0
- data/sig/generated/wardite/alu_f32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_f64.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i32.generated.rbs +11 -0
- data/sig/generated/wardite/alu_i64.generated.rbs +11 -0
- data/sig/generated/wardite/convert.generated.rbs +11 -0
- data/sig/generated/wardite/instruction.rbs +15 -6
- data/sig/generated/wardite/leb128.rbs +1 -1
- data/sig/generated/wardite/value.rbs +302 -0
- data/sig/generated/wardite/wasi.rbs +4 -2
- data/sig/generated/wardite.rbs +27 -12
- metadata +19 -2
data/scripts/gen_alu.rb
ADDED
@@ -0,0 +1,750 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
3
|
+
module GenAlu
|
4
|
+
def self.execute(path, prefix: "i32", defined_ops: [])
|
5
|
+
parent_dir = File.dirname(path)
|
6
|
+
system "mkdir -p #{parent_dir}"
|
7
|
+
|
8
|
+
basic_module = File.read(
|
9
|
+
File.expand_path("../templates/alu_module.rb.tmpl", __FILE__)
|
10
|
+
)
|
11
|
+
basic_module.gsub!(/\$\{PREFIX\}/, prefix)
|
12
|
+
ope_defs = generate_ops(prefix: prefix, defined_ops: defined_ops)
|
13
|
+
basic_module.gsub!(/\$\{DEFS\}/, ope_defs)
|
14
|
+
|
15
|
+
dest = File.open(path, "w")
|
16
|
+
dest.puts basic_module
|
17
|
+
|
18
|
+
$stderr.puts "generated: #{path}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.generate_ops(prefix:, defined_ops:)
|
22
|
+
result = StringIO.new("")
|
23
|
+
defined_ops.each do |op|
|
24
|
+
code = DEFS[op.to_sym].dup
|
25
|
+
if ! code
|
26
|
+
raise "unsupported code specified! #{op.inspect}"
|
27
|
+
end
|
28
|
+
code.gsub!(/\$\{PREFIX\}/, prefix)
|
29
|
+
code.gsub!(/\$\{CLASS\}/, to_class(prefix.to_sym))
|
30
|
+
result << "\n"
|
31
|
+
code.each_line do |ln|
|
32
|
+
result << " " * 6 << ln
|
33
|
+
end
|
34
|
+
result << "\n"
|
35
|
+
end
|
36
|
+
result.string
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.to_class(prefix)
|
40
|
+
{
|
41
|
+
i32: "I32",
|
42
|
+
i64: "I64",
|
43
|
+
f32: "F32",
|
44
|
+
f64: "F64",
|
45
|
+
}[prefix]
|
46
|
+
end
|
47
|
+
|
48
|
+
# ope_templates
|
49
|
+
DEFS = { #: Hash[Symbol, String]
|
50
|
+
load: <<~RUBY,
|
51
|
+
when :${PREFIX}_load
|
52
|
+
_align = insn.operand[0] # TODO: alignment support?
|
53
|
+
offset = insn.operand[1]
|
54
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
55
|
+
|
56
|
+
addr = runtime.stack.pop
|
57
|
+
if !addr.is_a?(I32)
|
58
|
+
raise EvalError, "maybe stack too short"
|
59
|
+
end
|
60
|
+
|
61
|
+
at = addr.value + offset
|
62
|
+
data_end = at + ${CLASS}.new.memsize / 8
|
63
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
64
|
+
buf = memory.data[at...data_end]
|
65
|
+
if !buf
|
66
|
+
raise EvalError, "invalid memory range"
|
67
|
+
end
|
68
|
+
runtime.stack.push(${CLASS}.from_bytes(buf))
|
69
|
+
RUBY
|
70
|
+
|
71
|
+
load8_s: <<~RUBY,
|
72
|
+
when :${PREFIX}_load8_s
|
73
|
+
_align = insn.operand[0] # TODO: alignment support?
|
74
|
+
offset = insn.operand[1]
|
75
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
76
|
+
|
77
|
+
addr = runtime.stack.pop
|
78
|
+
if !addr.is_a?(I32)
|
79
|
+
raise EvalError, "maybe stack too short"
|
80
|
+
end
|
81
|
+
|
82
|
+
at = addr.value + offset
|
83
|
+
data_end = at + 1
|
84
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
85
|
+
buf = memory.data[at...data_end]
|
86
|
+
if !buf
|
87
|
+
raise EvalError, "invalid memory range"
|
88
|
+
end
|
89
|
+
runtime.stack.push(${CLASS}.from_bytes(buf, size: 8, signed: true))
|
90
|
+
RUBY
|
91
|
+
|
92
|
+
load8_u: <<~RUBY,
|
93
|
+
when :${PREFIX}_load8_u
|
94
|
+
_align = insn.operand[0] # TODO: alignment support?
|
95
|
+
offset = insn.operand[1]
|
96
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
97
|
+
|
98
|
+
addr = runtime.stack.pop
|
99
|
+
if !addr.is_a?(I32)
|
100
|
+
raise EvalError, "maybe stack too short"
|
101
|
+
end
|
102
|
+
|
103
|
+
at = addr.value + offset
|
104
|
+
data_end = at + 1
|
105
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
106
|
+
buf = memory.data[at...data_end]
|
107
|
+
if !buf
|
108
|
+
raise EvalError, "invalid memory range"
|
109
|
+
end
|
110
|
+
runtime.stack.push(${CLASS}.from_bytes(buf, size: 8, signed: false))
|
111
|
+
RUBY
|
112
|
+
|
113
|
+
load16_s: <<~RUBY,
|
114
|
+
when :${PREFIX}_load16_s
|
115
|
+
_align = insn.operand[0] # TODO: alignment support?
|
116
|
+
offset = insn.operand[1]
|
117
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
118
|
+
|
119
|
+
addr = runtime.stack.pop
|
120
|
+
if !addr.is_a?(I32)
|
121
|
+
raise EvalError, "maybe stack too short"
|
122
|
+
end
|
123
|
+
|
124
|
+
at = addr.value + offset
|
125
|
+
data_end = at + 2
|
126
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
127
|
+
buf = memory.data[at...data_end]
|
128
|
+
if !buf
|
129
|
+
raise EvalError, "invalid memory range"
|
130
|
+
end
|
131
|
+
runtime.stack.push(${CLASS}.from_bytes(buf, size: 16, signed: true))
|
132
|
+
RUBY
|
133
|
+
|
134
|
+
load16_u: <<~RUBY,
|
135
|
+
when :${PREFIX}_load16_u
|
136
|
+
_align = insn.operand[0] # TODO: alignment support?
|
137
|
+
offset = insn.operand[1]
|
138
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
139
|
+
|
140
|
+
addr = runtime.stack.pop
|
141
|
+
if !addr.is_a?(I32)
|
142
|
+
raise EvalError, "maybe stack too short"
|
143
|
+
end
|
144
|
+
|
145
|
+
at = addr.value + offset
|
146
|
+
data_end = at + 2
|
147
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
148
|
+
buf = memory.data[at...data_end]
|
149
|
+
if !buf
|
150
|
+
raise EvalError, "invalid memory range"
|
151
|
+
end
|
152
|
+
runtime.stack.push(${CLASS}.from_bytes(buf, size: 16, signed: false))
|
153
|
+
RUBY
|
154
|
+
|
155
|
+
load32_s: <<~RUBY,
|
156
|
+
when :${PREFIX}_load32_s
|
157
|
+
_align = insn.operand[0] # TODO: alignment support?
|
158
|
+
offset = insn.operand[1]
|
159
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
160
|
+
|
161
|
+
addr = runtime.stack.pop
|
162
|
+
if !addr.is_a?(I32)
|
163
|
+
raise EvalError, "maybe stack too short"
|
164
|
+
end
|
165
|
+
|
166
|
+
at = addr.value + offset
|
167
|
+
data_end = at + 4
|
168
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
169
|
+
buf = memory.data[at...data_end]
|
170
|
+
if !buf
|
171
|
+
raise EvalError, "invalid memory range"
|
172
|
+
end
|
173
|
+
runtime.stack.push(${CLASS}.from_bytes(buf, size: 32, signed: true))
|
174
|
+
RUBY
|
175
|
+
|
176
|
+
load32_u: <<~RUBY,
|
177
|
+
when :${PREFIX}_load32_u
|
178
|
+
_align = insn.operand[0] # TODO: alignment support?
|
179
|
+
offset = insn.operand[1]
|
180
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
181
|
+
|
182
|
+
addr = runtime.stack.pop
|
183
|
+
if !addr.is_a?(I32)
|
184
|
+
raise EvalError, "maybe stack too short"
|
185
|
+
end
|
186
|
+
|
187
|
+
at = addr.value + offset
|
188
|
+
data_end = at + 4
|
189
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
190
|
+
buf = memory.data[at...data_end]
|
191
|
+
if !buf
|
192
|
+
raise EvalError, "invalid memory range"
|
193
|
+
end
|
194
|
+
runtime.stack.push(${CLASS}.from_bytes(buf, size: 32, signed: false))
|
195
|
+
RUBY
|
196
|
+
|
197
|
+
store: <<~RUBY,
|
198
|
+
when :${PREFIX}_store
|
199
|
+
_align = insn.operand[0] # TODO: alignment support?
|
200
|
+
offset = insn.operand[1]
|
201
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
202
|
+
|
203
|
+
value = runtime.stack.pop
|
204
|
+
addr = runtime.stack.pop
|
205
|
+
if !value.is_a?(${CLASS}) || !addr.is_a?(I32)
|
206
|
+
raise EvalError, "maybe stack too short"
|
207
|
+
end
|
208
|
+
|
209
|
+
at = addr.value + offset
|
210
|
+
data_end = at + value.packed.size
|
211
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
212
|
+
memory.data[at...data_end] = value.packed
|
213
|
+
RUBY
|
214
|
+
|
215
|
+
store8: <<~RUBY,
|
216
|
+
when :${PREFIX}_store8
|
217
|
+
_align = insn.operand[0] # TODO: alignment support?
|
218
|
+
offset = insn.operand[1]
|
219
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
220
|
+
|
221
|
+
value = runtime.stack.pop
|
222
|
+
addr = runtime.stack.pop
|
223
|
+
if !value.is_a?(${CLASS}) || !addr.is_a?(I32)
|
224
|
+
raise EvalError, "maybe stack too short"
|
225
|
+
end
|
226
|
+
|
227
|
+
at = addr.value + offset
|
228
|
+
data_end = at + 1
|
229
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
230
|
+
memory.data[at...data_end] = value.packed(size: 8)
|
231
|
+
RUBY
|
232
|
+
|
233
|
+
store16: <<~RUBY,
|
234
|
+
when :${PREFIX}_store16
|
235
|
+
_align = insn.operand[0] # TODO: alignment support?
|
236
|
+
offset = insn.operand[1]
|
237
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
238
|
+
|
239
|
+
value = runtime.stack.pop
|
240
|
+
addr = runtime.stack.pop
|
241
|
+
if !value.is_a?(${CLASS}) || !addr.is_a?(I32)
|
242
|
+
raise EvalError, "maybe stack too short"
|
243
|
+
end
|
244
|
+
|
245
|
+
at = addr.value + offset
|
246
|
+
data_end = at + 2
|
247
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
248
|
+
memory.data[at...data_end] = value.packed(size: 16)
|
249
|
+
RUBY
|
250
|
+
|
251
|
+
store32: <<~RUBY,
|
252
|
+
when :${PREFIX}_store32
|
253
|
+
_align = insn.operand[0] # TODO: alignment support?
|
254
|
+
offset = insn.operand[1]
|
255
|
+
raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
|
256
|
+
|
257
|
+
value = runtime.stack.pop
|
258
|
+
addr = runtime.stack.pop
|
259
|
+
if !value.is_a?(${CLASS}) || !addr.is_a?(I32)
|
260
|
+
raise EvalError, "maybe stack too short"
|
261
|
+
end
|
262
|
+
|
263
|
+
at = addr.value + offset
|
264
|
+
data_end = at + 4
|
265
|
+
memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
|
266
|
+
memory.data[at...data_end] = value.packed(size: 32)
|
267
|
+
RUBY
|
268
|
+
|
269
|
+
const: <<~RUBY,
|
270
|
+
when :${PREFIX}_const
|
271
|
+
const = insn.operand[0]
|
272
|
+
if !const.is_a?(Integer)
|
273
|
+
raise EvalError, "invalid type of operand"
|
274
|
+
end
|
275
|
+
runtime.stack.push(${CLASS}(const))
|
276
|
+
RUBY
|
277
|
+
|
278
|
+
const__f: <<~RUBY,
|
279
|
+
when :${PREFIX}_const
|
280
|
+
const = insn.operand[0]
|
281
|
+
if !const.is_a?(Float)
|
282
|
+
raise EvalError, "invalid type of operand"
|
283
|
+
end
|
284
|
+
runtime.stack.push(${CLASS}(const))
|
285
|
+
RUBY
|
286
|
+
|
287
|
+
eqz: <<~RUBY,
|
288
|
+
when :${PREFIX}_eqz
|
289
|
+
target = runtime.stack.pop
|
290
|
+
if !target.is_a?(${CLASS})
|
291
|
+
raise EvalError, "maybe empty or invalid stack"
|
292
|
+
end
|
293
|
+
value = target.value.zero? ? 1 : 0
|
294
|
+
runtime.stack.push(I32(value))
|
295
|
+
RUBY
|
296
|
+
|
297
|
+
eq: <<~RUBY,
|
298
|
+
when :${PREFIX}_eq
|
299
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
300
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
301
|
+
raise EvalError, "maybe empty or invalid stack"
|
302
|
+
end
|
303
|
+
value = (left.value == right.value) ? 1 : 0
|
304
|
+
runtime.stack.push(I32(value))
|
305
|
+
RUBY
|
306
|
+
|
307
|
+
ne: <<~RUBY,
|
308
|
+
when :${PREFIX}_ne
|
309
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
310
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
311
|
+
raise EvalError, "maybe empty or invalid stack"
|
312
|
+
end
|
313
|
+
value = (left.value != right.value) ? 1 : 0
|
314
|
+
runtime.stack.push(I32(value))
|
315
|
+
RUBY
|
316
|
+
|
317
|
+
lts: <<~RUBY,
|
318
|
+
when :${PREFIX}_lts
|
319
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
320
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
321
|
+
raise EvalError, "maybe empty or invalid stack"
|
322
|
+
end
|
323
|
+
value = (left.value_s < right.value_s) ? 1 : 0
|
324
|
+
runtime.stack.push(I32(value))
|
325
|
+
RUBY
|
326
|
+
|
327
|
+
ltu: <<~RUBY,
|
328
|
+
when :${PREFIX}_ltu
|
329
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
330
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
331
|
+
raise EvalError, "maybe empty or invalid stack"
|
332
|
+
end
|
333
|
+
value = (left.value < right.value) ? 1 : 0
|
334
|
+
runtime.stack.push(I32(value))
|
335
|
+
RUBY
|
336
|
+
|
337
|
+
lt: <<~RUBY,
|
338
|
+
when :${PREFIX}_lt
|
339
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
340
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
341
|
+
raise EvalError, "maybe empty or invalid stack"
|
342
|
+
end
|
343
|
+
value = (left.value < right.value) ? 1 : 0
|
344
|
+
runtime.stack.push(I32(value))
|
345
|
+
RUBY
|
346
|
+
|
347
|
+
gts: <<~RUBY,
|
348
|
+
when :${PREFIX}_gts
|
349
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
350
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
351
|
+
raise EvalError, "maybe empty or invalid stack"
|
352
|
+
end
|
353
|
+
value = (left.value_s > right.value_s) ? 1 : 0
|
354
|
+
runtime.stack.push(I32(value))
|
355
|
+
RUBY
|
356
|
+
|
357
|
+
gtu: <<~RUBY,
|
358
|
+
when :${PREFIX}_gtu
|
359
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
360
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
361
|
+
raise EvalError, "maybe empty or invalid stack"
|
362
|
+
end
|
363
|
+
value = (left.value > right.value) ? 1 : 0
|
364
|
+
runtime.stack.push(I32(value))
|
365
|
+
RUBY
|
366
|
+
|
367
|
+
gt: <<~RUBY,
|
368
|
+
when :${PREFIX}_gt
|
369
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
370
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
371
|
+
raise EvalError, "maybe empty or invalid stack"
|
372
|
+
end
|
373
|
+
value = (left.value > right.value) ? 1 : 0
|
374
|
+
runtime.stack.push(I32(value))
|
375
|
+
RUBY
|
376
|
+
|
377
|
+
les: <<~RUBY,
|
378
|
+
when :${PREFIX}_les
|
379
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
380
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
381
|
+
raise EvalError, "maybe empty or invalid stack"
|
382
|
+
end
|
383
|
+
value = (left.value_s <= right.value_s) ? 1 : 0
|
384
|
+
runtime.stack.push(I32(value))
|
385
|
+
RUBY
|
386
|
+
|
387
|
+
leu: <<~RUBY,
|
388
|
+
when :${PREFIX}_leu
|
389
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
390
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
391
|
+
raise EvalError, "maybe empty or invalid stack"
|
392
|
+
end
|
393
|
+
value = (left.value <= right.value) ? 1 : 0
|
394
|
+
runtime.stack.push(I32(value))
|
395
|
+
RUBY
|
396
|
+
|
397
|
+
le: <<~RUBY,
|
398
|
+
when :${PREFIX}_le
|
399
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
400
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
401
|
+
raise EvalError, "maybe empty or invalid stack"
|
402
|
+
end
|
403
|
+
value = (left.value <= right.value) ? 1 : 0
|
404
|
+
runtime.stack.push(I32(value))
|
405
|
+
RUBY
|
406
|
+
|
407
|
+
ges: <<~RUBY,
|
408
|
+
when :${PREFIX}_ges
|
409
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
410
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
411
|
+
raise EvalError, "maybe empty or invalid stack"
|
412
|
+
end
|
413
|
+
value = (left.value_s >= right.value_s) ? 1 : 0
|
414
|
+
runtime.stack.push(I32(value))
|
415
|
+
RUBY
|
416
|
+
|
417
|
+
geu: <<~RUBY,
|
418
|
+
when :${PREFIX}_geu
|
419
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
420
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
421
|
+
raise EvalError, "maybe empty or invalid stack"
|
422
|
+
end
|
423
|
+
value = (left.value >= right.value) ? 1 : 0
|
424
|
+
runtime.stack.push(I32(value))
|
425
|
+
RUBY
|
426
|
+
|
427
|
+
ge: <<~RUBY,
|
428
|
+
when :${PREFIX}_ge
|
429
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
430
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
431
|
+
raise EvalError, "maybe empty or invalid stack"
|
432
|
+
end
|
433
|
+
value = (left.value >= right.value) ? 1 : 0
|
434
|
+
runtime.stack.push(I32(value))
|
435
|
+
RUBY
|
436
|
+
|
437
|
+
clz: <<~RUBY,
|
438
|
+
when :${PREFIX}_clz
|
439
|
+
target = runtime.stack.pop
|
440
|
+
if !target.is_a?(${CLASS})
|
441
|
+
raise EvalError, "maybe empty or invalid stack"
|
442
|
+
end
|
443
|
+
start = target.memsize - 1
|
444
|
+
count = 0
|
445
|
+
while start > -1
|
446
|
+
if (target.value >> start).zero?
|
447
|
+
count += 1
|
448
|
+
start -= 1
|
449
|
+
else
|
450
|
+
break
|
451
|
+
end
|
452
|
+
end
|
453
|
+
runtime.stack.push(${CLASS}(count))
|
454
|
+
RUBY
|
455
|
+
|
456
|
+
ctz: <<~RUBY,
|
457
|
+
when :${PREFIX}_ctz
|
458
|
+
target = runtime.stack.pop
|
459
|
+
if !target.is_a?(${CLASS})
|
460
|
+
raise EvalError, "maybe empty or invalid stack"
|
461
|
+
end
|
462
|
+
finish = target.memsize
|
463
|
+
count = 0
|
464
|
+
while count < finish
|
465
|
+
if (target.value & (1 << count)).zero?
|
466
|
+
count += 1
|
467
|
+
else
|
468
|
+
break
|
469
|
+
end
|
470
|
+
end
|
471
|
+
runtime.stack.push(${CLASS}(count))
|
472
|
+
RUBY
|
473
|
+
|
474
|
+
popcnt: <<~RUBY,
|
475
|
+
when :${PREFIX}_popcnt
|
476
|
+
target = runtime.stack.pop
|
477
|
+
if !target.is_a?(${CLASS})
|
478
|
+
raise EvalError, "maybe empty or invalid stack"
|
479
|
+
end
|
480
|
+
digits = target.memsize
|
481
|
+
count = 0
|
482
|
+
digits.times do |i|
|
483
|
+
if (target.value & (1 << i)).zero?
|
484
|
+
count += 1
|
485
|
+
end
|
486
|
+
end
|
487
|
+
runtime.stack.push(${CLASS}(count))
|
488
|
+
RUBY
|
489
|
+
|
490
|
+
add: <<~RUBY,
|
491
|
+
when :${PREFIX}_add
|
492
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
493
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
494
|
+
raise EvalError, "maybe empty or invalid stack"
|
495
|
+
end
|
496
|
+
runtime.stack.push(${CLASS}(left.value + right.value))
|
497
|
+
RUBY
|
498
|
+
|
499
|
+
sub: <<~RUBY,
|
500
|
+
when :${PREFIX}_sub
|
501
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
502
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
503
|
+
raise EvalError, "maybe empty or invalid stack"
|
504
|
+
end
|
505
|
+
runtime.stack.push(${CLASS}(left.value - right.value))
|
506
|
+
RUBY
|
507
|
+
|
508
|
+
mul: <<~RUBY,
|
509
|
+
when :${PREFIX}_mul
|
510
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
511
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
512
|
+
raise EvalError, "maybe empty or invalid stack"
|
513
|
+
end
|
514
|
+
runtime.stack.push(${CLASS}(left.value * right.value))
|
515
|
+
RUBY
|
516
|
+
|
517
|
+
div_s: <<~RUBY,
|
518
|
+
when :${PREFIX}_div_s
|
519
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
520
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
521
|
+
raise EvalError, "maybe empty or invalid stack"
|
522
|
+
end
|
523
|
+
runtime.stack.push(${CLASS}(left.value_s / right.value_s))
|
524
|
+
RUBY
|
525
|
+
|
526
|
+
div_u: <<~RUBY,
|
527
|
+
when :${PREFIX}_div_u
|
528
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
529
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
530
|
+
raise EvalError, "maybe empty or invalid stack"
|
531
|
+
end
|
532
|
+
runtime.stack.push(${CLASS}(left.value / right.value))
|
533
|
+
RUBY
|
534
|
+
|
535
|
+
div: <<~RUBY,
|
536
|
+
when :${PREFIX}_div
|
537
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
538
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
539
|
+
raise EvalError, "maybe empty or invalid stack"
|
540
|
+
end
|
541
|
+
runtime.stack.push(${CLASS}(left.value / right.value))
|
542
|
+
RUBY
|
543
|
+
|
544
|
+
rem_s: <<~RUBY,
|
545
|
+
when :${PREFIX}_rem_s
|
546
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
547
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
548
|
+
raise EvalError, "maybe empty or invalid stack"
|
549
|
+
end
|
550
|
+
runtime.stack.push(${CLASS}(left.value_s % right.value_s))
|
551
|
+
RUBY
|
552
|
+
|
553
|
+
rem_u: <<~RUBY,
|
554
|
+
when :${PREFIX}_rem_u
|
555
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
556
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
557
|
+
raise EvalError, "maybe empty or invalid stack"
|
558
|
+
end
|
559
|
+
runtime.stack.push(${CLASS}(left.value % right.value))
|
560
|
+
RUBY
|
561
|
+
|
562
|
+
and: <<~RUBY,
|
563
|
+
when :${PREFIX}_and
|
564
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
565
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
566
|
+
raise EvalError, "maybe empty or invalid stack"
|
567
|
+
end
|
568
|
+
runtime.stack.push(${CLASS}(left.value & right.value))
|
569
|
+
RUBY
|
570
|
+
|
571
|
+
or: <<~RUBY,
|
572
|
+
when :${PREFIX}_or
|
573
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
574
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
575
|
+
raise EvalError, "maybe empty or invalid stack"
|
576
|
+
end
|
577
|
+
runtime.stack.push(${CLASS}(left.value | right.value))
|
578
|
+
RUBY
|
579
|
+
|
580
|
+
xor: <<~RUBY,
|
581
|
+
when :${PREFIX}_xor
|
582
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
583
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
584
|
+
raise EvalError, "maybe empty or invalid stack"
|
585
|
+
end
|
586
|
+
runtime.stack.push(${CLASS}(left.value ^ right.value))
|
587
|
+
RUBY
|
588
|
+
|
589
|
+
shl: <<~RUBY,
|
590
|
+
when :${PREFIX}_shl
|
591
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
592
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
593
|
+
raise EvalError, "maybe empty or invalid stack"
|
594
|
+
end
|
595
|
+
value = left.value << right.value
|
596
|
+
value %= (1 << right.memsize)
|
597
|
+
|
598
|
+
runtime.stack.push(${CLASS}(value))
|
599
|
+
RUBY
|
600
|
+
|
601
|
+
shr_s: <<~RUBY,
|
602
|
+
when :${PREFIX}_shr_s
|
603
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
604
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
605
|
+
raise EvalError, "maybe empty or invalid stack"
|
606
|
+
end
|
607
|
+
value = left.value_s >> right.value
|
608
|
+
runtime.stack.push(${CLASS}(value))
|
609
|
+
RUBY
|
610
|
+
|
611
|
+
shr_u: <<~RUBY,
|
612
|
+
when :${PREFIX}_shr_u
|
613
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
614
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
615
|
+
raise EvalError, "maybe empty or invalid stack"
|
616
|
+
end
|
617
|
+
value = left.value >> right.value
|
618
|
+
runtime.stack.push(${CLASS}(value))
|
619
|
+
RUBY
|
620
|
+
|
621
|
+
rotl: <<~RUBY,
|
622
|
+
when :${PREFIX}_rotl
|
623
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
624
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
625
|
+
raise EvalError, "maybe empty or invalid stack"
|
626
|
+
end
|
627
|
+
rotated = left.value << right.value
|
628
|
+
rest = left.value & (${CLASS}::${CLASS}_MAX << (right.memsize - right.value))
|
629
|
+
value = rotated | (rest >> (right.memsize - right.value))
|
630
|
+
runtime.stack.push(${CLASS}(value))
|
631
|
+
RUBY
|
632
|
+
|
633
|
+
rotr: <<~RUBY,
|
634
|
+
when :${PREFIX}_rotr
|
635
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
636
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
637
|
+
raise EvalError, "maybe empty or invalid stack"
|
638
|
+
end
|
639
|
+
rotated = left.value >> right.value
|
640
|
+
rest = left.value & (${CLASS}::${CLASS}_MAX >> (right.memsize - right.value))
|
641
|
+
value = rotated | (rest << (right.memsize - right.value))
|
642
|
+
runtime.stack.push(${CLASS}(value))
|
643
|
+
RUBY
|
644
|
+
|
645
|
+
# instructions for float
|
646
|
+
abs: <<~RUBY,
|
647
|
+
when :${PREFIX}_abs
|
648
|
+
x = runtime.stack.pop
|
649
|
+
if !x.is_a?(${CLASS})
|
650
|
+
raise EvalError, "maybe empty or invalid stack"
|
651
|
+
end
|
652
|
+
runtime.stack.push(${CLASS}(x.value.abs))
|
653
|
+
RUBY
|
654
|
+
|
655
|
+
neg: <<~RUBY,
|
656
|
+
when :${PREFIX}_neg
|
657
|
+
x = runtime.stack.pop
|
658
|
+
if !x.is_a?(${CLASS})
|
659
|
+
raise EvalError, "maybe empty or invalid stack"
|
660
|
+
end
|
661
|
+
runtime.stack.push(${CLASS}(-(x.value)))
|
662
|
+
RUBY
|
663
|
+
|
664
|
+
ceil: <<~RUBY,
|
665
|
+
when :${PREFIX}_ceil
|
666
|
+
x = runtime.stack.pop
|
667
|
+
if !x.is_a?(${CLASS})
|
668
|
+
raise EvalError, "maybe empty or invalid stack"
|
669
|
+
end
|
670
|
+
runtime.stack.push(${CLASS}(x.value.ceil.to_f))
|
671
|
+
RUBY
|
672
|
+
|
673
|
+
floor: <<~RUBY,
|
674
|
+
when :${PREFIX}_floor
|
675
|
+
x = runtime.stack.pop
|
676
|
+
if !x.is_a?(${CLASS})
|
677
|
+
raise EvalError, "maybe empty or invalid stack"
|
678
|
+
end
|
679
|
+
runtime.stack.push(${CLASS}(x.value.floor.to_f))
|
680
|
+
RUBY
|
681
|
+
|
682
|
+
trunc: <<~RUBY,
|
683
|
+
when :${PREFIX}_trunc
|
684
|
+
x = runtime.stack.pop
|
685
|
+
if !x.is_a?(${CLASS})
|
686
|
+
raise EvalError, "maybe empty or invalid stack"
|
687
|
+
end
|
688
|
+
runtime.stack.push(${CLASS}(x.value.to_i.to_f))
|
689
|
+
RUBY
|
690
|
+
|
691
|
+
nearest: <<~RUBY,
|
692
|
+
when :${PREFIX}_nearest
|
693
|
+
x = runtime.stack.pop
|
694
|
+
if !x.is_a?(${CLASS})
|
695
|
+
raise EvalError, "maybe empty or invalid stack"
|
696
|
+
end
|
697
|
+
runtime.stack.push(${CLASS}(x.value.round.to_f))
|
698
|
+
RUBY
|
699
|
+
|
700
|
+
sqrt: <<~RUBY,
|
701
|
+
when :${PREFIX}_sqrt
|
702
|
+
x = runtime.stack.pop
|
703
|
+
if !x.is_a?(${CLASS})
|
704
|
+
raise EvalError, "maybe empty or invalid stack"
|
705
|
+
end
|
706
|
+
runtime.stack.push(${CLASS}(x.value ** 0.5))
|
707
|
+
RUBY
|
708
|
+
|
709
|
+
min: <<~RUBY,
|
710
|
+
when :${PREFIX}_min
|
711
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
712
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
713
|
+
raise EvalError, "maybe empty or invalid stack"
|
714
|
+
end
|
715
|
+
if right.value.nan? || left.value.nan?
|
716
|
+
runtime.stack.push(${CLASS}(Float::NAN))
|
717
|
+
return
|
718
|
+
end
|
719
|
+
runtime.stack.push(${CLASS}([left.value, right.value].min))
|
720
|
+
RUBY
|
721
|
+
|
722
|
+
max: <<~RUBY,
|
723
|
+
when :${PREFIX}_max
|
724
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
725
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
726
|
+
raise EvalError, "maybe empty or invalid stack"
|
727
|
+
end
|
728
|
+
if right.value.nan? || left.value.nan?
|
729
|
+
runtime.stack.push(${CLASS}(Float::NAN))
|
730
|
+
return
|
731
|
+
end
|
732
|
+
runtime.stack.push(${CLASS}([left.value, right.value].max))
|
733
|
+
RUBY
|
734
|
+
|
735
|
+
copysign: <<~RUBY,
|
736
|
+
when :${PREFIX}_copysign
|
737
|
+
right, left = runtime.stack.pop, runtime.stack.pop
|
738
|
+
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
739
|
+
raise EvalError, "maybe empty or invalid stack"
|
740
|
+
end
|
741
|
+
if left.sign == right.sign
|
742
|
+
runtime.stack.push(${CLASS}(left.value))
|
743
|
+
else
|
744
|
+
runtime.stack.push(${CLASS}(-left.value))
|
745
|
+
end
|
746
|
+
RUBY
|
747
|
+
|
748
|
+
# ...end generative ops
|
749
|
+
}
|
750
|
+
end
|