Browse Source

pulley: use `Index{Mut}` instead of getters and setters (#9097)

Use the `Index` and `IndexMut` traits for accessing registers, rather
than having to define getters and setters for every register class.

Copyright (c) 2024, Arm Limited.

Signed-off-by: Karl Meakin <karl.meakin@arm.com>
pull/9105/head
Karl Meakin 3 months ago
committed by GitHub
parent
commit
e6c532fe01
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 341
      pulley/src/interp.rs
  2. 10
      pulley/tests/all/interp.rs

341
pulley/src/interp.rs

@ -8,6 +8,7 @@ use alloc::string::ToString;
use alloc::{vec, vec::Vec};
use core::fmt;
use core::mem;
use core::ops::{Index, IndexMut};
use core::ptr::{self, NonNull};
use sptr::Strict;
@ -82,15 +83,15 @@ impl Vm {
for arg in args {
match arg {
Val::XReg(val) => match x_args.next() {
Some(reg) => self.state.set_x(reg, *val),
Some(reg) => self.state[reg] = *val,
None => todo!("stack slots"),
},
Val::FReg(val) => match f_args.next() {
Some(reg) => self.state.set_f(reg, *val),
Some(reg) => self.state[reg] = *val,
None => todo!("stack slots"),
},
Val::VReg(val) => match v_args.next() {
Some(reg) => self.state.set_v(reg, *val),
Some(reg) => self.state[reg] = *val,
None => todo!("stack slots"),
},
}
@ -104,15 +105,15 @@ impl Vm {
Ok(rets.into_iter().map(move |ty| match ty {
RegType::XReg => match x_rets.next() {
Some(reg) => Val::XReg(self.state.get_x(reg)),
Some(reg) => Val::XReg(self.state[reg]),
None => todo!("stack slots"),
},
RegType::FReg => match f_rets.next() {
Some(reg) => Val::FReg(self.state.get_f(reg)),
Some(reg) => Val::FReg(self.state[reg]),
None => todo!("stack slots"),
},
RegType::VReg => match v_rets.next() {
Some(reg) => Val::VReg(self.state.get_v(reg)),
Some(reg) => Val::VReg(self.state[reg]),
None => todo!("stack slots"),
},
}))
@ -524,6 +525,28 @@ impl fmt::Debug for MachineState {
}
}
macro_rules! index_reg {
($reg_ty:ty,$value_ty:ty,$field:ident) => {
impl Index<$reg_ty> for MachineState {
type Output = $value_ty;
fn index(&self, reg: $reg_ty) -> &Self::Output {
&self.$field[reg.index()]
}
}
impl IndexMut<$reg_ty> for MachineState {
fn index_mut(&mut self, reg: $reg_ty) -> &mut Self::Output {
&mut self.$field[reg.index()]
}
}
};
}
index_reg!(XReg, XRegVal, x_regs);
index_reg!(FReg, FRegVal, f_regs);
index_reg!(VReg, VRegVal, v_regs);
impl MachineState {
fn with_stack(stack: Vec<u8>) -> Self {
assert!(stack.len() > 0);
@ -540,102 +563,13 @@ impl MachineState {
let sp = &mut state.stack[..];
let sp = sp.as_mut_ptr();
let sp = unsafe { sp.add(len) };
state.set_x(XReg::SP, XRegVal::new_ptr(sp));
state[XReg::SP] = XRegVal::new_ptr(sp);
state.set_x(XReg::FP, XRegVal::new_i64(-1));
state.set_x(XReg::LR, XRegVal::new_i64(-1));
state[XReg::FP] = XRegVal::new_i64(-1);
state[XReg::LR] = XRegVal::new_i64(-1);
state
}
/// Get a shared reference to the value of the given `x` register.
#[inline(always)]
pub fn x(&self, x: XReg) -> &XRegVal {
debug_assert!(x.index() < self.x_regs.len());
unsafe { self.x_regs.get_unchecked(x.index()) }
}
/// Get an exclusive reference to the value of the given `x` register.
#[inline(always)]
pub fn x_mut(&mut self, x: XReg) -> &mut XRegVal {
debug_assert!(x.index() < self.x_regs.len());
unsafe { self.x_regs.get_unchecked_mut(x.index()) }
}
/// Copy the value of the given `x` register.
#[inline(always)]
pub fn get_x(&self, x: XReg) -> XRegVal {
*self.x(x)
}
/// Set the value of the given `x` register.
#[inline(always)]
pub fn set_x(&mut self, x: XReg, val: XRegVal) {
debug_assert!(x.index() < self.x_regs.len());
unsafe {
*self.x_regs.get_unchecked_mut(x.index()) = val;
}
}
/// Get a shared reference to the value of the given `f` register.
#[inline(always)]
pub fn f(&self, f: FReg) -> &FRegVal {
debug_assert!(f.index() < self.f_regs.len());
unsafe { self.f_regs.get_unchecked(f.index()) }
}
/// Get an exclusive reference to the value of the given `f` register.
#[inline(always)]
pub fn f_mut(&mut self, f: FReg) -> &mut FRegVal {
debug_assert!(f.index() < self.f_regs.len());
unsafe { self.f_regs.get_unchecked_mut(f.index()) }
}
/// Copy the value of the given `f` register.
#[inline(always)]
pub fn get_f(&self, f: FReg) -> FRegVal {
debug_assert!(f.index() < self.f_regs.len());
unsafe { *self.f_regs.get_unchecked(f.index()) }
}
/// Set the value of the given `f` register.
#[inline(always)]
pub fn set_f(&mut self, f: FReg, val: FRegVal) {
debug_assert!(f.index() < self.f_regs.len());
unsafe {
*self.f_regs.get_unchecked_mut(f.index()) = val;
}
}
/// Get a shared reference to the value of the given `v` register.
#[inline(always)]
pub fn v(&self, v: VReg) -> &VRegVal {
debug_assert!(v.index() < self.v_regs.len());
unsafe { self.v_regs.get_unchecked(v.index()) }
}
/// Get an exclusive reference to the value of the given `v` register.
#[inline(always)]
pub fn v_mut(&mut self, v: VReg) -> &mut VRegVal {
debug_assert!(v.index() < self.v_regs.len());
unsafe { self.v_regs.get_unchecked_mut(v.index()) }
}
/// Copy the value of the given `v` register.
#[inline(always)]
pub fn get_v(&self, v: VReg) -> VRegVal {
debug_assert!(v.index() < self.v_regs.len());
unsafe { *self.v_regs.get_unchecked(v.index()) }
}
/// Set the value of the given `v` register.
#[inline(always)]
pub fn set_v(&mut self, v: VReg, val: VRegVal) {
debug_assert!(v.index() < self.v_regs.len());
unsafe {
*self.v_regs.get_unchecked_mut(v.index()) = val;
}
}
}
enum Continuation {
@ -672,10 +606,10 @@ impl OpVisitor for InterpreterVisitor<'_> {
type Return = Continuation;
fn ret(&mut self) -> Self::Return {
if self.state.x(XReg::LR).get_u64() == u64::MAX {
if self.state[XReg::LR].get_u64() == u64::MAX {
Continuation::ReturnToHost
} else {
let return_addr = self.state.x(XReg::LR).get_ptr();
let return_addr = self.state[XReg::LR].get_ptr();
self.pc = unsafe { UnsafeBytecodeStream::new(return_addr) };
// log::trace!("returning to {return_addr:#p}");
Continuation::Continue
@ -684,7 +618,7 @@ impl OpVisitor for InterpreterVisitor<'_> {
fn call(&mut self, offset: PcRelOffset) -> Self::Return {
let return_addr = u64::try_from(self.pc.as_ptr() as usize).unwrap();
self.state.x_mut(XReg::LR).set_u64(return_addr);
self.state[XReg::LR].set_u64(return_addr);
self.pc_rel_jump(offset, 5)
}
@ -693,7 +627,7 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if(&mut self, cond: XReg, offset: PcRelOffset) -> Self::Return {
let cond = self.state.x(cond).get_u64();
let cond = self.state[cond].get_u64();
if cond != 0 {
self.pc_rel_jump(offset, 6)
} else {
@ -702,7 +636,7 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_not(&mut self, cond: XReg, offset: PcRelOffset) -> Self::Return {
let cond = self.state.x(cond).get_u64();
let cond = self.state[cond].get_u64();
if cond == 0 {
self.pc_rel_jump(offset, 6)
} else {
@ -711,8 +645,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_xeq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return {
let a = self.state.x(a).get_u32();
let b = self.state.x(b).get_u32();
let a = self.state[a].get_u32();
let b = self.state[b].get_u32();
if a == b {
self.pc_rel_jump(offset, 7)
} else {
@ -721,8 +655,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_xneq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return {
let a = self.state.x(a).get_u32();
let b = self.state.x(b).get_u32();
let a = self.state[a].get_u32();
let b = self.state[b].get_u32();
if a != b {
self.pc_rel_jump(offset, 7)
} else {
@ -731,8 +665,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_xslt32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return {
let a = self.state.x(a).get_i32();
let b = self.state.x(b).get_i32();
let a = self.state[a].get_i32();
let b = self.state[b].get_i32();
if a < b {
self.pc_rel_jump(offset, 7)
} else {
@ -741,8 +675,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_xslteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return {
let a = self.state.x(a).get_i32();
let b = self.state.x(b).get_i32();
let a = self.state[a].get_i32();
let b = self.state[b].get_i32();
if a <= b {
self.pc_rel_jump(offset, 7)
} else {
@ -751,8 +685,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_xult32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return {
let a = self.state.x(a).get_u32();
let b = self.state.x(b).get_u32();
let a = self.state[a].get_u32();
let b = self.state[b].get_u32();
if a < b {
self.pc_rel_jump(offset, 7)
} else {
@ -761,8 +695,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn br_if_xulteq32(&mut self, a: XReg, b: XReg, offset: PcRelOffset) -> Self::Return {
let a = self.state.x(a).get_u32();
let b = self.state.x(b).get_u32();
let a = self.state[a].get_u32();
let b = self.state[b].get_u32();
if a <= b {
self.pc_rel_jump(offset, 7)
} else {
@ -771,201 +705,198 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn xmov(&mut self, dst: XReg, src: XReg) -> Self::Return {
let val = self.state.get_x(src);
self.state.set_x(dst, val);
let val = self.state[src];
self.state[dst] = val;
Continuation::Continue
}
fn fmov(&mut self, dst: FReg, src: FReg) -> Self::Return {
let val = self.state.get_f(src);
self.state.set_f(dst, val);
let val = self.state[src];
self.state[dst] = val;
Continuation::Continue
}
fn vmov(&mut self, dst: VReg, src: VReg) -> Self::Return {
let val = self.state.get_v(src);
self.state.set_v(dst, val);
let val = self.state[src];
self.state[dst] = val;
Continuation::Continue
}
fn xconst8(&mut self, dst: XReg, imm: i8) -> Self::Return {
self.state.x_mut(dst).set_i64(i64::from(imm));
self.state[dst].set_i64(i64::from(imm));
Continuation::Continue
}
fn xconst16(&mut self, dst: XReg, imm: i16) -> Self::Return {
self.state.x_mut(dst).set_i64(i64::from(imm));
self.state[dst].set_i64(i64::from(imm));
Continuation::Continue
}
fn xconst32(&mut self, dst: XReg, imm: i32) -> Self::Return {
self.state.x_mut(dst).set_i64(i64::from(imm));
self.state[dst].set_i64(i64::from(imm));
Continuation::Continue
}
fn xconst64(&mut self, dst: XReg, imm: i64) -> Self::Return {
self.state.x_mut(dst).set_i64(imm);
self.state[dst].set_i64(imm);
Continuation::Continue
}
fn xadd32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u32();
let b = self.state.x(src2).get_u32();
self.state.x_mut(dst).set_u32(a.wrapping_add(b));
let a = self.state[src1].get_u32();
let b = self.state[src2].get_u32();
self.state[dst].set_u32(a.wrapping_add(b));
Continuation::Continue
}
fn xadd64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u64();
let b = self.state.x(src2).get_u64();
self.state.x_mut(dst).set_u64(a.wrapping_add(b));
let a = self.state[src1].get_u64();
let b = self.state[src2].get_u64();
self.state[dst].set_u64(a.wrapping_add(b));
Continuation::Continue
}
fn xeq64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u64();
let b = self.state.x(src2).get_u64();
self.state.x_mut(dst).set_u64(u64::from(a == b));
let a = self.state[src1].get_u64();
let b = self.state[src2].get_u64();
self.state[dst].set_u64(u64::from(a == b));
Continuation::Continue
}
fn xneq64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u64();
let b = self.state.x(src2).get_u64();
self.state.x_mut(dst).set_u64(u64::from(a != b));
let a = self.state[src1].get_u64();
let b = self.state[src2].get_u64();
self.state[dst].set_u64(u64::from(a != b));
Continuation::Continue
}
fn xslt64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_i64();
let b = self.state.x(src2).get_i64();
self.state.x_mut(dst).set_u64(u64::from(a < b));
let a = self.state[src1].get_i64();
let b = self.state[src2].get_i64();
self.state[dst].set_u64(u64::from(a < b));
Continuation::Continue
}
fn xslteq64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_i64();
let b = self.state.x(src2).get_i64();
self.state.x_mut(dst).set_u64(u64::from(a <= b));
let a = self.state[src1].get_i64();
let b = self.state[src2].get_i64();
self.state[dst].set_u64(u64::from(a <= b));
Continuation::Continue
}
fn xult64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u64();
let b = self.state.x(src2).get_u64();
self.state.x_mut(dst).set_u64(u64::from(a < b));
let a = self.state[src1].get_u64();
let b = self.state[src2].get_u64();
self.state[dst].set_u64(u64::from(a < b));
Continuation::Continue
}
fn xulteq64(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u64();
let b = self.state.x(src2).get_u64();
self.state.x_mut(dst).set_u64(u64::from(a <= b));
let a = self.state[src1].get_u64();
let b = self.state[src2].get_u64();
self.state[dst].set_u64(u64::from(a <= b));
Continuation::Continue
}
fn xeq32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u32();
let b = self.state.x(src2).get_u32();
self.state.x_mut(dst).set_u64(u64::from(a == b));
let a = self.state[src1].get_u32();
let b = self.state[src2].get_u32();
self.state[dst].set_u64(u64::from(a == b));
Continuation::Continue
}
fn xneq32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u32();
let b = self.state.x(src2).get_u32();
self.state.x_mut(dst).set_u64(u64::from(a != b));
let a = self.state[src1].get_u32();
let b = self.state[src2].get_u32();
self.state[dst].set_u64(u64::from(a != b));
Continuation::Continue
}
fn xslt32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_i32();
let b = self.state.x(src2).get_i32();
self.state.x_mut(dst).set_u64(u64::from(a < b));
let a = self.state[src1].get_i32();
let b = self.state[src2].get_i32();
self.state[dst].set_u64(u64::from(a < b));
Continuation::Continue
}
fn xslteq32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_i32();
let b = self.state.x(src2).get_i32();
self.state.x_mut(dst).set_u64(u64::from(a <= b));
let a = self.state[src1].get_i32();
let b = self.state[src2].get_i32();
self.state[dst].set_u64(u64::from(a <= b));
Continuation::Continue
}
fn xult32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u32();
let b = self.state.x(src2).get_u32();
self.state.x_mut(dst).set_u64(u64::from(a < b));
let a = self.state[src1].get_u32();
let b = self.state[src2].get_u32();
self.state[dst].set_u64(u64::from(a < b));
Continuation::Continue
}
fn xulteq32(&mut self, dst: XReg, src1: XReg, src2: XReg) -> Self::Return {
let a = self.state.x(src1).get_u32();
let b = self.state.x(src2).get_u32();
self.state.x_mut(dst).set_u64(u64::from(a <= b));
let a = self.state[src1].get_u32();
let b = self.state[src2].get_u32();
self.state[dst].set_u64(u64::from(a <= b));
Continuation::Continue
}
fn load32_u(&mut self, dst: XReg, ptr: XReg) -> Self::Return {
let ptr = self.state.x(ptr).get_ptr::<u32>();
let ptr = self.state[ptr].get_ptr::<u32>();
let val = unsafe { ptr::read_unaligned(ptr) };
self.state.x_mut(dst).set_u64(u64::from(val));
self.state[dst].set_u64(u64::from(val));
Continuation::Continue
}
fn load32_s(&mut self, dst: XReg, ptr: XReg) -> Self::Return {
let ptr = self.state.x(ptr).get_ptr::<i32>();
let ptr = self.state[ptr].get_ptr::<i32>();
let val = unsafe { ptr::read_unaligned(ptr) };
self.state.x_mut(dst).set_i64(i64::from(val));
self.state[dst].set_i64(i64::from(val));
Continuation::Continue
}
fn load64(&mut self, dst: XReg, ptr: XReg) -> Self::Return {
let ptr = self.state.x(ptr).get_ptr::<u64>();
let ptr = self.state[ptr].get_ptr::<u64>();
let val = unsafe { ptr::read_unaligned(ptr) };
self.state.x_mut(dst).set_u64(val);
self.state[dst].set_u64(val);
Continuation::Continue
}
fn load32_u_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return {
let val = unsafe {
self.state
.x(ptr)
self.state[ptr]
.get_ptr::<u32>()
.byte_offset(offset.into())
.read_unaligned()
};
self.state.x_mut(dst).set_u64(u64::from(val));
self.state[dst].set_u64(u64::from(val));
Continuation::Continue
}
fn load32_s_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return {
let val = unsafe {
self.state
.x(ptr)
self.state[ptr]
.get_ptr::<i32>()
.byte_offset(offset.into())
.read_unaligned()
};
self.state.x_mut(dst).set_i64(i64::from(val));
self.state[dst].set_i64(i64::from(val));
Continuation::Continue
}
fn load64_offset8(&mut self, dst: XReg, ptr: XReg, offset: i8) -> Self::Return {
let val = unsafe {
self.state
.x(ptr)
self.state[ptr]
.get_ptr::<u64>()
.byte_offset(offset.into())
.read_unaligned()
};
self.state.x_mut(dst).set_u64(val);
self.state[dst].set_u64(val);
Continuation::Continue
}
fn store32(&mut self, ptr: XReg, src: XReg) -> Self::Return {
let ptr = self.state.x(ptr).get_ptr::<u32>();
let val = self.state.x(src).get_u32();
let ptr = self.state[ptr].get_ptr::<u32>();
let val = self.state[src].get_u32();
unsafe {
ptr::write_unaligned(ptr, val);
}
@ -973,8 +904,8 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn store64(&mut self, ptr: XReg, src: XReg) -> Self::Return {
let ptr = self.state.x(ptr).get_ptr::<u64>();
let val = self.state.x(src).get_u64();
let ptr = self.state[ptr].get_ptr::<u64>();
let val = self.state[src].get_u64();
unsafe {
ptr::write_unaligned(ptr, val);
}
@ -982,10 +913,9 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn store32_offset8(&mut self, ptr: XReg, offset: i8, src: XReg) -> Self::Return {
let val = self.state.x(src).get_u32();
let val = self.state[src].get_u32();
unsafe {
self.state
.x(ptr)
self.state[ptr]
.get_ptr::<u32>()
.byte_offset(offset.into())
.write_unaligned(val);
@ -994,10 +924,9 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn store64_offset8(&mut self, ptr: XReg, offset: i8, src: XReg) -> Self::Return {
let val = self.state.x(src).get_u64();
let val = self.state[src].get_u64();
unsafe {
self.state
.x(ptr)
self.state[ptr]
.get_ptr::<u64>()
.byte_offset(offset.into())
.write_unaligned(val);
@ -1006,34 +935,26 @@ impl OpVisitor for InterpreterVisitor<'_> {
}
fn bitcast_int_from_float_32(&mut self, dst: XReg, src: FReg) -> Self::Return {
let val = self.state.f(src).get_f32();
self.state
.x_mut(dst)
.set_u64(u32::from_ne_bytes(val.to_ne_bytes()).into());
let val = self.state[src].get_f32();
self.state[dst].set_u64(u32::from_ne_bytes(val.to_ne_bytes()).into());
Continuation::Continue
}
fn bitcast_int_from_float_64(&mut self, dst: XReg, src: FReg) -> Self::Return {
let val = self.state.f(src).get_f64();
self.state
.x_mut(dst)
.set_u64(u64::from_ne_bytes(val.to_ne_bytes()));
let val = self.state[src].get_f64();
self.state[dst].set_u64(u64::from_ne_bytes(val.to_ne_bytes()));
Continuation::Continue
}
fn bitcast_float_from_int_32(&mut self, dst: FReg, src: XReg) -> Self::Return {
let val = self.state.x(src).get_u32();
self.state
.f_mut(dst)
.set_f32(f32::from_ne_bytes(val.to_ne_bytes()));
let val = self.state[src].get_u32();
self.state[dst].set_f32(f32::from_ne_bytes(val.to_ne_bytes()));
Continuation::Continue
}
fn bitcast_float_from_int_64(&mut self, dst: FReg, src: XReg) -> Self::Return {
let val = self.state.x(src).get_u64();
self.state
.f_mut(dst)
.set_f64(f64::from_ne_bytes(val.to_ne_bytes()));
let val = self.state[src].get_u64();
self.state[dst].set_f64(f64::from_ne_bytes(val.to_ne_bytes()));
Continuation::Continue
}
}
@ -1048,8 +969,8 @@ impl ExtendedOpVisitor for InterpreterVisitor<'_> {
}
fn get_sp(&mut self, dst: XReg) -> Self::Return {
let sp = self.state.x(XReg::SP).get_u64();
self.state.x_mut(dst).set_u64(sp);
let sp = self.state[XReg::SP].get_u64();
self.state[dst].set_u64(sp);
Continuation::Continue
}
}

10
pulley/tests/all/interp.rs

@ -38,8 +38,8 @@ unsafe fn assert_one<R0, R1, V>(
let val = val.into();
eprintln!("{reg} = {val:#018x}");
match (reg, val) {
(AnyReg::X(r), Val::XReg(v)) => *vm.state_mut().x_mut(r) = v,
(AnyReg::F(r), Val::FReg(v)) => *vm.state_mut().f_mut(r) = v,
(AnyReg::X(r), Val::XReg(v)) => vm.state_mut()[r] = v,
(AnyReg::F(r), Val::FReg(v)) => vm.state_mut()[r] = v,
(AnyReg::V(_), Val::VReg(_)) => todo!(),
(kind, val) => panic!("register kind and value mismatch: {kind:?} and {val:?}"),
}
@ -53,8 +53,8 @@ unsafe fn assert_one<R0, R1, V>(
eprintln!("expected = {expected:#018x}");
let actual = match result.into() {
AnyReg::X(r) => vm.state_mut().x(r).get_u64(),
AnyReg::F(r) => vm.state_mut().f(r).get_f64().to_bits(),
AnyReg::X(r) => vm.state_mut()[r].get_u64(),
AnyReg::F(r) => vm.state_mut()[r].get_f64().to_bits(),
AnyReg::V(_) => todo!(),
};
eprintln!("actual = {actual:#018x}");
@ -992,5 +992,5 @@ fn trap() {
}
// `dst` should not have been written to the second time.
assert_eq!(vm.state().x(dst).get_u32(), 1);
assert_eq!(vm.state()[dst].get_u32(), 1);
}

Loading…
Cancel
Save