wardite 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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