working on simulator
All checks were successful
/ deps (push) Successful in 18s
/ test (push) Successful in 4m49s

This commit is contained in:
Jacob Lifshay 2024-11-12 01:08:32 -08:00
parent 96b3f1fee4
commit 5b2abd3fca
Signed by: programmerjake
SSH key fingerprint: SHA256:B1iRVvUJkvd7upMIiMqn6OyxvD2SgJkAH3ZnUOj6z+c
4 changed files with 1454 additions and 589 deletions

5
Cargo.lock generated
View file

@ -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",
]

View file

@ -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

View file

@ -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);