working on simulator
This commit is contained in:
parent
86c711c36e
commit
435514654c
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -473,11 +473,10 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.4"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0"
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"num-integer",
|
"num-integer",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
|
@ -26,7 +26,7 @@ eyre = "0.6.12"
|
||||||
hashbrown = "0.14.3"
|
hashbrown = "0.14.3"
|
||||||
indexmap = { version = "2.2.6", features = ["serde"] }
|
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
jobslot = "0.2.19"
|
jobslot = "0.2.19"
|
||||||
num-bigint = "0.4.4"
|
num-bigint = "0.4.6"
|
||||||
num-traits = "0.2.16"
|
num-traits = "0.2.16"
|
||||||
os_pipe = "1.2.1"
|
os_pipe = "1.2.1"
|
||||||
prettyplease = "0.2.20"
|
prettyplease = "0.2.20"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,11 +2,13 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
intern::{Intern, Interned},
|
intern::{Intern, Interned, Memoize},
|
||||||
source_location::SourceLocation,
|
source_location::SourceLocation,
|
||||||
|
ty::CanonicalType,
|
||||||
util::get_many_mut,
|
util::get_many_mut,
|
||||||
};
|
};
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::BorrowMut,
|
borrow::BorrowMut,
|
||||||
convert::Infallible,
|
convert::Infallible,
|
||||||
|
@ -21,6 +23,147 @@ pub(crate) type SmallUInt = u64;
|
||||||
pub(crate) type SmallSInt = i64;
|
pub(crate) type SmallSInt = i64;
|
||||||
pub(crate) const MIN_BITS_FOR_NEEDING_BIG: usize = SmallUInt::BITS as usize + 1;
|
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 {
|
macro_rules! impl_insns {
|
||||||
(
|
(
|
||||||
#[insn = $Insn:ident, next_macro = $next_macro:ident, branch_macro = $branch_macro:ident]
|
#[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_meta:meta])*
|
||||||
$insn_name:ident $({
|
$insn_name:ident $({
|
||||||
$(
|
$(
|
||||||
|
#[kind = $field_kind:ident]
|
||||||
$(#[$field_meta:meta])*
|
$(#[$field_meta:meta])*
|
||||||
$field_name:ident: $field_ty:ty,
|
$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 {
|
impl $State {
|
||||||
$vis fn $run(&mut $self) -> $run_ret_ty {
|
$vis fn $run(&mut $self) -> $run_ret_ty {
|
||||||
let mut $state = $state_init;
|
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),)*
|
$($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)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
@ -509,6 +743,14 @@ macro_rules! make_state_part_kinds {
|
||||||
$(pub(crate) $type_field: StatePartIndex<$TypeKind>,)*
|
$(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)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
||||||
|
@ -678,20 +920,17 @@ impl<T> Drop for BorrowedStack<'_, T> {
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||||
pub(crate) struct SlotDebugData {
|
pub(crate) struct SlotDebugData {
|
||||||
pub(crate) name: Interned<str>,
|
pub(crate) name: Interned<str>,
|
||||||
|
pub(crate) ty: CanonicalType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SlotDebugData {
|
impl SlotDebugData {
|
||||||
pub(crate) fn empty() -> Self {
|
|
||||||
Self {
|
|
||||||
name: Interned::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub(crate) fn with_prefixed_debug_names(&self, prefix: &str) -> Self {
|
pub(crate) fn with_prefixed_debug_names(&self, prefix: &str) -> Self {
|
||||||
let mut name = String::with_capacity(self.name.len() + prefix.len());
|
let mut name = String::with_capacity(self.name.len() + prefix.len());
|
||||||
name.push_str(prefix);
|
name.push_str(prefix);
|
||||||
name.push_str(&self.name);
|
name.push_str(&self.name);
|
||||||
Self {
|
Self {
|
||||||
name: Intern::intern_owned(name),
|
name: Intern::intern_owned(name),
|
||||||
|
ty: self.ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -728,6 +967,15 @@ impl<K: StatePartKind> StatePartIndex<K> {
|
||||||
pub(crate) fn as_usize(self) -> usize {
|
pub(crate) fn as_usize(self) -> usize {
|
||||||
self.value.try_into().expect("index too big")
|
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> {
|
impl<K: StatePartKind> fmt::Debug for StatePartIndex<K> {
|
||||||
|
@ -870,6 +1118,13 @@ impl<K: StatePartKind> StatePartIndexRange<K> {
|
||||||
_phantom: PhantomData,
|
_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 {
|
pub(crate) fn slice(self, index: StatePartIndexRange<K>) -> Self {
|
||||||
assert!(index.end().value <= self.len.value, "index out of range");
|
assert!(index.end().value <= self.len.value, "index out of range");
|
||||||
Self {
|
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! {
|
impl_insns! {
|
||||||
#[insn = Insn, next_macro = next, branch_macro = branch]
|
#[insn = Insn, next_macro = next, branch_macro = branch]
|
||||||
pub(crate) fn State::run(&mut self) -> () {
|
pub(crate) fn State::run(&mut self) -> () {
|
||||||
|
@ -1189,235 +1503,299 @@ impl_insns! {
|
||||||
main_loop!();
|
main_loop!();
|
||||||
cleanup! {}
|
cleanup! {}
|
||||||
}
|
}
|
||||||
CopySmall {
|
Copy {
|
||||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
#[kind = Output]
|
||||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
|
||||||
} => {
|
|
||||||
state.small_slots[dest] = state.small_slots[src];
|
|
||||||
next!();
|
|
||||||
}
|
|
||||||
CopyBig {
|
|
||||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||||
|
#[kind = Input]
|
||||||
src: StatePartIndex<StatePartKindBigSlots>,
|
src: StatePartIndex<StatePartKindBigSlots>,
|
||||||
} => {
|
} => {
|
||||||
let [dest, src] = state.big_slots.get_many_mut([dest, src]);
|
if dest != src {
|
||||||
dest.clone_from(src);
|
let [dest, src] = state.big_slots.get_many_mut([dest, src]);
|
||||||
|
dest.clone_from(src);
|
||||||
|
}
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
SExtSmall {
|
CastToSInt {
|
||||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
#[kind = Output]
|
||||||
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 {
|
|
||||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
#[kind = Input]
|
||||||
/// number of bits in a [`SmallSInt`] that aren't used
|
src: StatePartIndex<StatePartKindBigSlots>,
|
||||||
unused_bit_count: u8,
|
#[kind = Immediate]
|
||||||
|
dest_width: usize,
|
||||||
} => {
|
} => {
|
||||||
let mut value = state.small_slots[src] as SmallSInt;
|
let value = cast_bigint_to_sint(&state.big_slots[src], dest_width);
|
||||||
value <<= unused_bit_count;
|
state.big_slots[dest] = value;
|
||||||
value >>= unused_bit_count;
|
|
||||||
state.big_slots[dest] = value.into();
|
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
ZExtSmallToBig {
|
CastToUInt {
|
||||||
|
#[kind = Output]
|
||||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
dest: StatePartIndex<StatePartKindBigSlots>,
|
||||||
src: StatePartIndex<StatePartKindSmallSlots>,
|
#[kind = Input]
|
||||||
/// number of bits in a [`SmallUInt`] that aren't used
|
src: StatePartIndex<StatePartKindBigSlots>,
|
||||||
unused_bit_count: u8,
|
#[kind = Immediate]
|
||||||
|
dest_width: usize,
|
||||||
} => {
|
} => {
|
||||||
let mut value = state.small_slots[src];
|
let value = cast_bigint_to_uint(&state.big_slots[src], dest_width);
|
||||||
value <<= unused_bit_count;
|
state.big_slots[dest] = value;
|
||||||
value >>= unused_bit_count;
|
|
||||||
state.big_slots[dest] = value.into();
|
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
AndSmall {
|
And {
|
||||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
#[kind = Output]
|
||||||
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 {
|
|
||||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
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>,
|
src: StatePartIndex<StatePartKindBigSlots>,
|
||||||
} => {
|
} => {
|
||||||
let value = -&state.big_slots[src];
|
let value = -&state.big_slots[src];
|
||||||
state.big_slots[dest] = value;
|
state.big_slots[dest] = value;
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
MulSmall {
|
Add {
|
||||||
dest: StatePartIndex<StatePartKindSmallSlots>,
|
#[kind = Output]
|
||||||
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 {
|
|
||||||
dest: StatePartIndex<StatePartKindBigSlots>,
|
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>,
|
value: Interned<BigInt>,
|
||||||
} => {
|
} => {
|
||||||
state.big_slots[dest].clone_from(&value);
|
state.big_slots[dest].clone_from(&value);
|
||||||
|
|
Loading…
Reference in a new issue