1 //! Interpreter tests.
2
3 use interp::Val;
4 use pulley_interpreter::{
5 interp::{DoneReason, Vm},
6 *,
7 };
8 use std::{cell::UnsafeCell, fmt::Debug, ptr::NonNull};
9
encoded(ops: &[Op]) -> Vec<u8>10 fn encoded(ops: &[Op]) -> Vec<u8> {
11 let mut encoded = vec![];
12 for op in ops {
13 op.encode(&mut encoded);
14 }
15 log::trace!("encoded: {encoded:?}");
16 encoded
17 }
18
run(vm: &mut Vm, ops: &[Op]) -> Result<(), NonNull<u8>>19 unsafe fn run(vm: &mut Vm, ops: &[Op]) -> Result<(), NonNull<u8>> {
20 let _ = env_logger::try_init();
21 let ops = encoded(ops);
22 match unsafe { vm.call(NonNull::from(&ops[..]).cast(), &[], []) } {
23 DoneReason::ReturnToHost(_) => Ok(()),
24 DoneReason::Trap { pc, .. } => Err(pc),
25 DoneReason::CallIndirectHost { .. } => unimplemented!(),
26 }
27 }
28
assert_one<R0, R1, V>( xs: impl IntoIterator<Item = (R0, V)>, op: impl Into<Op> + Debug, result: R1, expected: u64, ) where R0: Into<AnyReg>, R1: Into<AnyReg>, V: Into<Val>,29 unsafe fn assert_one<R0, R1, V>(
30 xs: impl IntoIterator<Item = (R0, V)>,
31 op: impl Into<Op> + Debug,
32 result: R1,
33 expected: u64,
34 ) where
35 R0: Into<AnyReg>,
36 R1: Into<AnyReg>,
37 V: Into<Val>,
38 {
39 eprintln!("=======================================================");
40 let mut vm = Vm::new().unwrap();
41
42 for (reg, val) in xs {
43 let reg = reg.into();
44 let val = val.into();
45 eprintln!("{reg} = {val:#018x}");
46 match (reg, val) {
47 (AnyReg::X(r), Val::XReg(v)) => vm.state_mut()[r] = v,
48 (AnyReg::F(r), Val::FReg(v)) => vm.state_mut()[r] = v,
49 (AnyReg::V(_), Val::VReg(_)) => todo!(),
50 (kind, val) => panic!("register kind and value mismatch: {kind:?} and {val:?}"),
51 }
52 }
53
54 eprintln!("op = {op:?}");
55 let op = op.into();
56
57 unsafe {
58 run(&mut vm, &[op, Op::Ret(Ret {})]).expect("should not trap");
59 }
60
61 eprintln!("expected = {expected:#018x}");
62
63 let actual = match result.into() {
64 AnyReg::X(r) => vm.state_mut()[r].get_u64(),
65 AnyReg::F(r) => vm.state_mut()[r].get_f64().to_bits(),
66 AnyReg::V(_) => todo!(),
67 };
68 eprintln!("actual = {actual:#018x}");
69
70 assert_eq!(expected, actual);
71 }
72
x(x: u8) -> XReg73 fn x(x: u8) -> XReg {
74 XReg::new(x).unwrap()
75 }
76
f(f: u8) -> FReg77 fn f(f: u8) -> FReg {
78 FReg::new(f).unwrap()
79 }
80
81 #[test]
xconst8()82 fn xconst8() {
83 for (expected, imm) in [(42u64, 42i8), (u64::MAX, -1i8)] {
84 unsafe {
85 assert_one(
86 [(x(0), 0x1234567812345678u64)],
87 Xconst8 { dst: x(0), imm },
88 x(0),
89 expected,
90 );
91 }
92 }
93 }
94
95 #[test]
xconst16()96 fn xconst16() {
97 for (expected, imm) in [(42u64, 42i16), (u64::MAX, -1i16)] {
98 unsafe {
99 assert_one(
100 [(x(0), 0x1234567812345678u64)],
101 Xconst16 { dst: x(0), imm },
102 x(0),
103 expected,
104 );
105 }
106 }
107 }
108
109 #[test]
xconst32()110 fn xconst32() {
111 for (expected, imm) in [(42u64, 42i32), (u64::MAX, -1i32)] {
112 unsafe {
113 assert_one(
114 [(x(0), 0x1234567812345678u64)],
115 Xconst32 { dst: x(0), imm },
116 x(0),
117 expected,
118 );
119 }
120 }
121 }
122
123 #[test]
xconst64()124 fn xconst64() {
125 for (expected, imm) in [(42u64, 42i64), (u64::MAX, -1i64)] {
126 unsafe {
127 assert_one(
128 [(x(0), 0x1234567812345678u64)],
129 Xconst64 { dst: x(0), imm },
130 x(0),
131 expected,
132 );
133 }
134 }
135 }
136
137 #[test]
xadd32()138 fn xadd32() {
139 for (expected, a, b) in [
140 (42u64 | 0x1234567800000000, 10u64, 32u64),
141 (0x1234567800000000, u32::MAX as _, 1),
142 ] {
143 unsafe {
144 assert_one(
145 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
146 Xadd32 {
147 operands: BinaryOperands {
148 dst: x(0),
149 src1: x(1),
150 src2: x(2),
151 },
152 },
153 x(0),
154 expected,
155 );
156 }
157 }
158 }
159
160 #[test]
xadd64()161 fn xadd64() {
162 for (expected, a, b) in [(42u64, 10u64, 32u64), (0, u64::MAX, 1)] {
163 unsafe {
164 assert_one(
165 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
166 Xadd64 {
167 operands: BinaryOperands {
168 dst: x(0),
169 src1: x(1),
170 src2: x(2),
171 },
172 },
173 x(0),
174 expected,
175 );
176 }
177 }
178 }
179
180 #[test]
xeq64()181 fn xeq64() {
182 for (expected, a, b) in [
183 (1u64, 0u64, 0u64),
184 (0, 0, 1),
185 (1, u64::MAX, u64::MAX),
186 (0, u64::MAX, u64::MAX - 1),
187 ] {
188 unsafe {
189 assert_one(
190 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
191 Xeq64 {
192 operands: BinaryOperands {
193 dst: x(0),
194 src1: x(1),
195 src2: x(2),
196 },
197 },
198 x(0),
199 expected | 0x1234567800000000,
200 );
201 }
202 }
203 }
204
205 #[test]
xneq64()206 fn xneq64() {
207 for (expected, a, b) in [
208 (0u64, 0u64, 0u64),
209 (1, 0, 1),
210 (0, u64::MAX, u64::MAX),
211 (1, u64::MAX, u64::MAX - 1),
212 ] {
213 unsafe {
214 assert_one(
215 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
216 Xneq64 {
217 operands: BinaryOperands {
218 dst: x(0),
219 src1: x(1),
220 src2: x(2),
221 },
222 },
223 x(0),
224 expected | 0x1234567800000000,
225 );
226 }
227 }
228 }
229
230 #[test]
xslt64()231 fn xslt64() {
232 for (expected, a, b) in [
233 (0u64, 0u64, 0u64),
234 (0, 1, 0),
235 (1, 0, 1),
236 (0, 0, -1 as _),
237 (1, -1 as _, 0),
238 (0, i64::MAX as u64, i64::MAX as u64),
239 (0, i64::MAX as u64, i64::MAX as u64 - 1),
240 (1, i64::MAX as u64 - 1, i64::MAX as u64),
241 (0, i64::MIN as u64, i64::MIN as u64),
242 (0, i64::MIN as u64 + 1, i64::MIN as u64),
243 (1, i64::MIN as u64, i64::MIN as u64 + 1),
244 ] {
245 unsafe {
246 assert_one(
247 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
248 Xslt64 {
249 operands: BinaryOperands {
250 dst: x(0),
251 src1: x(1),
252 src2: x(2),
253 },
254 },
255 x(0),
256 expected | 0x1234567800000000,
257 );
258 }
259 }
260 }
261
262 #[test]
xslteq64()263 fn xslteq64() {
264 for (expected, a, b) in [
265 (1u64, 0u64, 0u64),
266 (0, 1, 0),
267 (1, 0, 1),
268 (0, 0, -1 as _),
269 (1, -1 as _, 0),
270 (1, i64::MAX as u64, i64::MAX as u64),
271 (0, i64::MAX as u64, i64::MAX as u64 - 1),
272 (1, i64::MAX as u64 - 1, i64::MAX as u64),
273 (1, i64::MIN as u64, i64::MIN as u64),
274 (0, i64::MIN as u64 + 1, i64::MIN as u64),
275 (1, i64::MIN as u64, i64::MIN as u64 + 1),
276 ] {
277 unsafe {
278 assert_one(
279 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
280 Xslteq64 {
281 operands: BinaryOperands {
282 dst: x(0),
283 src1: x(1),
284 src2: x(2),
285 },
286 },
287 x(0),
288 expected | 0x1234567800000000,
289 );
290 }
291 }
292 }
293
294 #[test]
xult64()295 fn xult64() {
296 for (expected, a, b) in [
297 (0u64, 0u64, 0u64),
298 (0, 1, 0),
299 (1, 0, 1),
300 (0, u64::MAX, u64::MAX),
301 (0, u64::MAX, u64::MAX - 1),
302 (1, u64::MAX - 1, u64::MAX),
303 (0, i64::MIN as u64, 0),
304 (1, 0, i64::MIN as u64),
305 ] {
306 unsafe {
307 assert_one(
308 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
309 Xult64 {
310 operands: BinaryOperands {
311 dst: x(0),
312 src1: x(1),
313 src2: x(2),
314 },
315 },
316 x(0),
317 expected | 0x1234567800000000,
318 );
319 }
320 }
321 }
322
323 #[test]
xulteq64()324 fn xulteq64() {
325 for (expected, a, b) in [
326 (1u64, 0u64, 0u64),
327 (0, 1, 0),
328 (1, 0, 1),
329 (1, u64::MAX, u64::MAX),
330 (0, u64::MAX, u64::MAX - 1),
331 (1, u64::MAX - 1, u64::MAX),
332 (0, i64::MIN as u64, 0),
333 (1, 0, i64::MIN as u64),
334 ] {
335 unsafe {
336 assert_one(
337 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
338 Xulteq64 {
339 operands: BinaryOperands {
340 dst: x(0),
341 src1: x(1),
342 src2: x(2),
343 },
344 },
345 x(0),
346 expected | 0x1234567800000000,
347 );
348 }
349 }
350 }
351
352 #[test]
xeq32()353 fn xeq32() {
354 for (expected, a, b) in [
355 (1u64, 0u64, 0u64),
356 (0, 0, 1),
357 (1, u64::MAX, u64::MAX),
358 (0, u64::MAX, u64::MAX - 1),
359 (1, 0xffffffff00000001, 1),
360 (0, 0xffffffff00000000, 1),
361 (0, 0xffffffff00000001, 0),
362 (1, 0xffffffff00000000, 0),
363 ] {
364 unsafe {
365 assert_one(
366 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
367 Xeq32 {
368 operands: BinaryOperands {
369 dst: x(0),
370 src1: x(1),
371 src2: x(2),
372 },
373 },
374 x(0),
375 expected | 0x1234567800000000,
376 );
377 }
378 }
379 }
380
381 #[test]
xneq32()382 fn xneq32() {
383 for (expected, a, b) in [
384 (0u64, 0u64, 0u64),
385 (1, 0, 1),
386 (0, u64::MAX, u64::MAX),
387 (1, u64::MAX, u64::MAX - 1),
388 (0, 0xffffffff00000000, 0),
389 ] {
390 unsafe {
391 assert_one(
392 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
393 Xneq32 {
394 operands: BinaryOperands {
395 dst: x(0),
396 src1: x(1),
397 src2: x(2),
398 },
399 },
400 x(0),
401 expected | 0x1234567800000000,
402 );
403 }
404 }
405 }
406
407 #[test]
xslt32()408 fn xslt32() {
409 for (expected, a, b) in [
410 (0u64, 0u64, 0u64),
411 (0, 1, 0),
412 (1, 0, 1),
413 (0, 0, -1 as _),
414 (1, -1 as _, 0),
415 (0, i64::MAX as u64, i64::MAX as u64),
416 (0, i64::MAX as u64, i64::MAX as u64 - 1),
417 (1, i64::MAX as u64 - 1, i64::MAX as u64),
418 (0, i64::MIN as u64, i64::MIN as u64),
419 (0, i64::MIN as u64 + 1, i64::MIN as u64),
420 (1, i64::MIN as u64, i64::MIN as u64 + 1),
421 (1, 0x00000000ffffffff, 0),
422 (0, 0, 0x00000000ffffffff),
423 ] {
424 unsafe {
425 assert_one(
426 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
427 Xslt32 {
428 operands: BinaryOperands {
429 dst: x(0),
430 src1: x(1),
431 src2: x(2),
432 },
433 },
434 x(0),
435 expected | 0x1234567800000000,
436 );
437 }
438 }
439 }
440
441 #[test]
xslteq32()442 fn xslteq32() {
443 for (expected, a, b) in [
444 (1u64, 0u64, 0u64),
445 (0, 1, 0),
446 (1, 0, 1),
447 (0, 0, -1 as _),
448 (1, -1 as _, 0),
449 (1, i64::MAX as u64, i64::MAX as u64),
450 (0, i64::MAX as u64, i64::MAX as u64 - 1),
451 (1, i64::MAX as u64 - 1, i64::MAX as u64),
452 (1, i64::MIN as u64, i64::MIN as u64),
453 (0, i64::MIN as u64 + 1, i64::MIN as u64),
454 (1, i64::MIN as u64, i64::MIN as u64 + 1),
455 ] {
456 unsafe {
457 assert_one(
458 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
459 Xslteq32 {
460 operands: BinaryOperands {
461 dst: x(0),
462 src1: x(1),
463 src2: x(2),
464 },
465 },
466 x(0),
467 expected | 0x1234567800000000,
468 );
469 }
470 }
471 }
472
473 #[test]
xult32()474 fn xult32() {
475 for (expected, a, b) in [
476 (0u64, 0u64, 0u64),
477 (0, 1, 0),
478 (1, 0, 1),
479 (0, 0x00000000ffffffff, 0xfffffffffffffffe),
480 (1, 0xfffffffffffffffe, 0x00000000ffffffff),
481 (0, 0x00000000ffffffff, 0xffffffffffffffff),
482 (0, 0xfffffffffffffffe, 0x00000000fffffffe),
483 ] {
484 unsafe {
485 assert_one(
486 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
487 Xult32 {
488 operands: BinaryOperands {
489 dst: x(0),
490 src1: x(1),
491 src2: x(2),
492 },
493 },
494 x(0),
495 expected | 0x1234567800000000,
496 );
497 }
498 }
499 }
500
501 #[test]
xulteq32()502 fn xulteq32() {
503 for (expected, a, b) in [
504 (1u64, 0u64, 0u64),
505 (0, 1, 0),
506 (1, 0, 1),
507 (0, 0x00000000ffffffff, 0xfffffffffffffffe),
508 (1, 0xfffffffffffffffe, 0x00000000ffffffff),
509 (1, 0x00000000ffffffff, 0xffffffffffffffff),
510 (1, 0xfffffffffffffffe, 0x00000000fffffffe),
511 ] {
512 unsafe {
513 assert_one(
514 [(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
515 Xulteq32 {
516 operands: BinaryOperands {
517 dst: x(0),
518 src1: x(1),
519 src2: x(2),
520 },
521 },
522 x(0),
523 expected | 0x1234567800000000,
524 );
525 }
526 }
527 }
528
529 #[test]
xload32le_o32()530 fn xload32le_o32() {
531 let a = UnsafeCell::new([11u32.to_le(), 22u32.to_le()]);
532 let b = UnsafeCell::new([33u32.to_le(), 44u32.to_le()]);
533 let c = UnsafeCell::new([55u32.to_le(), 66u32.to_le()]);
534 let d = UnsafeCell::new([(i32::MIN as u32).to_le(), (i32::MAX as u32).to_le()]);
535
536 for (expected, addr, offset) in [
537 (11, a.get(), 0),
538 (22, a.get(), 4),
539 (33, b.get(), 0),
540 (44, b.get(), 4),
541 (55, c.get(), 0),
542 (66, c.get(), 4),
543 (i32::MIN as u32 as u64, d.get(), 0),
544 (i32::MAX as u32 as u64, d.get(), 4),
545 ] {
546 let init = 0x1234567812345678u64;
547 let expected = init & !u64::from(u32::MAX) | expected;
548 unsafe {
549 assert_one(
550 [
551 (x(0), Val::from(init)),
552 (x(1), Val::from(addr.cast::<u8>())),
553 ],
554 XLoad32LeO32 {
555 dst: x(0),
556 addr: AddrO32 { addr: x(1), offset },
557 },
558 x(0),
559 expected,
560 );
561 }
562 }
563 }
564
565 #[test]
xload64le_o32()566 fn xload64le_o32() {
567 let a = UnsafeCell::new([11u64.to_le(), 22u64.to_le()]);
568 let b = UnsafeCell::new([33u64.to_le(), 44u64.to_le()]);
569 let c = UnsafeCell::new([55u64.to_le(), 66u64.to_le()]);
570 let d = UnsafeCell::new([(-1i64 as u64).to_le(), (i64::MAX as u64).to_le()]);
571
572 for (expected, addr, offset) in [
573 (11, a.get(), 0),
574 (22, a.get(), 8),
575 (33, b.get(), 0),
576 (44, b.get(), 8),
577 (55, c.get(), 0),
578 (66, c.get(), 8),
579 (-1i64 as u64, d.get(), 0),
580 (i64::MAX as u64, d.get(), 8),
581 ] {
582 unsafe {
583 assert_one(
584 [
585 (x(0), Val::from(0x1234567812345678u64)),
586 (x(1), Val::from(addr)),
587 ],
588 XLoad64LeO32 {
589 dst: x(0),
590 addr: AddrO32 { addr: x(1), offset },
591 },
592 x(0),
593 expected,
594 );
595 }
596 }
597 }
598
599 #[test]
xstore32_le_o32()600 fn xstore32_le_o32() {
601 let a = UnsafeCell::new([0x12u8, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]);
602 let b = UnsafeCell::new([0x12u8, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]);
603 let c = UnsafeCell::new([0x12u8, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]);
604
605 unsafe {
606 for (val, addr, offset) in [
607 (0x11111111u32, a.get(), 0),
608 (0x22222222, b.get(), 4),
609 (0x33333333, c.get(), 2),
610 ] {
611 let val = val as u64;
612 assert_one(
613 [(x(0), Val::from(addr)), (x(1), Val::from(val))],
614 XStore32LeO32 {
615 addr: AddrO32 { addr: x(0), offset },
616 src: x(1),
617 },
618 x(1),
619 val,
620 );
621 }
622 }
623
624 let a = u64::from_be_bytes(a.into_inner());
625 let expected = 0x1111111112345678u64;
626 eprintln!("expected(a) = {expected:#018x}");
627 eprintln!("actual(a) = {a:#018x}");
628 assert_eq!(a, expected);
629
630 let b = u64::from_be_bytes(b.into_inner());
631 let expected = 0x1234567822222222u64;
632 eprintln!("expected(b) = {expected:#018x}");
633 eprintln!("actual(b) = {b:#018x}");
634 assert_eq!(b, expected);
635
636 let c = u64::from_be_bytes(c.into_inner());
637 let expected = 0x1234333333335678u64;
638 eprintln!("expected(c) = {expected:#018x}");
639 eprintln!("actual(c) = {c:#018x}");
640 assert_eq!(c, expected);
641 }
642
643 #[test]
644
xstore64_le_o32()645 fn xstore64_le_o32() {
646 let a = UnsafeCell::new([0x1234567812345678, 0x1234567812345678, 0x1234567812345678]);
647
648 unsafe {
649 for (val, addr, offset) in [
650 (0x1111111111111111u64, a.get(), 0),
651 (0x2222222222222222, a.get(), 8),
652 (0x3333333333333333, a.get(), 16),
653 ] {
654 assert_one(
655 [(x(0), Val::from(addr)), (x(1), Val::from(val))],
656 XStore64LeO32 {
657 src: x(1),
658 addr: AddrO32 { addr: x(0), offset },
659 },
660 x(1),
661 val,
662 );
663 }
664 }
665
666 let [a, b, c] = a.into_inner();
667
668 let expected = 0x1111111111111111u64;
669 eprintln!("expected(a) = {expected:#018x}");
670 eprintln!("actual(a) = {a:#018x}");
671 assert_eq!(a, expected);
672
673 let expected = 0x2222222222222222u64;
674 eprintln!("expected(b) = {expected:#018x}");
675 eprintln!("actual(b) = {b:#018x}");
676 assert_eq!(b, expected);
677
678 let expected = 0x3333333333333333u64;
679 eprintln!("expected(c) = {expected:#018x}");
680 eprintln!("actual(c) = {c:#018x}");
681 assert_eq!(c, expected);
682 }
683
684 #[test]
bitcast_int_from_float_32()685 fn bitcast_int_from_float_32() {
686 for val in [
687 0.0,
688 1.0,
689 9.87654321,
690 f32::MAX,
691 f32::MIN,
692 f32::NAN,
693 f32::INFINITY,
694 f32::NEG_INFINITY,
695 f32::EPSILON,
696 f32::MIN_POSITIVE,
697 ] {
698 unsafe {
699 assert_one(
700 [(f(0), val)],
701 BitcastIntFromFloat32 {
702 dst: x(0),
703 src: f(0),
704 },
705 x(0),
706 val.to_bits() as u64,
707 );
708 }
709 }
710 }
711
712 #[test]
bitcast_int_from_float_64()713 fn bitcast_int_from_float_64() {
714 for val in [
715 0.0,
716 1.0,
717 9.87654321,
718 f64::MAX,
719 f64::MIN,
720 f64::NAN,
721 f64::INFINITY,
722 f64::NEG_INFINITY,
723 f64::EPSILON,
724 f64::MIN_POSITIVE,
725 ] {
726 unsafe {
727 assert_one(
728 [(f(0), val)],
729 BitcastIntFromFloat64 {
730 dst: x(0),
731 src: f(0),
732 },
733 x(0),
734 val.to_bits(),
735 );
736 }
737 }
738 }
739
740 #[test]
bitcast_float_from_int_32()741 fn bitcast_float_from_int_32() {
742 for val in [
743 0.0,
744 1.0,
745 9.87654321,
746 f32::MAX,
747 f32::MIN,
748 f32::NAN,
749 f32::INFINITY,
750 f32::NEG_INFINITY,
751 f32::EPSILON,
752 f32::MIN_POSITIVE,
753 ] {
754 let val = val.to_bits() as u64;
755 unsafe {
756 assert_one(
757 [(x(0), val)],
758 BitcastFloatFromInt32 {
759 dst: f(0),
760 src: x(0),
761 },
762 f(0),
763 val,
764 );
765 }
766 }
767 }
768
769 #[test]
bitcast_float_from_int_64()770 fn bitcast_float_from_int_64() {
771 for val in [
772 0.0,
773 1.0,
774 9.87654321,
775 f64::MAX,
776 f64::MIN,
777 f64::NAN,
778 f64::INFINITY,
779 f64::NEG_INFINITY,
780 f64::EPSILON,
781 f64::MIN_POSITIVE,
782 ] {
783 let val = val.to_bits();
784 unsafe {
785 assert_one(
786 [(x(0), val)],
787 BitcastFloatFromInt64 {
788 dst: f(0),
789 src: x(0),
790 },
791 f(0),
792 val,
793 );
794 }
795 }
796 }
797
798 #[test]
trap()799 fn trap() {
800 let mut vm = Vm::new().unwrap();
801 let dst = XReg::new(0).unwrap();
802
803 unsafe {
804 run(
805 &mut vm,
806 &[
807 Op::Xconst16(Xconst16 { dst, imm: 1 }),
808 Op::ExtendedOp(ExtendedOp::Trap(Trap {})),
809 Op::Xconst16(Xconst16 { dst, imm: 2 }),
810 Op::Ret(Ret {}),
811 ],
812 )
813 .unwrap_err();
814 }
815
816 // `dst` should not have been written to the second time.
817 assert_eq!(vm.state()[dst].get_u32(), 1);
818 }
819