working on simulator
This commit is contained in:
parent
96b3f1fee4
commit
5b2abd3fca
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -473,11 +473,10 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
|||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.4"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
|
|
@ -26,7 +26,7 @@ eyre = "0.6.12"
|
|||
hashbrown = "0.14.3"
|
||||
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||
jobslot = "0.2.19"
|
||||
num-bigint = "0.4.4"
|
||||
num-bigint = "0.4.6"
|
||||
num-traits = "0.2.16"
|
||||
os_pipe = "1.2.1"
|
||||
prettyplease = "0.2.20"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,11 +2,13 @@
|
|||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::{
|
||||
intern::{Intern, Interned},
|
||||
intern::{Intern, Interned, Memoize},
|
||||
source_location::SourceLocation,
|
||||
ty::CanonicalType,
|
||||
util::get_many_mut,
|
||||
};
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
convert::Infallible,
|
||||
|
@ -21,6 +23,147 @@ pub(crate) type SmallUInt = u64;
|
|||
pub(crate) type SmallSInt = i64;
|
||||
pub(crate) const MIN_BITS_FOR_NEEDING_BIG: usize = SmallUInt::BITS as usize + 1;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) enum InsnFieldKind {
|
||||
Input,
|
||||
Output,
|
||||
Immediate,
|
||||
BranchTarget,
|
||||
}
|
||||
|
||||
pub(crate) trait InsnFieldTypeTransform: Eq + Hash + fmt::Debug + Send + Sync {
|
||||
type Type<FieldType: InsnFieldTrait>: Eq + Hash + fmt::Debug + Send + Sync;
|
||||
fn empty_type() -> Self::Type<[(); 0]>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
|
||||
pub(crate) struct InsnFieldTypeTransformUnit;
|
||||
|
||||
impl InsnFieldTypeTransform for InsnFieldTypeTransformUnit {
|
||||
type Type<FieldType: InsnFieldTrait> = ();
|
||||
fn empty_type() -> Self::Type<[(); 0]> {
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct InsnFieldTypeTransformRef<'a>(PhantomData<&'a ()>);
|
||||
|
||||
impl<'a> InsnFieldTypeTransform for InsnFieldTypeTransformRef<'a> {
|
||||
type Type<FieldType: InsnFieldTrait> = &'a FieldType;
|
||||
fn empty_type() -> Self::Type<[(); 0]> {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct InsnFieldTypeTransformRefMut<'a>(PhantomData<&'a mut ()>);
|
||||
|
||||
impl<'a> InsnFieldTypeTransform for InsnFieldTypeTransformRefMut<'a> {
|
||||
type Type<FieldType: InsnFieldTrait> = &'a mut FieldType;
|
||||
fn empty_type() -> Self::Type<[(); 0]> {
|
||||
&mut []
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct InsnFieldTypeTransformValue;
|
||||
|
||||
impl InsnFieldTypeTransform for InsnFieldTypeTransformValue {
|
||||
type Type<FieldType: InsnFieldTrait> = FieldType;
|
||||
fn empty_type() -> Self::Type<[(); 0]> {
|
||||
[]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InsnFieldTrait: Send + Sync + 'static + Copy + Eq + Hash + fmt::Debug {
|
||||
const UNIT: InsnFieldType<InsnFieldTypeTransformUnit>;
|
||||
fn variant<Transform: InsnFieldTypeTransform>(
|
||||
v: Transform::Type<Self>,
|
||||
) -> InsnFieldType<Transform>;
|
||||
}
|
||||
|
||||
macro_rules! insn_field_enum {
|
||||
(
|
||||
$enum_vis:vis enum $InsnFieldType:ident<$Transform:ident: $InsnFieldTypeTransform:ident> {
|
||||
$($Variant:ident($Transform2:ident::$Type:ident<$variant_ty:ty>),)*
|
||||
}
|
||||
) => {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
$enum_vis enum $InsnFieldType<$Transform: $InsnFieldTypeTransform> {
|
||||
$($Variant($Transform2::$Type<$variant_ty>),)*
|
||||
}
|
||||
|
||||
$(impl InsnFieldTrait for $variant_ty {
|
||||
const UNIT: $InsnFieldType<InsnFieldTypeTransformUnit> = $InsnFieldType::$Variant(());
|
||||
fn variant<$Transform2: $InsnFieldTypeTransform>(
|
||||
v: $Transform2::$Type<Self>,
|
||||
) -> $InsnFieldType<$Transform2> {
|
||||
$InsnFieldType::$Variant(v)
|
||||
}
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
insn_field_enum! {
|
||||
pub(crate) enum InsnFieldType<Transform: InsnFieldTypeTransform> {
|
||||
SmallSlot(Transform::Type<StatePartIndex<StatePartKindSmallSlots>>),
|
||||
BigSlot(Transform::Type<StatePartIndex<StatePartKindBigSlots>>),
|
||||
SmallUInt(Transform::Type<SmallUInt>),
|
||||
SmallSInt(Transform::Type<SmallSInt>),
|
||||
InternedBigInt(Transform::Type<Interned<BigInt>>),
|
||||
U8(Transform::Type<u8>),
|
||||
USize(Transform::Type<usize>),
|
||||
Empty(Transform::Type<[(); 0]>),
|
||||
}
|
||||
}
|
||||
|
||||
impl<Transform: InsnFieldTypeTransform> InsnFieldType<Transform> {
|
||||
pub(crate) fn empty() -> Self {
|
||||
Self::Empty(Transform::empty_type())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub(crate) struct InsnField<Transform: InsnFieldTypeTransform> {
|
||||
pub(crate) ty: InsnFieldType<Transform>,
|
||||
pub(crate) kind: InsnFieldKind,
|
||||
}
|
||||
|
||||
impl<Transform: InsnFieldTypeTransform> Clone for InsnField<Transform>
|
||||
where
|
||||
InsnFieldType<Transform>: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
ty: self.ty.clone(),
|
||||
kind: self.kind.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Transform: InsnFieldTypeTransform> Copy for InsnField<Transform> where
|
||||
InsnFieldType<Transform>: Copy
|
||||
{
|
||||
}
|
||||
|
||||
fn make_array_into_iter<T, const I: usize, const N: usize>(
|
||||
input: [T; I],
|
||||
mut default: impl FnMut() -> T,
|
||||
) -> std::array::IntoIter<T, N> {
|
||||
const {
|
||||
assert!(I <= N);
|
||||
};
|
||||
let mut input = input.into_iter();
|
||||
let array = std::array::from_fn(|_| input.next().unwrap_or_else(&mut default));
|
||||
let mut retval = array.into_iter();
|
||||
// remove unneeded trailing elements
|
||||
if I < N {
|
||||
retval.nth_back(N - I - 1);
|
||||
}
|
||||
retval
|
||||
}
|
||||
|
||||
macro_rules! impl_insns {
|
||||
(
|
||||
#[insn = $Insn:ident, next_macro = $next_macro:ident, branch_macro = $branch_macro:ident]
|
||||
|
@ -39,6 +182,7 @@ macro_rules! impl_insns {
|
|||
$(#[$insn_meta:meta])*
|
||||
$insn_name:ident $({
|
||||
$(
|
||||
#[kind = $field_kind:ident]
|
||||
$(#[$field_meta:meta])*
|
||||
$field_name:ident: $field_ty:ty,
|
||||
)*
|
||||
|
@ -58,6 +202,91 @@ macro_rules! impl_insns {
|
|||
)*
|
||||
}
|
||||
|
||||
impl $Insn {
|
||||
$vis const MAX_FIELDS: usize = {
|
||||
let mut retval = 0;
|
||||
$($(
|
||||
let fields = [$(stringify!($field_name),)*].len();
|
||||
if retval < fields {
|
||||
retval = fields;
|
||||
}
|
||||
)?)*
|
||||
retval
|
||||
};
|
||||
}
|
||||
|
||||
impl $Insn {
|
||||
$vis const fn fields_unit(&self) -> &'static [InsnField<InsnFieldTypeTransformUnit>] {
|
||||
match self {
|
||||
$(
|
||||
$Insn::$insn_name {..} => &[
|
||||
$($(InsnField {
|
||||
ty: <$field_ty as InsnFieldTrait>::UNIT,
|
||||
kind: InsnFieldKind::$field_kind,
|
||||
},)*)?
|
||||
],
|
||||
)*
|
||||
}
|
||||
}
|
||||
$vis fn fields<'a>(&'a self) -> std::array::IntoIter<InsnField<InsnFieldTypeTransformRef<'a>>, { $Insn::MAX_FIELDS }> {
|
||||
match self {
|
||||
$(
|
||||
$Insn::$insn_name $({
|
||||
$($field_name,)*
|
||||
})? => make_array_into_iter([
|
||||
$($(InsnField {
|
||||
ty: <$field_ty as InsnFieldTrait>::variant($field_name),
|
||||
kind: InsnFieldKind::$field_kind,
|
||||
},)*)?
|
||||
],
|
||||
|| InsnField {
|
||||
ty: InsnFieldType::empty(),
|
||||
kind: InsnFieldKind::Immediate,
|
||||
},
|
||||
),
|
||||
)*
|
||||
}
|
||||
}
|
||||
$vis fn fields_mut<'a>(&'a mut self) -> std::array::IntoIter<InsnField<InsnFieldTypeTransformRefMut<'a>>, { $Insn::MAX_FIELDS }> {
|
||||
match self {
|
||||
$(
|
||||
$Insn::$insn_name $({
|
||||
$($field_name,)*
|
||||
})? => make_array_into_iter([
|
||||
$($(InsnField {
|
||||
ty: <$field_ty as InsnFieldTrait>::variant($field_name),
|
||||
kind: InsnFieldKind::$field_kind,
|
||||
},)*)?
|
||||
],
|
||||
|| InsnField {
|
||||
ty: InsnFieldType::empty(),
|
||||
kind: InsnFieldKind::Immediate,
|
||||
},
|
||||
),
|
||||
)*
|
||||
}
|
||||
}
|
||||
$vis fn into_fields(self) -> std::array::IntoIter<InsnField<InsnFieldTypeTransformValue>, { $Insn::MAX_FIELDS }> {
|
||||
match self {
|
||||
$(
|
||||
$Insn::$insn_name $({
|
||||
$($field_name,)*
|
||||
})? => make_array_into_iter([
|
||||
$($(InsnField {
|
||||
ty: <$field_ty as InsnFieldTrait>::variant($field_name),
|
||||
kind: InsnFieldKind::$field_kind,
|
||||
},)*)?
|
||||
],
|
||||
|| InsnField {
|
||||
ty: InsnFieldType::empty(),
|
||||
kind: InsnFieldKind::Immediate,
|
||||
},
|
||||
),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl $State {
|
||||
$vis fn $run(&mut $self) -> $run_ret_ty {
|
||||
let mut $state = $state_init;
|
||||
|
@ -497,6 +726,11 @@ macro_rules! make_state_part_kinds {
|
|||
$($type_field: self.$type_field.index_array(element_size.$type_field, index),)*
|
||||
}
|
||||
}
|
||||
pub(crate) fn offset(self, offset: TypeIndex) -> Self {
|
||||
Self {
|
||||
$($type_field: self.$type_field.offset(offset.$type_field),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
|
@ -509,6 +743,14 @@ macro_rules! make_state_part_kinds {
|
|||
$(pub(crate) $type_field: StatePartIndex<$TypeKind>,)*
|
||||
}
|
||||
|
||||
impl TypeIndex {
|
||||
pub(crate) fn offset(self, offset: TypeIndex) -> Self {
|
||||
Self {
|
||||
$($type_field: self.$type_field.offset(offset.$type_field),)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct State {
|
||||
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
||||
|
@ -678,20 +920,17 @@ impl<T> Drop for BorrowedStack<'_, T> {
|
|||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub(crate) struct SlotDebugData {
|
||||
pub(crate) name: Interned<str>,
|
||||
pub(crate) ty: CanonicalType,
|
||||
}
|
||||
|
||||
impl SlotDebugData {
|
||||
pub(crate) fn empty() -> Self {
|
||||
Self {
|
||||
name: Interned::default(),
|
||||
}
|
||||
}
|
||||
pub(crate) fn with_prefixed_debug_names(&self, prefix: &str) -> Self {
|
||||
let mut name = String::with_capacity(self.name.len() + prefix.len());
|
||||
name.push_str(prefix);
|
||||
name.push_str(&self.name);
|
||||
Self {
|
||||
name: Intern::intern_owned(name),
|
||||
ty: self.ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -728,6 +967,15 @@ impl<K: StatePartKind> StatePartIndex<K> {
|
|||
pub(crate) fn as_usize(self) -> usize {
|
||||
self.value.try_into().expect("index too big")
|
||||
}
|
||||
pub(crate) fn offset(self, offset: StatePartIndex<K>) -> Self {
|
||||
Self {
|
||||
value: self
|
||||
.value
|
||||
.checked_add(offset.value)
|
||||
.expect("offset too big"),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: StatePartKind> fmt::Debug for StatePartIndex<K> {
|
||||
|
@ -870,6 +1118,13 @@ impl<K: StatePartKind> StatePartIndexRange<K> {
|
|||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
pub(crate) fn offset(self, offset: StatePartIndex<K>) -> Self {
|
||||
self.end().offset(offset); // check for overflow
|
||||
Self {
|
||||
start: self.start.offset(offset),
|
||||
len: self.len,
|
||||
}
|
||||
}
|
||||
pub(crate) fn slice(self, index: StatePartIndexRange<K>) -> Self {
|
||||
assert!(index.end().value <= self.len.value, "index out of range");
|
||||
Self {
|
||||
|
@ -1180,6 +1435,65 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn bigint_pow2(width: usize) -> Interned<BigInt> {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
struct MyMemoize;
|
||||
impl Memoize for MyMemoize {
|
||||
type Input = usize;
|
||||
type InputOwned = usize;
|
||||
type Output = Interned<BigInt>;
|
||||
|
||||
fn inner(self, input: &Self::Input) -> Self::Output {
|
||||
(BigInt::one() << *input).intern_sized()
|
||||
}
|
||||
}
|
||||
MyMemoize.get(&width)
|
||||
}
|
||||
|
||||
fn bigint_mask(width: usize) -> Interned<BigInt> {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
struct MyMemoize;
|
||||
impl Memoize for MyMemoize {
|
||||
type Input = usize;
|
||||
type InputOwned = usize;
|
||||
type Output = Interned<BigInt>;
|
||||
|
||||
fn inner(self, input: &Self::Input) -> Self::Output {
|
||||
((BigInt::one() << *input) - BigInt::one()).intern_sized()
|
||||
}
|
||||
}
|
||||
MyMemoize.get(&width)
|
||||
}
|
||||
|
||||
fn bigint_not_mask(width: usize) -> Interned<BigInt> {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
struct MyMemoize;
|
||||
impl Memoize for MyMemoize {
|
||||
type Input = usize;
|
||||
type InputOwned = usize;
|
||||
type Output = Interned<BigInt>;
|
||||
|
||||
fn inner(self, input: &Self::Input) -> Self::Output {
|
||||
(-BigInt::one() << *input).intern_sized()
|
||||
}
|
||||
}
|
||||
MyMemoize.get(&width)
|
||||
}
|
||||
|
||||
fn cast_bigint_to_sint(src: &BigInt, dest_width: usize) -> BigInt {
|
||||
if dest_width == 0 {
|
||||
BigInt::ZERO
|
||||
} else if src.bit((dest_width - 1) as u64) {
|
||||
src | &*bigint_not_mask(dest_width)
|
||||
} else {
|
||||
src & &*bigint_mask(dest_width)
|
||||
}
|
||||
}
|
||||
|
||||
fn cast_bigint_to_uint(src: &BigInt, dest_width: usize) -> BigInt {
|
||||
src & &*bigint_mask(dest_width)
|
||||
}
|
||||
|
||||
impl_insns! {
|
||||
#[insn = Insn, next_macro = next, branch_macro = branch]
|
||||
pub(crate) fn State::run(&mut self) -> () {
|
||||
|
@ -1189,235 +1503,299 @@ impl_insns! {
|
|||
main_loop!();
|
||||
cleanup! {}
|
||||
}
|
||||
CopySmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
state.small_slots[dest] = state.small_slots[src];
|
||||
next!();
|
||||
}
|
||||
CopyBig {
|
||||
Copy {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
src: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let [dest, src] = state.big_slots.get_many_mut([dest, src]);
|
||||
dest.clone_from(src);
|
||||
if dest != src {
|
||||
let [dest, src] = state.big_slots.get_many_mut([dest, src]);
|
||||
dest.clone_from(src);
|
||||
}
|
||||
next!();
|
||||
}
|
||||
SExtSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
/// number of bits in a [`SmallSInt`] that aren't used
|
||||
unused_bit_count: u8,
|
||||
} => {
|
||||
let mut value = state.small_slots[src] as SmallSInt;
|
||||
value <<= unused_bit_count;
|
||||
value >>= unused_bit_count;
|
||||
state.small_slots[dest] = value as SmallUInt;
|
||||
next!();
|
||||
}
|
||||
ZExtSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
/// number of bits in a [`SmallUInt`] that aren't used
|
||||
unused_bit_count: u8,
|
||||
} => {
|
||||
let mut value = state.small_slots[src];
|
||||
value <<= unused_bit_count;
|
||||
value >>= unused_bit_count;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
SExtSmallToBig {
|
||||
CastToSInt {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
/// number of bits in a [`SmallSInt`] that aren't used
|
||||
unused_bit_count: u8,
|
||||
#[kind = Input]
|
||||
src: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
dest_width: usize,
|
||||
} => {
|
||||
let mut value = state.small_slots[src] as SmallSInt;
|
||||
value <<= unused_bit_count;
|
||||
value >>= unused_bit_count;
|
||||
state.big_slots[dest] = value.into();
|
||||
let value = cast_bigint_to_sint(&state.big_slots[src], dest_width);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
ZExtSmallToBig {
|
||||
CastToUInt {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
/// number of bits in a [`SmallUInt`] that aren't used
|
||||
unused_bit_count: u8,
|
||||
#[kind = Input]
|
||||
src: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
dest_width: usize,
|
||||
} => {
|
||||
let mut value = state.small_slots[src];
|
||||
value <<= unused_bit_count;
|
||||
value >>= unused_bit_count;
|
||||
state.big_slots[dest] = value.into();
|
||||
let value = cast_bigint_to_uint(&state.big_slots[src], dest_width);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
AndSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = lhs & rhs;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
OrSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = lhs | rhs;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
XorSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = lhs ^ rhs;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
NotSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let value = state.small_slots[src];
|
||||
state.small_slots[dest] = !value;
|
||||
next!();
|
||||
}
|
||||
CmpEqSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = (lhs == rhs) as SmallUInt;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpNeSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = (lhs != rhs) as SmallUInt;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpLTSmallUInt {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = (lhs < rhs) as SmallUInt;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpLESmallUInt {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = (lhs <= rhs) as SmallUInt;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpLTSmallSInt {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs] as SmallSInt;
|
||||
let rhs = state.small_slots[rhs] as SmallSInt;
|
||||
let value = (lhs < rhs) as SmallUInt;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpLESmallSInt {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs] as SmallSInt;
|
||||
let rhs = state.small_slots[rhs] as SmallSInt;
|
||||
let value = (lhs <= rhs) as SmallUInt;
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
AddSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = lhs.wrapping_add(rhs);
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
SubSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = lhs.wrapping_sub(rhs);
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
NegSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let value = state.small_slots[src];
|
||||
let value = value.wrapping_neg();
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
NegBig {
|
||||
And {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] & &state.big_slots[rhs];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Or {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] | &state.big_slots[rhs];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Xor {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] ^ &state.big_slots[rhs];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
NotS {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
src: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = !&state.big_slots[src];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
NotU {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
src: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
width: usize,
|
||||
} => {
|
||||
let value = &state.big_slots[src] ^ &*bigint_mask(width);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Neg {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
src: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = -&state.big_slots[src];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
MulSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
lhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
rhs: StatePartIndex<StatePartKindSmallSlots>,
|
||||
} => {
|
||||
let lhs = state.small_slots[lhs];
|
||||
let rhs = state.small_slots[rhs];
|
||||
let value = lhs.wrapping_mul(rhs);
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
ConstSmall {
|
||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
||||
value: SmallUInt,
|
||||
} => {
|
||||
state.small_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
ConstBig {
|
||||
Add {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] + &state.big_slots[rhs];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
SubS {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] - &state.big_slots[rhs];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
SubU {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
dest_width: usize,
|
||||
} => {
|
||||
let mut value = &state.big_slots[lhs] - &state.big_slots[rhs];
|
||||
value &= &*bigint_mask(dest_width);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Mul {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] * &state.big_slots[rhs];
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Div {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = state.big_slots[lhs].checked_div(&state.big_slots[rhs]).unwrap_or(BigInt::ZERO);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Rem {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
// no checked_rem?!
|
||||
let value = if state.big_slots[rhs].is_zero() {
|
||||
BigInt::ZERO
|
||||
} else {
|
||||
&state.big_slots[lhs] % &state.big_slots[rhs]
|
||||
};
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
DynShl {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] << state.big_slots[rhs].to_usize().expect("shl by invalid value");
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
DynShr {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
assert!(!state.big_slots[rhs].is_negative(), "shr by invalid value");
|
||||
let value = state.big_slots[rhs].to_usize().map_or(BigInt::ZERO, |rhs| &state.big_slots[lhs] >> rhs);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Shl {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
rhs: usize,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] << rhs;
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Shr {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
rhs: usize,
|
||||
} => {
|
||||
let value = &state.big_slots[lhs] >> rhs;
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpEq {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let lhs = &state.big_slots[lhs];
|
||||
let rhs = &state.big_slots[rhs];
|
||||
let value = BigInt::from(lhs == rhs);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpNe {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let lhs = &state.big_slots[lhs];
|
||||
let rhs = &state.big_slots[rhs];
|
||||
let value = BigInt::from(lhs != rhs);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpLt {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let lhs = &state.big_slots[lhs];
|
||||
let rhs = &state.big_slots[rhs];
|
||||
let value = BigInt::from(lhs < rhs);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
CmpLe {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
lhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Input]
|
||||
rhs: StatePartIndex<StatePartKindBigSlots>,
|
||||
} => {
|
||||
let lhs = &state.big_slots[lhs];
|
||||
let rhs = &state.big_slots[rhs];
|
||||
let value = BigInt::from(lhs <= rhs);
|
||||
state.big_slots[dest] = value;
|
||||
next!();
|
||||
}
|
||||
Const {
|
||||
#[kind = Output]
|
||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||
#[kind = Immediate]
|
||||
value: Interned<BigInt>,
|
||||
} => {
|
||||
state.big_slots[dest].clone_from(&value);
|
||||
|
|
Loading…
Reference in a new issue