redo ShiftRotateMOp and write actual operation definition in doc comment
All checks were successful
/ test (pull_request) Successful in 6m56s
All checks were successful
/ test (pull_request) Successful in 6m56s
This commit is contained in:
parent
a3898e8c13
commit
7481d079d5
12 changed files with 18082 additions and 13351 deletions
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue