Compare commits

..

10 commits

17 changed files with 475108 additions and 27307 deletions

View file

@ -1953,10 +1953,18 @@ impl DecodeState<'_> {
ShiftRotateMOpImm {
shift_rotate_amount: HdlNone(),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
shift_amount_overflow_behavior: if is_32bit {
ShiftAmountOverflowBehavior.WrapToUInt5()
} else {
ShiftAmountOverflowBehavior.WrapToUInt6()
},
dest_logic_op,
},
OutputIntegerMode.Full64(),
if is_32bit {
OutputIntegerMode.DupLow32()
} else {
OutputIntegerMode.Full64()
},
if is_32bit {
ShiftRotateMode.FunnelShift2x32Bit()
} else {
@ -2004,10 +2012,14 @@ impl DecodeState<'_> {
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(rotate_amount),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToUInt6(),
dest_logic_op,
},
OutputIntegerMode.Full64(),
if is_32bit {
OutputIntegerMode.DupLow32()
} else {
OutputIntegerMode.Full64()
},
if is_32bit {
ShiftRotateMode.FunnelShift2x32Bit()
} else {
@ -2156,7 +2168,7 @@ impl DecodeState<'_> {
shift_rotate_amount: HdlSome(sh.cast_to_static::<UInt<_>>()),
shift_rotate_right: true,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToWidth(),
.WrapToUInt6(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2186,7 +2198,7 @@ impl DecodeState<'_> {
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
shift_rotate_right: true,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToWidth(),
.WrapToUInt6(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2228,8 +2240,19 @@ impl DecodeState<'_> {
ShiftRotateMOpImm {
shift_rotate_amount: HdlNone(),
shift_rotate_right: is_right_shift,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToTwiceWidth(),
shift_amount_overflow_behavior: if is_signed && is_right_shift {
if is_32bit {
ShiftAmountOverflowBehavior.WrapToUInt6()
} else {
ShiftAmountOverflowBehavior.WrapToUInt7()
}
} else {
if is_32bit {
ShiftAmountOverflowBehavior.WrapToUInt6ZeroIfGE32()
} else {
ShiftAmountOverflowBehavior.WrapToUInt7ZeroIfGE64()
}
},
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
@ -2266,7 +2289,7 @@ impl DecodeState<'_> {
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
.WrapToWidth(),
.WrapToUInt6(),
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),

View file

@ -2157,21 +2157,21 @@ impl<DestReg: Type, SrcReg: Type> LogicalMOp<DestReg, SrcReg, ConstUsize<1>> {
#[hdl(cmp_eq)]
pub enum ShiftRotateMode {
/// like `llvm.fsh[lr].i8(src0, src1, shift_rotate_amount.unwrap_or(src2))`
/// like `llvm.fsh[lr].i8(src0, src1, shift_rotate_amount)` then zero-extended to 64-bits
FunnelShift2x8Bit,
/// like `llvm.fsh[lr].i16(src0, src1, shift_rotate_amount.unwrap_or(src2))`
/// like `llvm.fsh[lr].i16(src0, src1, shift_rotate_amount)` then zero-extended to 64-bits
FunnelShift2x16Bit,
/// like `llvm.fsh[lr].i32(src0, src1, shift_rotate_amount.unwrap_or(src2))`
/// like `llvm.fsh[lr].i32(src0, src1, shift_rotate_amount)` then zero-extended to 64-bits
FunnelShift2x32Bit,
/// like `llvm.fsh[lr].i64(src0, src1, shift_rotate_amount.unwrap_or(src2))`
/// like `llvm.fsh[lr].i64(src0, src1, shift_rotate_amount)`
FunnelShift2x64Bit,
/// `shift(src0 as i8 as i64, shift_rotate_amount.unwrap_or(src2))`
/// `shift(src0 as i8 as i64, shift_rotate_amount)`
SignExt8To64BitThenShift,
/// `shift(src0 as i16 as i64, shift_rotate_amount.unwrap_or(src2))`
/// `shift(src0 as i16 as i64, shift_rotate_amount)`
SignExt16To64BitThenShift,
/// `shift(src0 as i32 as i64, shift_rotate_amount.unwrap_or(src2))`
/// `shift(src0 as i32 as i64, shift_rotate_amount)`
SignExt32To64BitThenShift,
/// `shift(src0 as i64, shift_rotate_amount.unwrap_or(src2))`
/// `shift(src0 as i64, shift_rotate_amount)`
ShiftSigned64,
}
@ -2275,10 +2275,22 @@ impl ShiftRotateDestLogicOp {
#[hdl(cmp_eq)]
pub enum ShiftAmountOverflowBehavior {
/// wrap shift amount to width specified by [`ShiftRotateMode`]
WrapToWidth,
/// wrap shift amount to twice the width specified by [`ShiftRotateMode`]
WrapToTwiceWidth,
/// the shift amount is wrapped to fit in [`UInt<3>`], this is the same as `shift_rotate_amount % 8`
WrapToUInt3,
/// the shift amount is wrapped to fit in [`UInt<4>`], this is the same as `shift_rotate_amount % 0x10`
WrapToUInt4,
/// the shift amount is wrapped to fit in [`UInt<5>`], this is the same as `shift_rotate_amount % 0x20`
WrapToUInt5,
/// the shift amount is wrapped to fit in [`UInt<6>`], this is the same as `shift_rotate_amount % 0x40`
WrapToUInt6,
/// the shift amount is wrapped to fit in [`UInt<7>`], this is the same as `shift_rotate_amount % 0x80`
WrapToUInt7,
/// the shift amount is wrapped to fit in [`UInt<8>`], this is the same as `shift_rotate_amount % 0x100`
WrapToUInt8,
/// the shift amount is wrapped to fit in [`UInt<6>`] but the shifted output is zero if the wrapped shift amount is `>= 32`
WrapToUInt6ZeroIfGE32,
/// the shift amount is wrapped to fit in [`UInt<7>`] but the shifted output is zero if the wrapped shift amount is `>= 64`
WrapToUInt7ZeroIfGE64,
}
/// immediate values for [`ShiftRotateMOp`].
@ -2349,6 +2361,31 @@ common_mop_struct! {
})]
#[mapped(<NewDestReg, NewSrcReg> ShiftRotateMOp<NewDestReg, NewSrcReg>)]
#[hdl(cmp_eq, custom_debug(sim))]
/// Shift/Rotate.
///
/// Operation:
/// * If [`imm.shift_rotate_amount`] is `HdlSome(v)`, then:
/// * `shift_rotate_amount` is set to `v`.
/// * `shifted_output_is_zero` is set to `false`.
/// * Otherwise:
/// * `shift_rotate_amount` and `shifted_output_is_zero` are set to the result
/// of processing `src2` according to [`imm.shift_amount_overflow_behavior`].
/// * `shifted` is set to the result of shifting/rotating `src0` and `src1` by
/// `shift_rotate_amount` according to [`mode`] and [`imm.shift_rotate_right`].
/// * If `shifted_output_is_zero`, then `shifted` is set to `0`.
/// * `extended` is set to the result of processing `shifted` according to
/// [`alu_common.output_integer_mode`].
/// * If [`imm.dest_logic_op`] is `HdlSome(o)`, then:
/// * `output` is set to the result of processing `extended` according
/// to `o` (see [`ShiftRotateDestLogicOp::operation`]).
/// * Otherwise:
/// * `output` is set to `extended`.
///
/// [`imm.shift_rotate_amount`]: ShiftRotateMOpImm::shift_rotate_amount
/// [`imm.shift_amount_overflow_behavior`]: ShiftRotateMOpImm::shift_amount_overflow_behavior
/// [`mode`]: Self::mode
/// [`imm.shift_rotate_right`]: ShiftRotateMOpImm::shift_rotate_right
/// [`imm.dest_logic_op`]: ShiftRotateMOpImm::dest_logic_op
pub struct ShiftRotateMOp<DestReg: Type, SrcReg: Type> {
#[common]
pub alu_common: AluCommonMOp<DestReg, SrcReg, ConstUsize<3>, ShiftRotateMOpImm>,

View file

@ -11,5 +11,6 @@ pub mod powerisa_instructions_xml;
pub mod reg_alloc;
pub mod register;
pub mod rename_execute_retire;
pub mod test;
pub mod unit;
pub mod util;

View file

@ -13,7 +13,7 @@ use crate::{
COMMON_MOP_SRC_LEN, L2RegNum, MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, ReadL2RegMOp,
UnitNum, UnitOutRegNum, WriteL2RegMOp,
},
next_pc::{CallStackOp, SimValueDefault},
next_pc::{CallStackOp, FETCH_BLOCK_ID_WIDTH, SimValueDefault},
register::{FlagsMode, PRegFlagsPowerISA, PRegValue},
rename_execute_retire::{
rename_table::{RenameTable, RenameTableDebugState, RenameTableEntry, RenameTableUpdate},
@ -42,7 +42,7 @@ pub type MOpId = UInt<{ MOP_ID_WIDTH }>;
#[hdl(custom_debug(sim))]
/// A &micro;Op along with the state needed for this instance of the &micro;Op.
pub struct MOpInstance<MOp> {
pub fetch_block_id: UInt<8>,
pub fetch_block_id: UInt<{ FETCH_BLOCK_ID_WIDTH }>,
pub id: MOpId,
pub pc: UInt<64>,
/// initialized to 0 by decoder, overwritten by `next_pc()`

4
crates/cpu/src/test.rs Normal file
View file

@ -0,0 +1,4 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
pub mod decode_and_run_single_insn;

View file

@ -0,0 +1,477 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
config::{CpuConfig, CpuConfigUnitCount, PhantomConstCpuConfig},
instruction::{MOp, MOpRegNum, MOpTrait, MoveRegMOp, PRegNum, UnitNum, UnitOutRegNum},
next_pc::FETCH_BLOCK_ID_WIDTH,
register::PRegValue,
rename_execute_retire::{
ExecuteToUnitInterface, GlobalState, MOpId, MOpInstance, NextPcPredictorOp, RenamedMOp,
to_unit_interfaces::ExecuteToUnitInterfaces,
},
unit::{HdlUnitKind, UnitMOp},
util::array_vec::ArrayVec,
};
use fayalite::{
bundle::BundleType,
int::UIntInRangeType,
intern::{Intern, Interned},
module::wire_with_loc,
prelude::*,
util::{prefix_sum::reduce, ready_valid::ReadyValid},
};
/// make arrays dynamically-sized to avoid putting large types on the stack
#[hdl(get(|c| 1 << MOpRegNum::WIDTH))]
type MOpRegCount<C: PhantomConstGet<CpuConfig>> = DynSize;
#[hdl(cmp_eq, no_static)]
pub struct Registers<C: PhantomConstGet<CpuConfig>> {
pub regs: ArrayType<TraceAsString<PRegValue>, MOpRegCount<C>>,
pub config: C,
}
impl<C: PhantomConstCpuConfig> Registers<C> {
#[hdl]
pub fn zeroed(self) -> Expr<Self> {
#[hdl]
Self {
regs: repeat(PRegValue::zeroed().into_trace_as_string(), self.regs.len()),
config: self.config,
}
}
#[hdl]
pub fn zeroed_sim(self) -> SimValue<Self> {
#[hdl(sim)]
Self {
regs: vec![PRegValue::zeroed_sim().into_trace_as_string(); self.regs.len()],
config: self.config,
}
}
}
#[hdl(no_static)]
pub struct DecodeOneInsnOutput<MaxMOpCount: Size> {
pub mops: ArrayVec<TraceAsString<MOp>, MaxMOpCount>,
pub size_in_bytes: UInt<4>,
pub is_illegal: Bool,
}
pub trait DecodeOneInsn: BundleType {
type Input: Type;
fn input_ty(self) -> Self::Input;
type MaxMOpCount: Size;
fn max_mop_count(self) -> <Self::MaxMOpCount as Size>::SizeType;
fn connect_io(
this: Expr<Self>,
input: Expr<Self::Input>,
output: Expr<DecodeOneInsnOutput<Self::MaxMOpCount>>,
);
}
pub type DecodeOneInsnInput<T> = <T as DecodeOneInsn>::Input;
#[doc(hidden)]
#[expect(non_upper_case_globals)]
pub const DecodeOneInsnInput: DecodeOneInsnInputWithoutGenerics =
DecodeOneInsnInputWithoutGenerics {};
#[doc(hidden)]
pub struct DecodeOneInsnInputWithoutGenerics {}
impl<T: DecodeOneInsn> std::ops::Index<T> for DecodeOneInsnInputWithoutGenerics {
type Output = DecodeOneInsnInput<T>;
fn index(&self, index: T) -> &Self::Output {
Interned::into_inner(index.input_ty().intern_sized())
}
}
pub type DecodeOneInsnMaxMOpCount<T> = <T as DecodeOneInsn>::MaxMOpCount;
#[doc(hidden)]
#[expect(non_upper_case_globals)]
pub const DecodeOneInsnMaxMOpCount: DecodeOneInsnMaxMOpCountWithoutGenerics =
DecodeOneInsnMaxMOpCountWithoutGenerics {};
#[doc(hidden)]
pub struct DecodeOneInsnMaxMOpCountWithoutGenerics {}
impl<T: DecodeOneInsn> std::ops::Index<T> for DecodeOneInsnMaxMOpCountWithoutGenerics {
type Output = <T::MaxMOpCount as Size>::SizeType;
fn index(&self, index: T) -> &Self::Output {
Interned::into_inner(index.max_mop_count().intern_sized())
}
}
#[hdl(no_static)]
pub struct DecodeAndRunSingleInsnInput<C: PhantomConstGet<CpuConfig>, I> {
pub decoder_input: I,
pub fetch_block_id: UInt<{ FETCH_BLOCK_ID_WIDTH }>,
pub first_id: MOpId,
pub pc: UInt<64>,
pub predicted_next_pc: UInt<64>,
pub regs: Registers<C>,
pub config: C,
}
#[hdl(no_static)]
pub struct DecodeAndRunSingleInsnOutput<C: PhantomConstGet<CpuConfig>, MaxMOpCount: Size> {
pub regs: Registers<C>,
pub cancel_and_start_at: HdlOption<UInt<64>>,
pub retired_insns: ArrayVec<NextPcPredictorOp<C>, MaxMOpCount>,
pub config: C,
}
#[hdl(no_static)]
struct UnrenamedMOpState<C: PhantomConstGet<CpuConfig>> {
unrenamed: MOpInstance<MOp>,
renamed: HdlOption<TraceAsString<RenamedMOp<C>>>,
}
#[hdl(no_static)]
enum Error {
NoUnitsOfKind(HdlUnitKind),
}
#[hdl(no_static)]
struct CancelState<C: PhantomConstGet<CpuConfig>, MaxMOpCount: Size> {
cancel_index: UIntInRangeType<ConstUsize<0>, MaxMOpCount>,
canceling_units: ArrayType<Bool, CpuConfigUnitCount<C>>,
config: C,
}
#[hdl(no_static)]
enum RunState<C: PhantomConstGet<CpuConfig>, MaxMOpCount: Size> {
RunningMOp(UIntInRangeType<ConstUsize<0>, MaxMOpCount>),
CancelingUnits(CancelState<C, MaxMOpCount>),
Finished,
Error(TraceAsString<Error>),
}
#[hdl(no_static)]
struct DecodeAndRunSingleInsnState<C: PhantomConstGet<CpuConfig>, MaxMOpCount: Size> {
mops: ArrayVec<UnrenamedMOpState<C>, MaxMOpCount>,
regs: Registers<C>,
run_state: RunState<C, MaxMOpCount>,
config: C,
}
#[hdl(no_static)]
enum StepOutput<C: PhantomConstGet<CpuConfig>, MaxMOpCount: Size> {
Finished(DecodeAndRunSingleInsnOutput<C, MaxMOpCount>),
Step(DecodeAndRunSingleInsnState<C, MaxMOpCount>),
Error(TraceAsString<Error>),
}
impl<C: PhantomConstCpuConfig, MaxMOpCount: Size> DecodeAndRunSingleInsnState<C, MaxMOpCount> {
#[hdl]
fn new(
input: Expr<DecodeAndRunSingleInsnInput<C, impl Type>>,
decoder_output: Expr<DecodeOneInsnOutput<MaxMOpCount>>,
config: C,
max_mop_count: MaxMOpCount::SizeType,
) -> Expr<Self> {
#[hdl]
let new_state = wire(DecodeAndRunSingleInsnState[config][max_mop_count]);
#[hdl]
let Self {
mops,
regs,
run_state,
config: _,
} = new_state;
connect(run_state, run_state.ty().Finished());
connect(
mops,
ArrayVec::map(
decoder_output.mops,
mops.ty().element(),
|index, decoded_mop| {
if index == 0 {
connect(
run_state,
#[hdl(sim)]
(run_state.ty()).RunningMOp(0usize),
);
}
let retval = wire_with_loc(
&format!("mops_{index}"),
SourceLocation::caller(),
UnrenamedMOpState[config],
);
#[hdl]
let UnrenamedMOpState::<_> { unrenamed, renamed } = retval;
#[hdl]
let MOpInstance::<_> {
fetch_block_id,
id,
pc,
predicted_next_pc,
size_in_bytes,
is_first_mop_in_insn,
is_last_mop_in_insn,
mop,
} = unrenamed;
connect(fetch_block_id, input.fetch_block_id);
connect(id, (input.first_id + index).cast_to_static::<MOpId>());
connect(pc, input.pc);
connect(predicted_next_pc, input.predicted_next_pc);
connect(size_in_bytes, decoder_output.size_in_bytes);
connect(is_first_mop_in_insn, index == 0);
connect(
is_last_mop_in_insn,
ArrayVec::len(decoder_output.mops).cmp_eq(index + 1),
);
connect(mop, decoded_mop);
#[hdl]
let renamed_untransformed_move = wire(
HdlOption[TraceAsString[UnitMOp[PRegNum[config]][PRegNum[config]]
[MoveRegMOp[PRegNum[config]][PRegNum[config]]]]],
);
#[hdl]
if let MOp::TransformedMove(_) = *mop {
connect(
renamed_untransformed_move,
renamed_untransformed_move.ty().HdlNone(),
);
} else {
let unit_kind = MOp::kind(*mop);
let available_units = config.get().available_units_for_kind(unit_kind);
let chosen_unit = reduce(
available_units.into_iter().enumerate().map(
|(unit_index, available_unit)| {
#[hdl]
let chosen_unit = wire(UnitNum[config]);
connect(chosen_unit, chosen_unit.ty().const_zero());
#[hdl]
if available_unit {
connect(
chosen_unit,
chosen_unit.ty().from_index(unit_index),
);
}
chosen_unit
},
),
|a, b| {
#[hdl]
let chosen_unit = wire(UnitNum[config]);
connect(chosen_unit, a);
#[hdl]
if a.cmp_eq(chosen_unit.ty().const_zero()) {
connect(chosen_unit, b);
}
chosen_unit
},
)
.unwrap_or(UnitNum[config].const_zero());
#[hdl]
if chosen_unit.cmp_eq(chosen_unit.ty().const_zero()) {
connect(
run_state,
run_state
.ty()
.Error(Error.NoUnitsOfKind(unit_kind).to_trace_as_string()),
);
}
let unit_out_reg_num_ty = UnitOutRegNum[config];
connect(
renamed_untransformed_move,
HdlSome(
MOpTrait::map_regs(
*mop,
#[hdl]
PRegNum::<_> {
unit_num: chosen_unit,
unit_out_reg: #[hdl]
UnitOutRegNum::<_> {
value: !unit_out_reg_num_ty.value.zero(),
config,
},
},
PRegNum[config],
&mut |src_reg, index| {
#[hdl]
let renamed_src_reg = wire(PRegNum[config]);
#[hdl]
if src_reg.cmp_eq(MOpRegNum::const_zero()) {
connect(
renamed_src_reg,
renamed_src_reg.ty().const_zero(),
);
} else {
connect(
renamed_src_reg,
#[hdl]
PRegNum::<_> {
unit_num: chosen_unit,
unit_out_reg: unit_out_reg_num_ty
.new_sim(index),
},
);
}
renamed_src_reg
},
)
.to_trace_as_string(),
),
);
}
connect(renamed, renamed.ty().HdlNone());
#[hdl]
if let HdlSome(renamed_untransformed_move) = renamed_untransformed_move {
let v = UnitMOp::try_with_transformed_move_op(
*renamed_untransformed_move,
renamed.ty().HdlSome.inner_ty().TransformedMove,
|dest, _src| {
connect(dest, dest.ty().HdlNone());
},
);
#[hdl]
if let HdlSome(v) = v {
connect(renamed, HdlSome(v.to_trace_as_string()));
}
}
retval
},
),
);
connect(regs, input.regs);
new_state
}
#[hdl]
fn step(
this: Expr<Self>,
to_units: Expr<ExecuteToUnitInterfaces<C>>,
) -> Expr<StepOutput<C, MaxMOpCount>> {
#[hdl]
let Self {
mops,
regs,
run_state,
config,
} = this;
let config = config.ty();
let max_mop_count = MaxMOpCount::from_usize(mops.ty().capacity());
#[hdl]
let stepped = wire(StepOutput[config][max_mop_count]);
#[hdl]
match run_state {
RunState::<_, _>::RunningMOp(cur_mop_index) => {
todo!();
}
RunState::<_, _>::CancelingUnits(cancel_state) => {
todo!();
}
RunState::<_, _>::Finished => {
todo!();
}
RunState::<_, _>::Error(error) => {
connect(stepped, stepped.ty().Error(error));
}
}
stepped
}
}
#[hdl_module]
pub fn decode_and_run_single_insn<C: Type + PhantomConstCpuConfig, D: Type + DecodeOneInsn>(
config: C,
decoder: Interned<Module<D>>,
) {
#[hdl]
let cd: ClockDomain = m.input();
#[hdl]
let input: ReadyValid<DecodeAndRunSingleInsnInput<C, DecodeOneInsnInput<D>>> = m.input(
ReadyValid[DecodeAndRunSingleInsnInput[config][DecodeOneInsnInput[decoder.io_ty()]]],
);
#[hdl]
let global_state: GlobalState = m.input();
#[hdl]
let output: ReadyValid<DecodeAndRunSingleInsnOutput<C, DecodeOneInsnMaxMOpCount<D>>> = m
.output(
ReadyValid
[DecodeAndRunSingleInsnOutput[config][DecodeOneInsnMaxMOpCount[decoder.io_ty()]]],
);
#[hdl]
let to_units: ExecuteToUnitInterfaces<C> = m.output(ExecuteToUnitInterfaces[config]);
#[hdl]
let error: Bool = m.output();
for to_unit in ExecuteToUnitInterfaces::unit_fields(to_units) {
#[hdl]
let ExecuteToUnitInterface::<_> {
global_state: global_state_,
enqueue,
inputs_ready,
is_no_longer_speculative,
cant_cause_cancel: _,
output_ready: _,
finish_cause_cancel: _,
unit_outputs_ready,
cancel_all,
config: _,
} = to_unit;
connect(global_state_, global_state);
connect(enqueue.data, enqueue.ty().data.HdlNone());
connect(inputs_ready, inputs_ready.ty().HdlNone());
connect(
is_no_longer_speculative,
is_no_longer_speculative.ty().HdlNone(),
);
connect(unit_outputs_ready, false);
connect(cancel_all.data, HdlNone());
}
connect(error, false);
#[hdl]
let decoder = instance(decoder);
#[hdl]
let decoder_input = wire(decoder.ty().input_ty());
connect(decoder_input, decoder_input.ty().uninit());
#[hdl]
let decoder_output = wire(DecodeOneInsnOutput[decoder.ty().max_mop_count()]);
D::connect_io(decoder, decoder_input, decoder_output);
#[hdl]
let state_reg = reg_builder().clock_domain(cd).reset(
HdlOption[DecodeAndRunSingleInsnState[config][decoder.ty().max_mop_count()]].HdlNone(),
);
#[hdl]
if let HdlSome(state) = state_reg {
connect(input.ready, false);
let step = DecodeAndRunSingleInsnState::step(state, to_units);
#[hdl]
match step {
StepOutput::<_, _>::Finished(v) => {
connect(output.data, HdlSome(v));
#[hdl]
if output.ready {
connect(state_reg, state_reg.ty().HdlNone());
}
}
StepOutput::<_, _>::Step(state) => {
connect(state_reg, HdlSome(state));
}
StepOutput::<_, _>::Error(_) => {
connect(error, true);
}
}
} else {
connect(input.ready, true);
connect(output.data, output.ty().data.HdlNone());
#[hdl]
if let HdlSome(input) = input.data {
connect(
state_reg,
HdlSome(DecodeAndRunSingleInsnState::new(
input,
decoder_output,
config,
decoder.ty().max_mop_count(),
)),
);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -226,6 +226,10 @@ impl<T: Type, N: Size> ArrayVec<T, N> {
#[hdl]
let mapped_array_vec = wire(this.ty().mapped_ty(new_element_ty));
connect(mapped_array_vec.len, this.len);
connect(
mapped_array_vec.elements,
mapped_array_vec.ty().elements.uninit(),
);
Self::for_each(this, |index, element| {
connect(mapped_array_vec[index], f(index, element));
});

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

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(),
)],
));
@ -1642,7 +1642,7 @@ macro_rules! impl_funnel_shift {
}
fn funnel_shr(high: Self, low: Self, shift: u32) -> Self {
if shift == 0 {
high
low
} else {
(high << ($ty::BITS - shift)) | (low >> shift)
}
@ -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()
@ -4270,6 +4216,43 @@ fn test_rename_execute_retire_fibonacci_combinatorial() {
assert!(sim.read_bool(sim.io().all_outputs_written));
}
#[hdl]
#[test]
fn test_rename_execute_retire_fibonacci_real() {
let _n = SourceLocation::normalize_files_for_tests();
let mut config = CpuConfig::new(
vec![
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::LoadStore),
UnitConfig::new(UnitKind::TransformedMove),
],
NonZeroUsize::new(20).unwrap(),
);
config.fetch_width = NonZeroUsize::new(3).unwrap();
let m = rename_execute_retire_test_harness::<FibonacciInsns>(
PhantomConst::new_sized(config),
AluBranchKind::Real,
);
let mut sim = Simulation::new(m);
let _checked_vcd_output = checked_vcd_output!(
&mut sim,
"tests/expected/rename_execute_retire_fibonacci_real.vcd",
);
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
for cycle in 0..200 {
sim.advance_time(SimDuration::from_nanos(500));
println!("clock tick: {cycle}");
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, false);
}
assert!(sim.read_bool(sim.io().all_outputs_written));
}
struct SlowLoopInsns;
impl SlowLoopInsns {
@ -4389,6 +4372,46 @@ fn test_rename_execute_retire_slow_loop() {
assert!(sim.read_bool(sim.io().started_any_l2_reg_file_ops));
}
#[hdl]
#[test]
fn test_rename_execute_retire_slow_loop_real() {
let _n = SourceLocation::normalize_files_for_tests();
let mut config = CpuConfig::new(
vec![
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::LoadStore),
UnitConfig::new(UnitKind::TransformedMove),
],
NonZeroUsize::new(20).unwrap(),
);
config.fetch_width = NonZeroUsize::new(4).unwrap();
let m = rename_execute_retire_test_harness::<SlowLoopInsns>(
PhantomConst::new_sized(config),
AluBranchKind::Real,
);
let mut sim = Simulation::new(m);
let _checked_vcd_output = checked_vcd_output!(
&mut sim,
"tests/expected/rename_execute_retire_slow_loop_real.vcd",
);
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
for cycle in 0..350 {
sim.advance_time(SimDuration::from_nanos(500));
println!("clock tick: {cycle}");
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, false);
}
assert!(sim.read_bool(sim.io().all_outputs_written));
// make sure we're actually testing L2 reg file ops
assert!(sim.read_bool(sim.io().started_any_l2_reg_file_ops));
}
/// equivalent of Unix's `head -n1`
struct HeadN1Insns;
@ -4508,6 +4531,42 @@ fn test_rename_execute_retire_head_n1() {
assert!(sim.read_bool(sim.io().all_outputs_written));
}
#[hdl]
#[test]
fn test_rename_execute_retire_head_n1_real() {
let _n = SourceLocation::normalize_files_for_tests();
let mut config = CpuConfig::new(
vec![
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::AluBranch),
UnitConfig::new(UnitKind::LoadStore),
UnitConfig::new(UnitKind::TransformedMove),
],
NonZeroUsize::new(20).unwrap(),
);
config.fetch_width = NonZeroUsize::new(2).unwrap();
let m = rename_execute_retire_test_harness::<HeadN1Insns>(
PhantomConst::new_sized(config),
AluBranchKind::Real,
);
let mut sim = Simulation::new(m);
let _checked_vcd_output = checked_vcd_output!(
&mut sim,
"tests/expected/rename_execute_retire_head_n1_real.vcd",
);
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
for cycle in 0..300 {
sim.advance_time(SimDuration::from_nanos(500));
println!("clock tick: {cycle}");
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, false);
}
assert!(sim.read_bool(sim.io().all_outputs_written));
}
struct SaveRestoreGprsInsns;
impl SaveRestoreGprsInsns {

File diff suppressed because it is too large Load diff

View file

@ -3,9 +3,10 @@
use crate::test_cases::TestCase;
use cpu::{
decoder::simple_power_isa::decode_one_insn, instruction::MOp, util::array_vec::ArrayVec,
checked_vcd_output, decoder::simple_power_isa::decode_one_insn, instruction::MOp,
util::array_vec::ArrayVec,
};
use fayalite::{prelude::*, sim::vcd::VcdWriterDecls, util::RcWriter};
use fayalite::prelude::*;
use std::{fmt::Write as _, io::Write, process::Command};
mod test_cases;
@ -127,22 +128,10 @@ fn test_decode_insn() {
let _n = SourceLocation::normalize_files_for_tests();
let m = decode_one_insn();
let mut sim = Simulation::new(m);
let writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
struct DumpVcdOnDrop {
writer: Option<RcWriter>,
}
impl Drop for DumpVcdOnDrop {
fn drop(&mut self) {
if let Some(mut writer) = self.writer.take() {
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
}
}
}
let mut writer = DumpVcdOnDrop {
writer: Some(writer),
};
let _checked_vcd_output = checked_vcd_output!(
&mut sim,
"tests/simple_power_isa_decoder/expected/decode_one_insn.vcd",
);
for test_case @ TestCase {
mnemonic: _,
first_input,
@ -185,11 +174,6 @@ fn test_decode_insn() {
"test_case={test_case:#?}\noutput={output}\nexpected={expected}"
);
}
let vcd = String::from_utf8(writer.writer.take().unwrap().take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != include_str!("expected/decode_one_insn.vcd") {
panic!();
}
}
#[hdl]

View file

@ -9,7 +9,11 @@ use cpu::instruction::{
use fayalite::prelude::*;
#[hdl]
fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
fn shift_imm(
amount: Option<u8>,
shift_right: bool,
overflow_behavior: Expr<ShiftAmountOverflowBehavior>,
) -> Expr<ShiftRotateMOpImm> {
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: if let Some(amount) = amount {
@ -18,11 +22,7 @@ fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
HdlNone()
},
shift_rotate_right: shift_right,
shift_amount_overflow_behavior: if amount.is_some() {
ShiftAmountOverflowBehavior.WrapToWidth()
} else {
ShiftAmountOverflowBehavior.WrapToTwiceWidth()
},
shift_amount_overflow_behavior: overflow_behavior,
dest_logic_op: HdlNone(),
}
}
@ -30,6 +30,7 @@ fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
#[hdl]
fn rotate_imm(
amount: Option<u8>,
overflow_behavior: Expr<ShiftAmountOverflowBehavior>,
rotated_output_start_and_len: Option<(u8, u8)>,
fallback_is_src2: bool,
) -> SimValue<ShiftRotateMOpImm> {
@ -37,7 +38,7 @@ fn rotate_imm(
ShiftRotateMOpImm {
shift_rotate_amount: amount.map(|amount| amount.cast_to_static::<UInt<_>>()),
shift_rotate_right: false,
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
shift_amount_overflow_behavior: overflow_behavior,
dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) =
rotated_output_start_and_len
{
@ -80,9 +81,15 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
$encoding:literal;
$rotated_output_start_and_len:expr;
$fallback_is_src2:literal;
$output_integer_mode:ident;
$shift_rotate_mode:ident;
) => {{
let imm = rotate_imm(Some($amount), $rotated_output_start_and_len, $fallback_is_src2);
let imm = rotate_imm(
Some($amount),
ShiftAmountOverflowBehavior.WrapToUInt6(),
$rotated_output_start_and_len,
$fallback_is_src2,
);
let src2 = rotate_imm_src2(&imm, $dest);
retval.push(insn_single(
concat!(
@ -106,7 +113,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
src2,
],
&imm,
OutputIntegerMode.Full64(),
OutputIntegerMode.$output_integer_mode(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
@ -132,7 +139,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
src2,
],
imm,
OutputIntegerMode.Full64(),
OutputIntegerMode.$output_integer_mode(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
@ -142,7 +149,9 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal $(, $args:literal)*;
$encoding:literal;
$overflow_behavior:ident;
$rotated_output_start_and_len:expr;
$output_integer_mode:ident;
$shift_rotate_mode:ident;
) => {{
retval.push(insn_single(
@ -166,8 +175,13 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
rotate_imm(None, $rotated_output_start_and_len, false),
OutputIntegerMode.Full64(),
rotate_imm(
None,
ShiftAmountOverflowBehavior.$overflow_behavior(),
$rotated_output_start_and_len,
false,
),
OutputIntegerMode.$output_integer_mode(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
@ -192,8 +206,13 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
rotate_imm(None, $rotated_output_start_and_len, false),
OutputIntegerMode.Full64(),
rotate_imm(
None,
ShiftAmountOverflowBehavior.$overflow_behavior(),
$rotated_output_start_and_len,
false,
),
OutputIntegerMode.$output_integer_mode(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
@ -205,6 +224,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x54830000;
Some((31, 1));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -212,6 +232,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x54832800;
Some((31, 1));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -219,6 +240,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x5483f800;
Some((31, 1));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -226,6 +248,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x54832820;
Some((15, 17));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -233,6 +256,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x5483283e;
Some((0, 32));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -240,6 +264,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x54832ffe;
Some((0, 1));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -247,37 +272,48 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x54832fc0;
Some((31, 34));
false;
DupLow32;
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 0, 0;
0x5c832800;
WrapToUInt5;
Some((31, 1));
DupLow32;
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 0, 16;
0x5c832820;
WrapToUInt5;
Some((15, 17));
DupLow32;
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 0, 31;
0x5c83283e;
WrapToUInt5;
Some((0, 32));
DupLow32;
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 31, 31;
0x5c832ffe;
WrapToUInt5;
Some((0, 1));
DupLow32;
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 31, 0;
0x5c832fc0;
WrapToUInt5;
Some((31, 34));
DupLow32;
FunnelShift2x32Bit;
}
@ -286,6 +322,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x50830000;
Some((31, 1));
true;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -293,6 +330,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x50832800;
Some((31, 1));
true;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -300,6 +338,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x5083f800;
Some((31, 1));
true;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -307,6 +346,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x50832820;
Some((15, 17));
true;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -314,6 +354,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x5083283e;
Some((0, 32));
true;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -321,6 +362,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x50832ffe;
Some((0, 1));
true;
DupLow32;
FunnelShift2x32Bit;
}
rotate_imm! {
@ -328,6 +370,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x50832fc0;
Some((31, 34));
true;
DupLow32;
FunnelShift2x32Bit;
}
@ -336,6 +379,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78830000;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -343,6 +387,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832800;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -350,6 +395,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78838000;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -357,6 +403,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883f800;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -364,6 +411,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78830002;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -371,6 +419,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883f802;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -378,6 +427,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832940;
Some((0, 59));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -385,6 +435,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832c00;
Some((0, 48));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -392,6 +443,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832fc0;
Some((0, 33));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -399,6 +451,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832820;
Some((0, 32));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -406,6 +459,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832fe0;
Some((0, 1));
false;
Full64;
FunnelShift2x64Bit;
}
@ -414,6 +468,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307e4;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -421,6 +476,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832fe4;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -428,6 +484,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788387e4;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -435,6 +492,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883ffe4;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -442,6 +500,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307e6;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -449,6 +508,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883ffe6;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -456,6 +516,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832804;
Some((63, 1));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -463,6 +524,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832944;
Some((58, 6));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -470,6 +532,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832c04;
Some((47, 17));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -477,6 +540,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832fc4;
Some((32, 32));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -484,6 +548,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832824;
Some((31, 33));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -491,6 +556,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78832fe4;
None;
false;
Full64;
FunnelShift2x64Bit;
}
@ -499,6 +565,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78830008;
None;
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -506,6 +573,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78830408;
Some((0, 48));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -513,6 +581,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307c8;
Some((0, 33));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -520,6 +589,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x78830028;
Some((0, 32));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -527,6 +597,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307e8;
Some((0, 1));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -534,6 +605,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788387e8;
Some((16, 49));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -541,6 +613,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883ffe8;
Some((31, 34));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -548,6 +621,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307ea;
Some((32, 33));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -555,6 +629,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883ffea;
Some((63, 2));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -562,6 +637,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883f82a;
Some((63, 33));
false;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -569,80 +645,105 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883f80a;
Some((63, 1));
false;
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 0;
0x78832810;
WrapToUInt6;
None;
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 5;
0x78832950;
WrapToUInt6;
Some((0, 59));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 16;
0x78832c10;
WrapToUInt6;
Some((0, 48));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 31;
0x78832fd0;
WrapToUInt6;
Some((0, 33));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 32;
0x78832830;
WrapToUInt6;
Some((0, 32));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 63;
0x78832ff0;
WrapToUInt6;
Some((0, 1));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 0;
0x78832812;
WrapToUInt6;
Some((63, 1));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 5;
0x78832952;
WrapToUInt6;
Some((58, 6));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 16;
0x78832c12;
WrapToUInt6;
Some((47, 17));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 31;
0x78832fd2;
WrapToUInt6;
Some((32, 32));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 32;
0x78832832;
WrapToUInt6;
Some((31, 33));
Full64;
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 63;
0x78832ff2;
WrapToUInt6;
None;
Full64;
FunnelShift2x64Bit;
}
@ -651,6 +752,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883000c;
None;
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -658,6 +760,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883040c;
Some((0, 48));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -665,6 +768,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307cc;
Some((0, 33));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -672,6 +776,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883002c;
Some((0, 32));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -679,6 +784,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307ec;
Some((0, 1));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -686,6 +792,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788387ec;
Some((16, 49));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -693,6 +800,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883ffec;
Some((31, 34));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -700,6 +808,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x788307ee;
Some((32, 33));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -707,6 +816,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883ffee;
Some((63, 2));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -714,6 +824,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883f82e;
Some((63, 33));
true;
Full64;
FunnelShift2x64Bit;
}
rotate_imm! {
@ -721,6 +832,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7883f80e;
Some((63, 1));
true;
Full64;
FunnelShift2x64Bit;
}
@ -728,6 +840,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
$encoding:literal;
$overflow_behavior:ident;
$shift_rotate_mode:ident;
) => {{
retval.push(insn_single(
@ -749,7 +862,11 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, false),
shift_imm(
None,
false,
ShiftAmountOverflowBehavior.$overflow_behavior(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -776,7 +893,11 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, false),
shift_imm(
None,
false,
ShiftAmountOverflowBehavior.$overflow_behavior(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -787,6 +908,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
$encoding:literal;
$overflow_behavior:ident;
$shift_rotate_mode:ident;
) => {{
retval.push(insn_single(
@ -808,7 +930,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -835,7 +957,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -846,6 +968,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
$encoding:literal;
$overflow_behavior:ident;
$shift_rotate_mode:ident;
) => {{
retval.push(insn_single(
@ -873,7 +996,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -903,7 +1026,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true),
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -941,7 +1064,11 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), true),
shift_imm(
Some($amount),
true,
ShiftAmountOverflowBehavior.WrapToUInt6(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -971,7 +1098,11 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), true),
shift_imm(
Some($amount),
true,
ShiftAmountOverflowBehavior.WrapToUInt6(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
@ -981,11 +1112,13 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
shift_left! {
"slw" 3, 4, 5;
0x7c832830;
WrapToUInt6ZeroIfGE32;
FunnelShift2x32Bit;
}
shift_right_unsigned! {
"srw" 3, 4, 5;
0x7c832c30;
WrapToUInt6ZeroIfGE32;
FunnelShift2x32Bit;
}
shift_right_signed_imm! {
@ -1011,16 +1144,19 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
shift_right_signed! {
"sraw" 3, 4, 5;
0x7c832e30;
WrapToUInt6;
SignExt32To64BitThenShift;
}
shift_left! {
"sld" 3, 4, 5;
0x7c832836;
WrapToUInt7ZeroIfGE64;
FunnelShift2x64Bit;
}
shift_right_unsigned! {
"srd" 3, 4, 5;
0x7c832c36;
WrapToUInt7ZeroIfGE64;
FunnelShift2x64Bit;
}
shift_right_signed_imm! {
@ -1056,6 +1192,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
shift_right_signed! {
"srad" 3, 4, 5;
0x7c832e34;
WrapToUInt7;
ShiftSigned64;
}
macro_rules! extswsli {
@ -1082,7 +1219,11 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), false),
shift_imm(
Some($amount),
false,
ShiftAmountOverflowBehavior.WrapToUInt6(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.SignExt32To64BitThenShift(),
),
@ -1109,7 +1250,11 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
],
shift_imm(Some($amount), false),
shift_imm(
Some($amount),
false,
ShiftAmountOverflowBehavior.WrapToUInt6(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.SignExt32To64BitThenShift(),
),