redo ShiftRotateMOp and write actual operation definition in doc comment
All checks were successful
/ test (pull_request) Successful in 6m56s

This commit is contained in:
Jacob Lifshay 2026-05-28 01:41:31 -07:00
parent a3898e8c13
commit 7481d079d5
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
12 changed files with 18082 additions and 13351 deletions

View file

@ -719,7 +719,7 @@ impl InsnsBuilder {
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(shift.cast_to_static::<UInt<_>>()),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToUInt6(),
dest_logic_op: if rotated_output_len == 0 {
// rotated_output_len wrapped around to 64
HdlNone()
@ -735,7 +735,7 @@ impl InsnsBuilder {
)
},
},
OutputIntegerMode.Full64(),
OutputIntegerMode.DupLow32(),
ShiftRotateMode.FunnelShift2x32Bit(),
)],
));
@ -1838,157 +1838,103 @@ trait MockExecutionStateTrait: Default {
shift_amount_overflow_behavior,
dest_logic_op,
} = imm;
let shift_rotate_amount = #[hdl(sim)]
let (shift_rotate_amount, shifted_output_is_zero) = #[hdl(sim)]
match shift_rotate_amount {
HdlSome(shift_rotate_amount) => {
shift_rotate_amount.cast_to_static::<UInt<64>>().as_int()
HdlSome(shift_rotate_amount) => (
shift_rotate_amount.cast_to_static::<UInt<64>>().as_int(),
false,
),
HdlNone => {
let do_overflow_behavior = |width: usize, zero_if_ge_half| {
let shift_rotate_amount = src_values[2].inner().int_fp.as_int() % (1 << width);
(
shift_rotate_amount,
zero_if_ge_half && shift_rotate_amount >= 1 << (width - 1),
)
};
#[hdl(sim)]
match shift_amount_overflow_behavior {
ShiftAmountOverflowBehavior::WrapToUInt3 => do_overflow_behavior(3, false),
ShiftAmountOverflowBehavior::WrapToUInt4 => do_overflow_behavior(4, false),
ShiftAmountOverflowBehavior::WrapToUInt5 => do_overflow_behavior(5, false),
ShiftAmountOverflowBehavior::WrapToUInt6 => do_overflow_behavior(6, false),
ShiftAmountOverflowBehavior::WrapToUInt7 => do_overflow_behavior(7, false),
ShiftAmountOverflowBehavior::WrapToUInt8 => do_overflow_behavior(8, false),
ShiftAmountOverflowBehavior::WrapToUInt6ZeroIfGE32 => {
do_overflow_behavior(6, true)
}
ShiftAmountOverflowBehavior::WrapToUInt7ZeroIfGE64 => {
do_overflow_behavior(7, true)
}
}
}
HdlNone => src_values[2].inner().int_fp.as_int(),
};
let shifted_rotated = #[hdl(sim)]
let funnel_shift = |width: u32| -> u64 {
let Ok(shift_rotate_amount) = shift_rotate_amount.try_into() else {
return 0;
};
let mask = (1 << width) - 1;
let high = src_values[0].inner().int_fp.as_int() & mask;
let low = src_values[1].inner().int_fp.as_int() & mask;
let input = ((high as u128) << width) | low as u128;
if **shift_rotate_right {
input.unbounded_shr(shift_rotate_amount) as u64 & mask
} else {
(input.unbounded_shl(shift_rotate_amount) >> width) as u64 & mask
}
};
let sign_ext_shift = |width: u32| -> u64 {
let mut input = src_values[0].inner().int_fp.as_int() as i64;
input <<= 64 - width;
input >>= 64 - width;
let Ok(shift_rotate_amount) = shift_rotate_amount.try_into() else {
return 0;
};
if **shift_rotate_right {
input.unbounded_shr(shift_rotate_amount) as u64
} else {
input.unbounded_shl(shift_rotate_amount) as u64
}
};
let mut shifted = #[hdl(sim)]
match mode {
ShiftRotateMode::FunnelShift2x8Bit => {
if shift_rotate_amount >= 8 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
if **shift_rotate_right {
FunnelShift::funnel_shr(
src_values[0].inner().int_fp.as_int() as u8,
src_values[1].inner().int_fp.as_int() as u8,
shift_rotate_amount as _,
) as u64
} else {
FunnelShift::funnel_shl(
src_values[0].inner().int_fp.as_int() as u8,
src_values[1].inner().int_fp.as_int() as u8,
shift_rotate_amount as _,
) as u64
}
}
ShiftRotateMode::FunnelShift2x16Bit => {
if shift_rotate_amount >= 16 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
if **shift_rotate_right {
FunnelShift::funnel_shr(
src_values[0].inner().int_fp.as_int() as u16,
src_values[1].inner().int_fp.as_int() as u16,
shift_rotate_amount as _,
) as u64
} else {
FunnelShift::funnel_shl(
src_values[0].inner().int_fp.as_int() as u16,
src_values[1].inner().int_fp.as_int() as u16,
shift_rotate_amount as _,
) as u64
}
}
ShiftRotateMode::FunnelShift2x32Bit => {
if shift_rotate_amount >= 32 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
if **shift_rotate_right {
FunnelShift::funnel_shr(
src_values[0].inner().int_fp.as_int() as u32,
src_values[1].inner().int_fp.as_int() as u32,
shift_rotate_amount as _,
) as u64
} else {
FunnelShift::funnel_shl(
src_values[0].inner().int_fp.as_int() as u32,
src_values[1].inner().int_fp.as_int() as u32,
shift_rotate_amount as _,
) as u64
}
}
ShiftRotateMode::FunnelShift2x64Bit => {
if shift_rotate_amount >= 64 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
if **shift_rotate_right {
FunnelShift::funnel_shr(
src_values[0].inner().int_fp.as_int(),
src_values[1].inner().int_fp.as_int(),
shift_rotate_amount as _,
)
} else {
FunnelShift::funnel_shl(
src_values[0].inner().int_fp.as_int(),
src_values[1].inner().int_fp.as_int(),
shift_rotate_amount as _,
)
}
}
ShiftRotateMode::SignExt8To64BitThenShift => {
if shift_rotate_amount >= 64 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
let input = src_values[0].inner().int_fp.as_int() as i8 as i64;
if **shift_rotate_right {
(input >> shift_rotate_amount) as u64
} else {
(input << shift_rotate_amount) as u64
}
}
ShiftRotateMode::SignExt16To64BitThenShift => {
if shift_rotate_amount >= 64 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
let input = src_values[0].inner().int_fp.as_int() as i16 as i64;
if **shift_rotate_right {
(input >> shift_rotate_amount) as u64
} else {
(input << shift_rotate_amount) as u64
}
}
ShiftRotateMode::SignExt32To64BitThenShift => {
if shift_rotate_amount >= 64 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
let input = src_values[0].inner().int_fp.as_int() as i32 as i64;
if **shift_rotate_right {
(input >> shift_rotate_amount) as u64
} else {
(input << shift_rotate_amount) as u64
}
}
ShiftRotateMode::ShiftSigned64 => {
if shift_rotate_amount >= 64 {
todo!("large shift_rotate_amount={shift_rotate_amount}");
}
let input = src_values[0].inner().int_fp.as_int() as i64;
if **shift_rotate_right {
(input >> shift_rotate_amount) as u64
} else {
(input << shift_rotate_amount) as u64
}
}
ShiftRotateMode::FunnelShift2x8Bit => funnel_shift(8),
ShiftRotateMode::FunnelShift2x16Bit => funnel_shift(16),
ShiftRotateMode::FunnelShift2x32Bit => funnel_shift(32),
ShiftRotateMode::FunnelShift2x64Bit => funnel_shift(64),
ShiftRotateMode::SignExt8To64BitThenShift => sign_ext_shift(8),
ShiftRotateMode::SignExt16To64BitThenShift => sign_ext_shift(16),
ShiftRotateMode::SignExt32To64BitThenShift => sign_ext_shift(32),
ShiftRotateMode::ShiftSigned64 => sign_ext_shift(64),
};
let masked = #[hdl(sim)]
if shifted_output_is_zero {
shifted = 0
};
let extended = #[hdl(sim)]
match output_integer_mode {
OutputIntegerMode::Full64 => shifted,
OutputIntegerMode::DupLow32 => (shifted & 0xFFFFFFFF) | (shifted << 32),
OutputIntegerMode::ZeroExt32 => shifted as u32 as u64,
OutputIntegerMode::SignExt32 => shifted as i32 as u64,
OutputIntegerMode::ZeroExt16 => shifted as u16 as u64,
OutputIntegerMode::SignExt16 => shifted as i16 as u64,
OutputIntegerMode::ZeroExt8 => shifted as u8 as u64,
OutputIntegerMode::SignExt8 => shifted as i8 as u64,
};
let output = #[hdl(sim)]
if let HdlSome(dest_logic_op) = dest_logic_op {
ShiftRotateDestLogicOp::operation_sim(
dest_logic_op,
shifted_rotated,
extended,
&src_values[2].inner().int_fp,
)
.as_int()
} else {
shifted_rotated
};
let int_fp = #[hdl(sim)]
match output_integer_mode {
OutputIntegerMode::Full64 => masked,
OutputIntegerMode::DupLow32 => (masked & 0xFFFFFFFF) | (masked << 32),
OutputIntegerMode::ZeroExt32 => masked as u32 as u64,
OutputIntegerMode::SignExt32 => masked as i32 as u64,
OutputIntegerMode::ZeroExt16 => masked as u16 as u64,
OutputIntegerMode::SignExt16 => masked as i16 as u64,
OutputIntegerMode::ZeroExt8 => masked as u8 as u64,
OutputIntegerMode::SignExt8 => masked as i8 as u64,
extended
};
let retval = #[hdl(sim)]
PRegValue {
int_fp,
int_fp: output,
flags: PRegFlags::zeroed_sim(), // TODO: compute flags
};
retval.into_trace_as_string()