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.
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
- const: <<~RUBY,
89
- when :${PREFIX}_const
90
- const = insn.operand[0]
91
- if !const.is_a?(Integer)
92
- raise EvalError, "invalid type of operand"
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}(const))
514
+ runtime.stack.push(${CLASS}(left.value * right.value))
95
515
  RUBY
96
516
 
97
- const__f: <<~RUBY,
98
- when :${PREFIX}_const
99
- const = insn.operand[0]
100
- if !const.is_a?(Float)
101
- raise EvalError, "invalid type of operand"
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}(const))
523
+ runtime.stack.push(${CLASS}(left.value_s / right.value_s))
104
524
  RUBY
105
525
 
106
- store: <<~RUBY,
107
- when :${PREFIX}_store
108
- _align = insn.operand[0] # TODO: alignment support?
109
- offset = insn.operand[1]
110
- raise EvalError, "[BUG] invalid type of operand" if !offset.is_a?(Integer)
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
- value = runtime.stack.pop
113
- addr = runtime.stack.pop
114
- if !value.is_a?(${CLASS}) || !addr.is_a?(I32)
115
- raise EvalError, "maybe stack too short"
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
- at = addr.value + offset
119
- data_end = at + value.packed.size
120
- memory = runtime.instance.store.memories[0] || raise("[BUG] no memory")
121
- memory.data[at...data_end] = value.packed
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