wardite 0.2.0 → 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 +163 -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 +398 -18
- data/lib/wardite/alu_i64.generated.rb +514 -0
- data/lib/wardite/convert.generated.rb +234 -0
- data/lib/wardite/instruction.rb +62 -31
- data/lib/wardite/value.rb +576 -31
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi.rb +1 -1
- data/lib/wardite.rb +127 -77
- data/scripts/gen_alu.rb +653 -27
- data/scripts/gen_conv.rb +76 -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_i64.generated.rbs +11 -0
- data/sig/generated/wardite/convert.generated.rbs +11 -0
- data/sig/generated/wardite/instruction.rbs +6 -0
- data/sig/generated/wardite/value.rbs +263 -19
- data/sig/generated/wardite.rbs +12 -3
- metadata +13 -2
data/scripts/gen_alu.rb
CHANGED
@@ -21,9 +21,9 @@ module GenAlu
|
|
21
21
|
def self.generate_ops(prefix:, defined_ops:)
|
22
22
|
result = StringIO.new("")
|
23
23
|
defined_ops.each do |op|
|
24
|
-
code = DEFS[op.to_sym]
|
24
|
+
code = DEFS[op.to_sym].dup
|
25
25
|
if ! code
|
26
|
-
raise "unsupported code specified!"
|
26
|
+
raise "unsupported code specified! #{op.inspect}"
|
27
27
|
end
|
28
28
|
code.gsub!(/\$\{PREFIX\}/, prefix)
|
29
29
|
code.gsub!(/\$\{CLASS\}/, to_class(prefix.to_sym))
|
@@ -47,8 +47,295 @@ module GenAlu
|
|
47
47
|
|
48
48
|
# ope_templates
|
49
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
|
+
|
50
317
|
lts: <<~RUBY,
|
51
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
|
52
339
|
right, left = runtime.stack.pop, runtime.stack.pop
|
53
340
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
54
341
|
raise EvalError, "maybe empty or invalid stack"
|
@@ -57,8 +344,78 @@ module GenAlu
|
|
57
344
|
runtime.stack.push(I32(value))
|
58
345
|
RUBY
|
59
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
|
+
|
60
387
|
leu: <<~RUBY,
|
61
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
|
62
419
|
right, left = runtime.stack.pop, runtime.stack.pop
|
63
420
|
if !right.is_a?(${CLASS}) || !left.is_a?(${CLASS})
|
64
421
|
raise EvalError, "maybe empty or invalid stack"
|
@@ -67,6 +424,69 @@ module GenAlu
|
|
67
424
|
runtime.stack.push(I32(value))
|
68
425
|
RUBY
|
69
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
|
+
|
70
490
|
add: <<~RUBY,
|
71
491
|
when :${PREFIX}_add
|
72
492
|
right, left = runtime.stack.pop, runtime.stack.pop
|
@@ -85,40 +505,246 @@ module GenAlu
|
|
85
505
|
runtime.stack.push(${CLASS}(left.value - right.value))
|
86
506
|
RUBY
|
87
507
|
|
88
|
-
|
89
|
-
when :${PREFIX}
|
90
|
-
|
91
|
-
if !
|
92
|
-
raise EvalError, "
|
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"
|
93
513
|
end
|
94
|
-
runtime.stack.push(${CLASS}(
|
514
|
+
runtime.stack.push(${CLASS}(left.value * right.value))
|
95
515
|
RUBY
|
96
516
|
|
97
|
-
|
98
|
-
when :${PREFIX}
|
99
|
-
|
100
|
-
if !
|
101
|
-
raise EvalError, "
|
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"
|
102
522
|
end
|
103
|
-
runtime.stack.push(${CLASS}(
|
523
|
+
runtime.stack.push(${CLASS}(left.value_s / right.value_s))
|
104
524
|
RUBY
|
105
525
|
|
106
|
-
|
107
|
-
when :${PREFIX}
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
111
534
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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"
|
116
540
|
end
|
541
|
+
runtime.stack.push(${CLASS}(left.value / right.value))
|
542
|
+
RUBY
|
117
543
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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))
|
122
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
|
123
749
|
}
|
124
750
|
end
|