forked from libre-chip/cpu
redo ShiftRotateMOp and write actual operation definition in doc comment
This commit is contained in:
parent
a3898e8c13
commit
7481d079d5
12 changed files with 18082 additions and 13351 deletions
|
|
@ -1953,10 +1953,18 @@ impl DecodeState<'_> {
|
||||||
ShiftRotateMOpImm {
|
ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: HdlNone(),
|
shift_rotate_amount: HdlNone(),
|
||||||
shift_rotate_right: false,
|
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,
|
dest_logic_op,
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
if is_32bit {
|
||||||
|
OutputIntegerMode.DupLow32()
|
||||||
|
} else {
|
||||||
|
OutputIntegerMode.Full64()
|
||||||
|
},
|
||||||
if is_32bit {
|
if is_32bit {
|
||||||
ShiftRotateMode.FunnelShift2x32Bit()
|
ShiftRotateMode.FunnelShift2x32Bit()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2004,10 +2012,14 @@ impl DecodeState<'_> {
|
||||||
ShiftRotateMOpImm {
|
ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: HdlSome(rotate_amount),
|
shift_rotate_amount: HdlSome(rotate_amount),
|
||||||
shift_rotate_right: false,
|
shift_rotate_right: false,
|
||||||
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
|
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToUInt6(),
|
||||||
dest_logic_op,
|
dest_logic_op,
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
if is_32bit {
|
||||||
|
OutputIntegerMode.DupLow32()
|
||||||
|
} else {
|
||||||
|
OutputIntegerMode.Full64()
|
||||||
|
},
|
||||||
if is_32bit {
|
if is_32bit {
|
||||||
ShiftRotateMode.FunnelShift2x32Bit()
|
ShiftRotateMode.FunnelShift2x32Bit()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2156,7 +2168,7 @@ impl DecodeState<'_> {
|
||||||
shift_rotate_amount: HdlSome(sh.cast_to_static::<UInt<_>>()),
|
shift_rotate_amount: HdlSome(sh.cast_to_static::<UInt<_>>()),
|
||||||
shift_rotate_right: true,
|
shift_rotate_right: true,
|
||||||
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
||||||
.WrapToWidth(),
|
.WrapToUInt6(),
|
||||||
dest_logic_op: HdlNone(),
|
dest_logic_op: HdlNone(),
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
|
|
@ -2186,7 +2198,7 @@ impl DecodeState<'_> {
|
||||||
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
|
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
|
||||||
shift_rotate_right: true,
|
shift_rotate_right: true,
|
||||||
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
||||||
.WrapToWidth(),
|
.WrapToUInt6(),
|
||||||
dest_logic_op: HdlNone(),
|
dest_logic_op: HdlNone(),
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
|
|
@ -2228,8 +2240,19 @@ impl DecodeState<'_> {
|
||||||
ShiftRotateMOpImm {
|
ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: HdlNone(),
|
shift_rotate_amount: HdlNone(),
|
||||||
shift_rotate_right: is_right_shift,
|
shift_rotate_right: is_right_shift,
|
||||||
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
shift_amount_overflow_behavior: if is_signed && is_right_shift {
|
||||||
.WrapToTwiceWidth(),
|
if is_32bit {
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt6()
|
||||||
|
} else {
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt7()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if is_32bit {
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt6ZeroIfGE32()
|
||||||
|
} else {
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt7ZeroIfGE64()
|
||||||
|
}
|
||||||
|
},
|
||||||
dest_logic_op: HdlNone(),
|
dest_logic_op: HdlNone(),
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
|
|
@ -2266,7 +2289,7 @@ impl DecodeState<'_> {
|
||||||
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
|
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
|
||||||
shift_rotate_right: false,
|
shift_rotate_right: false,
|
||||||
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior
|
||||||
.WrapToWidth(),
|
.WrapToUInt6(),
|
||||||
dest_logic_op: HdlNone(),
|
dest_logic_op: HdlNone(),
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
|
|
|
||||||
|
|
@ -2157,21 +2157,21 @@ impl<DestReg: Type, SrcReg: Type> LogicalMOp<DestReg, SrcReg, ConstUsize<1>> {
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub enum ShiftRotateMode {
|
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,
|
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,
|
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,
|
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,
|
FunnelShift2x64Bit,
|
||||||
/// `shift(src0 as i8 as i64, shift_rotate_amount.unwrap_or(src2))`
|
/// `shift(src0 as i8 as i64, shift_rotate_amount)`
|
||||||
SignExt8To64BitThenShift,
|
SignExt8To64BitThenShift,
|
||||||
/// `shift(src0 as i16 as i64, shift_rotate_amount.unwrap_or(src2))`
|
/// `shift(src0 as i16 as i64, shift_rotate_amount)`
|
||||||
SignExt16To64BitThenShift,
|
SignExt16To64BitThenShift,
|
||||||
/// `shift(src0 as i32 as i64, shift_rotate_amount.unwrap_or(src2))`
|
/// `shift(src0 as i32 as i64, shift_rotate_amount)`
|
||||||
SignExt32To64BitThenShift,
|
SignExt32To64BitThenShift,
|
||||||
/// `shift(src0 as i64, shift_rotate_amount.unwrap_or(src2))`
|
/// `shift(src0 as i64, shift_rotate_amount)`
|
||||||
ShiftSigned64,
|
ShiftSigned64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2275,10 +2275,22 @@ impl ShiftRotateDestLogicOp {
|
||||||
|
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub enum ShiftAmountOverflowBehavior {
|
pub enum ShiftAmountOverflowBehavior {
|
||||||
/// wrap shift amount to width specified by [`ShiftRotateMode`]
|
/// the shift amount is wrapped to fit in [`UInt<3>`], this is the same as `shift_rotate_amount % 8`
|
||||||
WrapToWidth,
|
WrapToUInt3,
|
||||||
/// wrap shift amount to twice the width specified by [`ShiftRotateMode`]
|
/// the shift amount is wrapped to fit in [`UInt<4>`], this is the same as `shift_rotate_amount % 0x10`
|
||||||
WrapToTwiceWidth,
|
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`].
|
/// immediate values for [`ShiftRotateMOp`].
|
||||||
|
|
@ -2349,6 +2361,31 @@ common_mop_struct! {
|
||||||
})]
|
})]
|
||||||
#[mapped(<NewDestReg, NewSrcReg> ShiftRotateMOp<NewDestReg, NewSrcReg>)]
|
#[mapped(<NewDestReg, NewSrcReg> ShiftRotateMOp<NewDestReg, NewSrcReg>)]
|
||||||
#[hdl(cmp_eq, custom_debug(sim))]
|
#[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> {
|
pub struct ShiftRotateMOp<DestReg: Type, SrcReg: Type> {
|
||||||
#[common]
|
#[common]
|
||||||
pub alu_common: AluCommonMOp<DestReg, SrcReg, ConstUsize<3>, ShiftRotateMOpImm>,
|
pub alu_common: AluCommonMOp<DestReg, SrcReg, ConstUsize<3>, ShiftRotateMOpImm>,
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ use crate::{
|
||||||
instruction::{
|
instruction::{
|
||||||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
||||||
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
||||||
Lut4, OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
|
Lut4, OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftAmountOverflowBehavior,
|
||||||
ShiftRotateMOpImm, ShiftRotateMode,
|
ShiftRotateDestLogicOp, ShiftRotateMOp, ShiftRotateMOpImm, ShiftRotateMode,
|
||||||
},
|
},
|
||||||
next_pc::CallStackOp,
|
next_pc::CallStackOp,
|
||||||
register::{
|
register::{
|
||||||
|
|
@ -21,7 +21,11 @@ use crate::{
|
||||||
unit::{DynUnit, DynUnitWrapper, UnitKind, UnitTrait},
|
unit::{DynUnit, DynUnitWrapper, UnitKind, UnitTrait},
|
||||||
};
|
};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
expr::CastToImpl, int::IntType, intern::Interned, module::wire_with_loc, prelude::*,
|
expr::CastToImpl,
|
||||||
|
int::{BoolOrIntType, IntType},
|
||||||
|
intern::Interned,
|
||||||
|
module::wire_with_loc,
|
||||||
|
prelude::*,
|
||||||
ty::StaticType,
|
ty::StaticType,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, ops::RangeTo};
|
use std::{collections::HashMap, ops::RangeTo};
|
||||||
|
|
@ -385,70 +389,181 @@ fn logical<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl_module]
|
||||||
fn funnel_shift<W: Size, A: Size>(
|
fn right_shifter<I: KnownSize, O: KnownSize, A: KnownSize>() {
|
||||||
high: impl ToExpr<Type = UIntType<W>>,
|
|
||||||
low: impl ToExpr<Type = UIntType<W>>,
|
|
||||||
shift_right: impl ToExpr<Type = Bool>,
|
|
||||||
shift_amount: impl ToExpr<Type = UIntType<A>>,
|
|
||||||
) -> Expr<UIntType<W>> {
|
|
||||||
let high = high.to_expr();
|
|
||||||
let low = low.to_expr();
|
|
||||||
let shift_right = shift_right.to_expr();
|
|
||||||
let shift_amount = shift_amount.to_expr();
|
|
||||||
let int_ty = high.ty();
|
|
||||||
assert_eq!(int_ty, low.ty());
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_high = wire(int_ty);
|
let input: UIntType<I> = m.input();
|
||||||
connect(funnel_shift_high, high);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_low = wire(int_ty);
|
let shift_amount: UIntType<A> = m.input();
|
||||||
connect(funnel_shift_low, low);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_right = wire();
|
let signed: Bool = m.input();
|
||||||
connect(funnel_shift_right, shift_right);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_amount = wire(
|
let output: UIntType<O> = m.output();
|
||||||
UInt[shift_amount
|
#[hdl]
|
||||||
|
let shifted_out_any_one_bits: Bool = m.output();
|
||||||
|
#[hdl]
|
||||||
|
let last_shifted_out_bit: Bool = m.output();
|
||||||
|
|
||||||
|
connect(shifted_out_any_one_bits, false);
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
let shifted_in = wire(UInt[I::VALUE + 1]);
|
||||||
|
connect(shifted_in, input << 1);
|
||||||
|
|
||||||
|
let mut shifted = shifted_in;
|
||||||
|
|
||||||
|
for shift_amount_bit_index in 0..A::VALUE {
|
||||||
|
let shifted_in = shifted;
|
||||||
|
let shift_amount_step = 1 << shift_amount_bit_index;
|
||||||
|
let shifted_width = shifted_in
|
||||||
.ty()
|
.ty()
|
||||||
.width()
|
.width()
|
||||||
.min(UInt::range_usize(0..int_ty.width()).width())],
|
.saturating_sub(shift_amount_step)
|
||||||
);
|
.max(O::VALUE + 1);
|
||||||
connect_any(funnel_shift_amount, shift_amount);
|
shifted = wire_with_loc(
|
||||||
#[hdl]
|
&format!("shifted_{shift_amount_bit_index}"),
|
||||||
let funnel_shift_reverse_amount = wire(funnel_shift_amount.ty());
|
SourceLocation::caller(),
|
||||||
connect_any(
|
UInt[shifted_width],
|
||||||
funnel_shift_reverse_amount,
|
);
|
||||||
int_ty.width() - funnel_shift_amount,
|
|
||||||
);
|
|
||||||
#[hdl]
|
|
||||||
let funnel_shift_high_left_amount = wire(funnel_shift_amount.ty());
|
|
||||||
#[hdl]
|
|
||||||
let funnel_shift_low_right_amount = wire(funnel_shift_amount.ty());
|
|
||||||
#[hdl]
|
|
||||||
let funnel_shift_retval = wire(int_ty);
|
|
||||||
connect_any(
|
|
||||||
funnel_shift_retval,
|
|
||||||
(funnel_shift_high << funnel_shift_high_left_amount)
|
|
||||||
| (funnel_shift_low >> funnel_shift_low_right_amount),
|
|
||||||
);
|
|
||||||
#[hdl]
|
|
||||||
if funnel_shift_right {
|
|
||||||
connect(funnel_shift_high_left_amount, funnel_shift_reverse_amount);
|
|
||||||
connect(funnel_shift_low_right_amount, funnel_shift_amount);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if shift_amount.cmp_eq(0u8) {
|
if shift_amount[shift_amount_bit_index] {
|
||||||
connect(funnel_shift_retval, funnel_shift_low);
|
let shifted_in_signed = shifted_in.cast_to(shifted_in.ty().as_same_width_sint());
|
||||||
}
|
#[hdl]
|
||||||
} else {
|
if signed {
|
||||||
connect(funnel_shift_high_left_amount, funnel_shift_amount);
|
connect_any(
|
||||||
connect(funnel_shift_low_right_amount, funnel_shift_reverse_amount);
|
shifted,
|
||||||
#[hdl]
|
(shifted_in_signed >> shift_amount_step).cast_to(shifted.ty()),
|
||||||
if shift_amount.cmp_eq(0u8) {
|
);
|
||||||
connect(funnel_shift_retval, funnel_shift_high);
|
} else {
|
||||||
|
connect_any(shifted, shifted_in >> shift_amount_step);
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
|
if shifted_in[..shift_amount_step.min(shifted_in.ty().width())].any_one_bits() {
|
||||||
|
connect(shifted_out_any_one_bits, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
connect_any(shifted, shifted_in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
funnel_shift_retval
|
|
||||||
|
connect_any(output, shifted >> 1);
|
||||||
|
connect(last_shifted_out_bit, shifted[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[test]
|
||||||
|
fn test_right_shifter() {
|
||||||
|
let mut sim = Simulation::new(right_shifter::<
|
||||||
|
ConstUsize<128>,
|
||||||
|
ConstUsize<64>,
|
||||||
|
ConstUsize<8>,
|
||||||
|
>());
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
struct TestCase {
|
||||||
|
input: u128,
|
||||||
|
shift_amount: u8,
|
||||||
|
signed: bool,
|
||||||
|
output: u64,
|
||||||
|
shifted_out_any_one_bits: bool,
|
||||||
|
last_shifted_out_bit: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for TestCase {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let Self {
|
||||||
|
input,
|
||||||
|
shift_amount,
|
||||||
|
signed,
|
||||||
|
output,
|
||||||
|
shifted_out_any_one_bits,
|
||||||
|
last_shifted_out_bit,
|
||||||
|
} = self;
|
||||||
|
fn hex(v: impl std::fmt::LowerHex) -> impl std::fmt::Debug {
|
||||||
|
std::fmt::from_fn(move |f| write!(f, "{v:#x}"))
|
||||||
|
}
|
||||||
|
f.debug_struct("TestCase")
|
||||||
|
.field("input", &hex(input))
|
||||||
|
.field("shift_amount", shift_amount)
|
||||||
|
.field("signed", signed)
|
||||||
|
.field("output", &hex(output))
|
||||||
|
.field("shifted_out_any_one_bits", shifted_out_any_one_bits)
|
||||||
|
.field("last_shifted_out_bit", last_shifted_out_bit)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const TEST_CASES: &[TestCase] = &[
|
||||||
|
TestCase {
|
||||||
|
input: 0x0123_4567_89AB_CDEF,
|
||||||
|
shift_amount: 5,
|
||||||
|
signed: false,
|
||||||
|
output: 0x9_1A2B_3C4D_5E6F,
|
||||||
|
shifted_out_any_one_bits: true,
|
||||||
|
last_shifted_out_bit: false,
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
input: 0x8123_4567_89AB_CDEFu64 as i64 as u128,
|
||||||
|
shift_amount: 5,
|
||||||
|
signed: true,
|
||||||
|
output: 0xFC09_1A2B_3C4D_5E6F,
|
||||||
|
shifted_out_any_one_bits: true,
|
||||||
|
last_shifted_out_bit: false,
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
input: 0x0123_4567_89AB_CDEF,
|
||||||
|
shift_amount: 0,
|
||||||
|
signed: false,
|
||||||
|
output: 0x0123_4567_89AB_CDEF,
|
||||||
|
shifted_out_any_one_bits: false,
|
||||||
|
last_shifted_out_bit: false,
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
input: 0x0123_4567_89AB_CDEF,
|
||||||
|
shift_amount: 64,
|
||||||
|
signed: false,
|
||||||
|
output: 0,
|
||||||
|
shifted_out_any_one_bits: true,
|
||||||
|
last_shifted_out_bit: false,
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
input: 0x8123_4567_89AB_CDEFu64 as i64 as u128,
|
||||||
|
shift_amount: 128,
|
||||||
|
signed: false,
|
||||||
|
output: 0,
|
||||||
|
shifted_out_any_one_bits: true,
|
||||||
|
last_shifted_out_bit: false,
|
||||||
|
},
|
||||||
|
TestCase {
|
||||||
|
input: 0x8123_4567_89AB_CDEFu64 as i64 as u128,
|
||||||
|
shift_amount: 128,
|
||||||
|
signed: true,
|
||||||
|
output: !0,
|
||||||
|
shifted_out_any_one_bits: true,
|
||||||
|
last_shifted_out_bit: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
for expected in TEST_CASES {
|
||||||
|
let TestCase {
|
||||||
|
input,
|
||||||
|
shift_amount,
|
||||||
|
signed,
|
||||||
|
output: _,
|
||||||
|
shifted_out_any_one_bits: _,
|
||||||
|
last_shifted_out_bit: _,
|
||||||
|
} = *expected;
|
||||||
|
sim.write(sim.io().input, input);
|
||||||
|
sim.write(sim.io().shift_amount, shift_amount);
|
||||||
|
sim.write(sim.io().signed, signed);
|
||||||
|
sim.advance_time(SimDuration::from_micros(1));
|
||||||
|
let output = TestCase {
|
||||||
|
input: sim.read(sim.io().input).as_int(),
|
||||||
|
shift_amount: sim.read(sim.io().shift_amount).as_int(),
|
||||||
|
signed: sim.read_bool(sim.io().signed),
|
||||||
|
output: sim.read(sim.io().output).as_int(),
|
||||||
|
shifted_out_any_one_bits: sim.read_bool(sim.io().shifted_out_any_one_bits),
|
||||||
|
last_shifted_out_bit: sim.read_bool(sim.io().last_shifted_out_bit),
|
||||||
|
};
|
||||||
|
assert_eq!(output, *expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
|
|
@ -474,88 +589,123 @@ fn shift_rotate<C: Type + PhantomConstCpuConfig>(config: C) {
|
||||||
} = alu_common;
|
} = alu_common;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let ShiftRotateMOpImm {
|
let ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: shift_rotate_amount_opt,
|
shift_rotate_amount: imm_shift_rotate_amount,
|
||||||
shift_rotate_right,
|
shift_rotate_right,
|
||||||
shift_amount_overflow_behavior,
|
shift_amount_overflow_behavior,
|
||||||
dest_logic_op,
|
dest_logic_op,
|
||||||
} = common.imm;
|
} = common.imm;
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let shift_rotate_amount = wire();
|
let shift_rotate_amount: UInt<8> = wire();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
match shift_rotate_amount_opt {
|
let shifted_output_is_zero = wire();
|
||||||
HdlSome(shift_rotate_amount_opt) => connect(
|
#[hdl]
|
||||||
shift_rotate_amount,
|
match imm_shift_rotate_amount {
|
||||||
shift_rotate_amount_opt.cast_to_static::<UInt<64>>(),
|
HdlSome(v) => {
|
||||||
),
|
connect(shift_rotate_amount, v.cast_to_static());
|
||||||
HdlNone => connect(shift_rotate_amount, src_values[2].int_fp),
|
connect(shifted_output_is_zero, false);
|
||||||
|
}
|
||||||
|
HdlNone => {
|
||||||
|
connect(shifted_output_is_zero, false);
|
||||||
|
let do_overflow_behavior = |width: usize, zero_if_ge_half| {
|
||||||
|
assert!(width <= shift_rotate_amount.ty().width());
|
||||||
|
connect(
|
||||||
|
shift_rotate_amount,
|
||||||
|
src_values[2].int_fp.cast_to(UInt[width]).cast_to_static(),
|
||||||
|
);
|
||||||
|
if zero_if_ge_half {
|
||||||
|
connect(shifted_output_is_zero, shift_rotate_amount[width - 1]);
|
||||||
|
} else {
|
||||||
|
connect(shifted_output_is_zero, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#[hdl]
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_2x64_high: UInt<64> = wire();
|
let right_shifter = instance(right_shifter());
|
||||||
|
connect(right_shifter.shift_amount, shift_rotate_amount);
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_2x64_low: UInt<64> = wire();
|
let input_is_negative: Bool = wire();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_2x64_amount = wire(UInt::range_usize(0..funnel_shift_2x64_high.ty().width()));
|
let signed_input_is_negative: Bool = wire();
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let funnel_shift_2x64_output: UInt<64> = wire();
|
let shifted: UInt<64> = wire();
|
||||||
connect(
|
let connect_for_funnel_shift = |width: usize| {
|
||||||
funnel_shift_2x64_output,
|
let high = src_values[0].int_fp.cast_to(UInt[width]);
|
||||||
funnel_shift(
|
let low = src_values[1].int_fp.cast_to(UInt[width]);
|
||||||
funnel_shift_2x64_high,
|
let input = low | (high << width);
|
||||||
funnel_shift_2x64_low,
|
connect(right_shifter.signed, false);
|
||||||
shift_rotate_right,
|
connect(input_is_negative, false);
|
||||||
funnel_shift_2x64_amount,
|
connect(signed_input_is_negative, low[width - 1]);
|
||||||
),
|
|
||||||
);
|
|
||||||
#[hdl]
|
|
||||||
let shifted_rotated: UInt<64> = wire();
|
|
||||||
let excess_bits_for_2x64 = |width| funnel_shift_2x64_low.ty().width() - width;
|
|
||||||
let connect_for_funnel_shift = |width| {
|
|
||||||
// TODO: handle large shift_rotate_amount >= width
|
|
||||||
connect(
|
|
||||||
funnel_shift_2x64_high,
|
|
||||||
src_values[0]
|
|
||||||
.int_fp
|
|
||||||
.cast_to(UInt[width])
|
|
||||||
.cast_to_static::<UInt<64>>(),
|
|
||||||
);
|
|
||||||
connect_any(
|
|
||||||
funnel_shift_2x64_low,
|
|
||||||
src_values[1].int_fp.cast_to(UInt[width]) << excess_bits_for_2x64(width),
|
|
||||||
);
|
|
||||||
connect_any(funnel_shift_2x64_amount, shift_rotate_amount);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if shift_rotate_right {
|
if shift_rotate_right {
|
||||||
connect_any(
|
connect(right_shifter.input, input.cast_to_static::<UInt<128>>());
|
||||||
shifted_rotated,
|
connect(shifted, right_shifter.output);
|
||||||
funnel_shift_2x64_output >> excess_bits_for_2x64(8),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
connect(
|
// properly gets the high half of shifting 2 * width bits left
|
||||||
shifted_rotated,
|
let input_array_ty = Array[Bool][width * 2];
|
||||||
funnel_shift_2x64_output
|
let input_bits = input
|
||||||
.cast_to(UInt[width])
|
.cast_bits_to(input_array_ty)
|
||||||
.cast_to_static::<UInt<64>>(),
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
connect_any(right_shifter.input, input_bits.cast_to_bits());
|
||||||
|
let output_bits = right_shifter
|
||||||
|
.output
|
||||||
|
.cast_to(UInt[width])
|
||||||
|
.cast_bits_to(Array[Bool][width])
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
connect_any(
|
||||||
|
shifted,
|
||||||
|
output_bits.cast_to_bits().cast_to_static::<UInt<64>>(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let connect_for_sign_ext_then_shift = |width| {
|
let connect_for_sign_ext_then_shift = |width| {
|
||||||
// TODO: handle large shift_rotate_amount >= 64
|
let input = src_values[0].int_fp.cast_to(SInt[width]);
|
||||||
let input = src_values[0]
|
connect(right_shifter.signed, shift_rotate_right);
|
||||||
.int_fp
|
connect(input_is_negative, input.cmp_lt(0i8));
|
||||||
.cast_to(SInt[width])
|
connect(signed_input_is_negative, input_is_negative);
|
||||||
.cast_to_static::<SInt<64>>();
|
|
||||||
let input_sign_bit = input >> (input.ty().width() - 1);
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if shift_rotate_right {
|
if shift_rotate_right {
|
||||||
connect(funnel_shift_2x64_high, input_sign_bit.cast_to_static());
|
// sign-extend to full 128 bits
|
||||||
connect(funnel_shift_2x64_low, input.cast_to_static());
|
connect(right_shifter.input, input.cast_to_static::<UInt<128>>());
|
||||||
connect_any(funnel_shift_2x64_amount, shift_rotate_amount);
|
connect(shifted, right_shifter.output);
|
||||||
connect(shifted_rotated, funnel_shift_2x64_output);
|
|
||||||
} else {
|
} else {
|
||||||
connect(funnel_shift_2x64_high, input.cast_to_static());
|
// shift the input 64 bits left with a 64-bit result
|
||||||
connect(funnel_shift_2x64_low, 0u64);
|
let input_bits = input
|
||||||
connect_any(funnel_shift_2x64_amount, shift_rotate_amount);
|
.cast_to_static::<UInt<64>>()
|
||||||
connect(shifted_rotated, funnel_shift_2x64_output);
|
.cast_bits_to(Array[Bool][ConstUsize::<64>])
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
connect(
|
||||||
|
right_shifter.input,
|
||||||
|
input_bits.cast_to_bits().cast_to_static::<UInt<128>>(),
|
||||||
|
);
|
||||||
|
let output_bits = right_shifter
|
||||||
|
.output
|
||||||
|
.cast_to_static::<UInt<64>>()
|
||||||
|
.cast_bits_to(Array[Bool][ConstUsize::<64>])
|
||||||
|
.into_iter()
|
||||||
|
.rev()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
connect_any(shifted, output_bits.cast_to_bits());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -570,42 +720,112 @@ fn shift_rotate<C: Type + PhantomConstCpuConfig>(config: C) {
|
||||||
ShiftRotateMode::ShiftSigned64 => connect_for_sign_ext_then_shift(64),
|
ShiftRotateMode::ShiftSigned64 => connect_for_sign_ext_then_shift(64),
|
||||||
}
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let masked: UInt<64> = wire();
|
if shifted_output_is_zero {
|
||||||
|
connect(shifted, 0u64);
|
||||||
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
if let HdlSome(dest_logic_op) = dest_logic_op {
|
let extended: UInt<64> = wire();
|
||||||
connect(
|
#[hdl]
|
||||||
masked,
|
let x86_sf = wire();
|
||||||
ShiftRotateDestLogicOp::operation(dest_logic_op, shifted_rotated, src_values[2].int_fp),
|
let do_mode = |width: usize, signed| {
|
||||||
);
|
connect(x86_sf, shifted[width - 1]);
|
||||||
} else {
|
if signed {
|
||||||
connect(masked, shifted_rotated);
|
connect(
|
||||||
}
|
extended,
|
||||||
let int_fp = output.int_fp;
|
shifted.cast_to(SInt[width]).cast_to_static::<UInt<64>>(),
|
||||||
fn connect_int_fp_cast<T: IntType + StaticType>(int_fp: Expr<UInt<64>>, masked: Expr<UInt<64>>)
|
);
|
||||||
where
|
} else {
|
||||||
UInt<64>: CastToImpl<T>,
|
connect(
|
||||||
T: CastToImpl<UInt<64>>,
|
extended,
|
||||||
{
|
shifted.cast_to(UInt[width]).cast_to_static::<UInt<64>>(),
|
||||||
connect(
|
);
|
||||||
int_fp,
|
}
|
||||||
masked.cast_to_static::<T>().cast_to_static::<UInt<64>>(),
|
};
|
||||||
)
|
|
||||||
}
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
match output_integer_mode {
|
match output_integer_mode {
|
||||||
OutputIntegerMode::Full64 => connect(int_fp, masked),
|
OutputIntegerMode::Full64 => do_mode(64, false),
|
||||||
OutputIntegerMode::DupLow32 => connect_any(
|
OutputIntegerMode::DupLow32 => {
|
||||||
int_fp,
|
let shifted = shifted.cast_to_static::<UInt<32>>();
|
||||||
masked.cast_to_static::<UInt<32>>() | (masked.cast_to_static::<UInt<32>>() << 32),
|
connect_any(extended, shifted | (shifted << 32));
|
||||||
),
|
connect(x86_sf, shifted[31]);
|
||||||
OutputIntegerMode::ZeroExt32 => connect_int_fp_cast::<UInt<32>>(int_fp, masked),
|
}
|
||||||
OutputIntegerMode::SignExt32 => connect_int_fp_cast::<SInt<32>>(int_fp, masked),
|
OutputIntegerMode::ZeroExt32 => do_mode(32, false),
|
||||||
OutputIntegerMode::ZeroExt16 => connect_int_fp_cast::<UInt<16>>(int_fp, masked),
|
OutputIntegerMode::SignExt32 => do_mode(32, true),
|
||||||
OutputIntegerMode::SignExt16 => connect_int_fp_cast::<SInt<16>>(int_fp, masked),
|
OutputIntegerMode::ZeroExt16 => do_mode(16, false),
|
||||||
OutputIntegerMode::ZeroExt8 => connect_int_fp_cast::<UInt<8>>(int_fp, masked),
|
OutputIntegerMode::SignExt16 => do_mode(16, true),
|
||||||
OutputIntegerMode::SignExt8 => connect_int_fp_cast::<SInt<8>>(int_fp, masked),
|
OutputIntegerMode::ZeroExt8 => do_mode(8, false),
|
||||||
|
OutputIntegerMode::SignExt8 => do_mode(8, true),
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
|
if let HdlSome(o) = dest_logic_op {
|
||||||
|
connect(
|
||||||
|
output.int_fp,
|
||||||
|
ShiftRotateDestLogicOp::operation(o, extended, src_values[2].int_fp),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
connect(output.int_fp, extended);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
let power_isa_flags = wire();
|
||||||
|
connect(power_isa_flags, PRegFlags::zeroed());
|
||||||
|
{
|
||||||
|
let PRegFlagsPowerISAView {
|
||||||
|
unused: _,
|
||||||
|
xer_ca,
|
||||||
|
xer_ca32,
|
||||||
|
xer_ov: _,
|
||||||
|
xer_ov32: _,
|
||||||
|
cr_lt,
|
||||||
|
cr_gt,
|
||||||
|
cr_eq,
|
||||||
|
so,
|
||||||
|
} = PRegFlags::view::<PRegFlagsPowerISA>(power_isa_flags);
|
||||||
|
|
||||||
|
connect(
|
||||||
|
xer_ca,
|
||||||
|
input_is_negative & right_shifter.shifted_out_any_one_bits,
|
||||||
|
);
|
||||||
|
connect(xer_ca32, xer_ca);
|
||||||
|
|
||||||
|
let _ = so; // TODO: need to set from the global SO
|
||||||
|
connect(cr_lt, output.int_fp[63]);
|
||||||
|
connect(cr_eq, output.int_fp.cmp_eq(0u64));
|
||||||
|
connect(cr_gt, !(cr_lt | cr_eq));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
let x86_flags = wire();
|
||||||
|
connect(x86_flags, PRegFlags::zeroed());
|
||||||
|
{
|
||||||
|
// TODO: retain previous flags if shift_rotate_amount is 0
|
||||||
|
let PRegFlagsX86View {
|
||||||
|
unused: _,
|
||||||
|
cf,
|
||||||
|
zf,
|
||||||
|
sf,
|
||||||
|
of,
|
||||||
|
af: _, // undefined when shift_rotate_amount > 0
|
||||||
|
pf,
|
||||||
|
df: _, // not written by this instruction
|
||||||
|
} = PRegFlags::view::<PRegFlagsX86>(power_isa_flags);
|
||||||
|
connect(cf, right_shifter.last_shifted_out_bit);
|
||||||
|
connect(zf, output.int_fp.cmp_eq(0u64));
|
||||||
|
connect(sf, x86_sf);
|
||||||
|
#[hdl]
|
||||||
|
if shift_rotate_right {
|
||||||
|
connect(of, sf ^ signed_input_is_negative);
|
||||||
|
} else {
|
||||||
|
connect(of, sf ^ cf);
|
||||||
|
}
|
||||||
|
connect(pf, output.int_fp[..8].parity_even());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
match flags_mode {
|
||||||
|
FlagsMode::PowerISA(_) => connect(output.flags, power_isa_flags),
|
||||||
|
FlagsMode::X86(_) => connect(output.flags, x86_flags),
|
||||||
}
|
}
|
||||||
connect(output.flags, PRegFlags::zeroed()); // TODO: compute flags
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
1334
crates/cpu/tests/expected/rename_execute_retire_head_n1.vcd
generated
1334
crates/cpu/tests/expected/rename_execute_retire_head_n1.vcd
generated
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
|
|
@ -719,7 +719,7 @@ impl InsnsBuilder {
|
||||||
ShiftRotateMOpImm {
|
ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: HdlSome(shift.cast_to_static::<UInt<_>>()),
|
shift_rotate_amount: HdlSome(shift.cast_to_static::<UInt<_>>()),
|
||||||
shift_rotate_right: false,
|
shift_rotate_right: false,
|
||||||
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToWidth(),
|
shift_amount_overflow_behavior: ShiftAmountOverflowBehavior.WrapToUInt6(),
|
||||||
dest_logic_op: if rotated_output_len == 0 {
|
dest_logic_op: if rotated_output_len == 0 {
|
||||||
// rotated_output_len wrapped around to 64
|
// rotated_output_len wrapped around to 64
|
||||||
HdlNone()
|
HdlNone()
|
||||||
|
|
@ -735,7 +735,7 @@ impl InsnsBuilder {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.DupLow32(),
|
||||||
ShiftRotateMode.FunnelShift2x32Bit(),
|
ShiftRotateMode.FunnelShift2x32Bit(),
|
||||||
)],
|
)],
|
||||||
));
|
));
|
||||||
|
|
@ -1838,157 +1838,103 @@ trait MockExecutionStateTrait: Default {
|
||||||
shift_amount_overflow_behavior,
|
shift_amount_overflow_behavior,
|
||||||
dest_logic_op,
|
dest_logic_op,
|
||||||
} = imm;
|
} = imm;
|
||||||
let shift_rotate_amount = #[hdl(sim)]
|
let (shift_rotate_amount, shifted_output_is_zero) = #[hdl(sim)]
|
||||||
match shift_rotate_amount {
|
match shift_rotate_amount {
|
||||||
HdlSome(shift_rotate_amount) => {
|
HdlSome(shift_rotate_amount) => (
|
||||||
shift_rotate_amount.cast_to_static::<UInt<64>>().as_int()
|
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 {
|
match mode {
|
||||||
ShiftRotateMode::FunnelShift2x8Bit => {
|
ShiftRotateMode::FunnelShift2x8Bit => funnel_shift(8),
|
||||||
if shift_rotate_amount >= 8 {
|
ShiftRotateMode::FunnelShift2x16Bit => funnel_shift(16),
|
||||||
todo!("large shift_rotate_amount={shift_rotate_amount}");
|
ShiftRotateMode::FunnelShift2x32Bit => funnel_shift(32),
|
||||||
}
|
ShiftRotateMode::FunnelShift2x64Bit => funnel_shift(64),
|
||||||
if **shift_rotate_right {
|
ShiftRotateMode::SignExt8To64BitThenShift => sign_ext_shift(8),
|
||||||
FunnelShift::funnel_shr(
|
ShiftRotateMode::SignExt16To64BitThenShift => sign_ext_shift(16),
|
||||||
src_values[0].inner().int_fp.as_int() as u8,
|
ShiftRotateMode::SignExt32To64BitThenShift => sign_ext_shift(32),
|
||||||
src_values[1].inner().int_fp.as_int() as u8,
|
ShiftRotateMode::ShiftSigned64 => sign_ext_shift(64),
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
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 {
|
if let HdlSome(dest_logic_op) = dest_logic_op {
|
||||||
ShiftRotateDestLogicOp::operation_sim(
|
ShiftRotateDestLogicOp::operation_sim(
|
||||||
dest_logic_op,
|
dest_logic_op,
|
||||||
shifted_rotated,
|
extended,
|
||||||
&src_values[2].inner().int_fp,
|
&src_values[2].inner().int_fp,
|
||||||
)
|
)
|
||||||
.as_int()
|
.as_int()
|
||||||
} else {
|
} else {
|
||||||
shifted_rotated
|
extended
|
||||||
};
|
|
||||||
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,
|
|
||||||
};
|
};
|
||||||
let retval = #[hdl(sim)]
|
let retval = #[hdl(sim)]
|
||||||
PRegValue {
|
PRegValue {
|
||||||
int_fp,
|
int_fp: output,
|
||||||
flags: PRegFlags::zeroed_sim(), // TODO: compute flags
|
flags: PRegFlags::zeroed_sim(), // TODO: compute flags
|
||||||
};
|
};
|
||||||
retval.into_trace_as_string()
|
retval.into_trace_as_string()
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -3,9 +3,10 @@
|
||||||
|
|
||||||
use crate::test_cases::TestCase;
|
use crate::test_cases::TestCase;
|
||||||
use cpu::{
|
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};
|
use std::{fmt::Write as _, io::Write, process::Command};
|
||||||
|
|
||||||
mod test_cases;
|
mod test_cases;
|
||||||
|
|
@ -127,22 +128,10 @@ fn test_decode_insn() {
|
||||||
let _n = SourceLocation::normalize_files_for_tests();
|
let _n = SourceLocation::normalize_files_for_tests();
|
||||||
let m = decode_one_insn();
|
let m = decode_one_insn();
|
||||||
let mut sim = Simulation::new(m);
|
let mut sim = Simulation::new(m);
|
||||||
let writer = RcWriter::default();
|
let _checked_vcd_output = checked_vcd_output!(
|
||||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
&mut sim,
|
||||||
struct DumpVcdOnDrop {
|
"tests/simple_power_isa_decoder/expected/decode_one_insn.vcd",
|
||||||
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),
|
|
||||||
};
|
|
||||||
for test_case @ TestCase {
|
for test_case @ TestCase {
|
||||||
mnemonic: _,
|
mnemonic: _,
|
||||||
first_input,
|
first_input,
|
||||||
|
|
@ -185,11 +174,6 @@ fn test_decode_insn() {
|
||||||
"test_case={test_case:#?}\noutput={output}\nexpected={expected}"
|
"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]
|
#[hdl]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,11 @@ use cpu::instruction::{
|
||||||
use fayalite::prelude::*;
|
use fayalite::prelude::*;
|
||||||
|
|
||||||
#[hdl]
|
#[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]
|
#[hdl]
|
||||||
ShiftRotateMOpImm {
|
ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: if let Some(amount) = amount {
|
shift_rotate_amount: if let Some(amount) = amount {
|
||||||
|
|
@ -18,11 +22,7 @@ fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
|
||||||
HdlNone()
|
HdlNone()
|
||||||
},
|
},
|
||||||
shift_rotate_right: shift_right,
|
shift_rotate_right: shift_right,
|
||||||
shift_amount_overflow_behavior: if amount.is_some() {
|
shift_amount_overflow_behavior: overflow_behavior,
|
||||||
ShiftAmountOverflowBehavior.WrapToWidth()
|
|
||||||
} else {
|
|
||||||
ShiftAmountOverflowBehavior.WrapToTwiceWidth()
|
|
||||||
},
|
|
||||||
dest_logic_op: HdlNone(),
|
dest_logic_op: HdlNone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,6 +30,7 @@ fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn rotate_imm(
|
fn rotate_imm(
|
||||||
amount: Option<u8>,
|
amount: Option<u8>,
|
||||||
|
overflow_behavior: Expr<ShiftAmountOverflowBehavior>,
|
||||||
rotated_output_start_and_len: Option<(u8, u8)>,
|
rotated_output_start_and_len: Option<(u8, u8)>,
|
||||||
fallback_is_src2: bool,
|
fallback_is_src2: bool,
|
||||||
) -> SimValue<ShiftRotateMOpImm> {
|
) -> SimValue<ShiftRotateMOpImm> {
|
||||||
|
|
@ -37,7 +38,7 @@ fn rotate_imm(
|
||||||
ShiftRotateMOpImm {
|
ShiftRotateMOpImm {
|
||||||
shift_rotate_amount: amount.map(|amount| amount.cast_to_static::<UInt<_>>()),
|
shift_rotate_amount: amount.map(|amount| amount.cast_to_static::<UInt<_>>()),
|
||||||
shift_rotate_right: false,
|
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)) =
|
dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) =
|
||||||
rotated_output_start_and_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;
|
$encoding:literal;
|
||||||
$rotated_output_start_and_len:expr;
|
$rotated_output_start_and_len:expr;
|
||||||
$fallback_is_src2:literal;
|
$fallback_is_src2:literal;
|
||||||
|
$output_integer_mode:ident;
|
||||||
$shift_rotate_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);
|
let src2 = rotate_imm_src2(&imm, $dest);
|
||||||
retval.push(insn_single(
|
retval.push(insn_single(
|
||||||
concat!(
|
concat!(
|
||||||
|
|
@ -106,7 +113,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
|
||||||
src2,
|
src2,
|
||||||
],
|
],
|
||||||
&imm,
|
&imm,
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.$output_integer_mode(),
|
||||||
ShiftRotateMode.$shift_rotate_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,
|
src2,
|
||||||
],
|
],
|
||||||
imm,
|
imm,
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.$output_integer_mode(),
|
||||||
ShiftRotateMode.$shift_rotate_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)*;
|
$mnemonic:literal $dest:literal, $src:literal, $amount:literal $(, $args:literal)*;
|
||||||
$encoding:literal;
|
$encoding:literal;
|
||||||
|
$overflow_behavior:ident;
|
||||||
$rotated_output_start_and_len:expr;
|
$rotated_output_start_and_len:expr;
|
||||||
|
$output_integer_mode:ident;
|
||||||
$shift_rotate_mode:ident;
|
$shift_rotate_mode:ident;
|
||||||
) => {{
|
) => {{
|
||||||
retval.push(insn_single(
|
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($src),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
rotate_imm(None, $rotated_output_start_and_len, false),
|
rotate_imm(
|
||||||
OutputIntegerMode.Full64(),
|
None,
|
||||||
|
ShiftAmountOverflowBehavior.$overflow_behavior(),
|
||||||
|
$rotated_output_start_and_len,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
OutputIntegerMode.$output_integer_mode(),
|
||||||
ShiftRotateMode.$shift_rotate_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($src),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
rotate_imm(None, $rotated_output_start_and_len, false),
|
rotate_imm(
|
||||||
OutputIntegerMode.Full64(),
|
None,
|
||||||
|
ShiftAmountOverflowBehavior.$overflow_behavior(),
|
||||||
|
$rotated_output_start_and_len,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
OutputIntegerMode.$output_integer_mode(),
|
||||||
ShiftRotateMode.$shift_rotate_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;
|
0x54830000;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x54832800;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x5483f800;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x54832820;
|
||||||
Some((15, 17));
|
Some((15, 17));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x5483283e;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x54832ffe;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x54832fc0;
|
||||||
Some((31, 34));
|
Some((31, 34));
|
||||||
false;
|
false;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate! {
|
rotate! {
|
||||||
"rlwnm" 3, 4, 5, 0, 0;
|
"rlwnm" 3, 4, 5, 0, 0;
|
||||||
0x5c832800;
|
0x5c832800;
|
||||||
|
WrapToUInt5;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rlwnm" 3, 4, 5, 0, 16;
|
"rlwnm" 3, 4, 5, 0, 16;
|
||||||
0x5c832820;
|
0x5c832820;
|
||||||
|
WrapToUInt5;
|
||||||
Some((15, 17));
|
Some((15, 17));
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rlwnm" 3, 4, 5, 0, 31;
|
"rlwnm" 3, 4, 5, 0, 31;
|
||||||
0x5c83283e;
|
0x5c83283e;
|
||||||
|
WrapToUInt5;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rlwnm" 3, 4, 5, 31, 31;
|
"rlwnm" 3, 4, 5, 31, 31;
|
||||||
0x5c832ffe;
|
0x5c832ffe;
|
||||||
|
WrapToUInt5;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rlwnm" 3, 4, 5, 31, 0;
|
"rlwnm" 3, 4, 5, 31, 0;
|
||||||
0x5c832fc0;
|
0x5c832fc0;
|
||||||
|
WrapToUInt5;
|
||||||
Some((31, 34));
|
Some((31, 34));
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,6 +322,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
|
||||||
0x50830000;
|
0x50830000;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x50832800;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x5083f800;
|
||||||
Some((31, 1));
|
Some((31, 1));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x50832820;
|
||||||
Some((15, 17));
|
Some((15, 17));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x5083283e;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x50832ffe;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x50832fc0;
|
||||||
Some((31, 34));
|
Some((31, 34));
|
||||||
true;
|
true;
|
||||||
|
DupLow32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,6 +379,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
|
||||||
0x78830000;
|
0x78830000;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832800;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78838000;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883f800;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78830002;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883f802;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832940;
|
||||||
Some((0, 59));
|
Some((0, 59));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832c00;
|
||||||
Some((0, 48));
|
Some((0, 48));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832fc0;
|
||||||
Some((0, 33));
|
Some((0, 33));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832820;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832fe0;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -414,6 +468,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
|
||||||
0x788307e4;
|
0x788307e4;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832fe4;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788387e4;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883ffe4;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307e6;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883ffe6;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832804;
|
||||||
Some((63, 1));
|
Some((63, 1));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832944;
|
||||||
Some((58, 6));
|
Some((58, 6));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832c04;
|
||||||
Some((47, 17));
|
Some((47, 17));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832fc4;
|
||||||
Some((32, 32));
|
Some((32, 32));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832824;
|
||||||
Some((31, 33));
|
Some((31, 33));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78832fe4;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -499,6 +565,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
|
||||||
0x78830008;
|
0x78830008;
|
||||||
None;
|
None;
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78830408;
|
||||||
Some((0, 48));
|
Some((0, 48));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307c8;
|
||||||
Some((0, 33));
|
Some((0, 33));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x78830028;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307e8;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788387e8;
|
||||||
Some((16, 49));
|
Some((16, 49));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883ffe8;
|
||||||
Some((31, 34));
|
Some((31, 34));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307ea;
|
||||||
Some((32, 33));
|
Some((32, 33));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883ffea;
|
||||||
Some((63, 2));
|
Some((63, 2));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883f82a;
|
||||||
Some((63, 33));
|
Some((63, 33));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883f80a;
|
||||||
Some((63, 1));
|
Some((63, 1));
|
||||||
false;
|
false;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcl" 3, 4, 5, 0;
|
"rldcl" 3, 4, 5, 0;
|
||||||
0x78832810;
|
0x78832810;
|
||||||
|
WrapToUInt6;
|
||||||
None;
|
None;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcl" 3, 4, 5, 5;
|
"rldcl" 3, 4, 5, 5;
|
||||||
0x78832950;
|
0x78832950;
|
||||||
|
WrapToUInt6;
|
||||||
Some((0, 59));
|
Some((0, 59));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcl" 3, 4, 5, 16;
|
"rldcl" 3, 4, 5, 16;
|
||||||
0x78832c10;
|
0x78832c10;
|
||||||
|
WrapToUInt6;
|
||||||
Some((0, 48));
|
Some((0, 48));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcl" 3, 4, 5, 31;
|
"rldcl" 3, 4, 5, 31;
|
||||||
0x78832fd0;
|
0x78832fd0;
|
||||||
|
WrapToUInt6;
|
||||||
Some((0, 33));
|
Some((0, 33));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcl" 3, 4, 5, 32;
|
"rldcl" 3, 4, 5, 32;
|
||||||
0x78832830;
|
0x78832830;
|
||||||
|
WrapToUInt6;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcl" 3, 4, 5, 63;
|
"rldcl" 3, 4, 5, 63;
|
||||||
0x78832ff0;
|
0x78832ff0;
|
||||||
|
WrapToUInt6;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcr" 3, 4, 5, 0;
|
"rldcr" 3, 4, 5, 0;
|
||||||
0x78832812;
|
0x78832812;
|
||||||
|
WrapToUInt6;
|
||||||
Some((63, 1));
|
Some((63, 1));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcr" 3, 4, 5, 5;
|
"rldcr" 3, 4, 5, 5;
|
||||||
0x78832952;
|
0x78832952;
|
||||||
|
WrapToUInt6;
|
||||||
Some((58, 6));
|
Some((58, 6));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcr" 3, 4, 5, 16;
|
"rldcr" 3, 4, 5, 16;
|
||||||
0x78832c12;
|
0x78832c12;
|
||||||
|
WrapToUInt6;
|
||||||
Some((47, 17));
|
Some((47, 17));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcr" 3, 4, 5, 31;
|
"rldcr" 3, 4, 5, 31;
|
||||||
0x78832fd2;
|
0x78832fd2;
|
||||||
|
WrapToUInt6;
|
||||||
Some((32, 32));
|
Some((32, 32));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcr" 3, 4, 5, 32;
|
"rldcr" 3, 4, 5, 32;
|
||||||
0x78832832;
|
0x78832832;
|
||||||
|
WrapToUInt6;
|
||||||
Some((31, 33));
|
Some((31, 33));
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate! {
|
rotate! {
|
||||||
"rldcr" 3, 4, 5, 63;
|
"rldcr" 3, 4, 5, 63;
|
||||||
0x78832ff2;
|
0x78832ff2;
|
||||||
|
WrapToUInt6;
|
||||||
None;
|
None;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -651,6 +752,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
|
||||||
0x7883000c;
|
0x7883000c;
|
||||||
None;
|
None;
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883040c;
|
||||||
Some((0, 48));
|
Some((0, 48));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307cc;
|
||||||
Some((0, 33));
|
Some((0, 33));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883002c;
|
||||||
Some((0, 32));
|
Some((0, 32));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307ec;
|
||||||
Some((0, 1));
|
Some((0, 1));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788387ec;
|
||||||
Some((16, 49));
|
Some((16, 49));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883ffec;
|
||||||
Some((31, 34));
|
Some((31, 34));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x788307ee;
|
||||||
Some((32, 33));
|
Some((32, 33));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883ffee;
|
||||||
Some((63, 2));
|
Some((63, 2));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883f82e;
|
||||||
Some((63, 33));
|
Some((63, 33));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
rotate_imm! {
|
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;
|
0x7883f80e;
|
||||||
Some((63, 1));
|
Some((63, 1));
|
||||||
true;
|
true;
|
||||||
|
Full64;
|
||||||
FunnelShift2x64Bit;
|
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;
|
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||||
$encoding:literal;
|
$encoding:literal;
|
||||||
|
$overflow_behavior:ident;
|
||||||
$shift_rotate_mode:ident;
|
$shift_rotate_mode:ident;
|
||||||
) => {{
|
) => {{
|
||||||
retval.push(insn_single(
|
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::const_zero(),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
shift_imm(None, false),
|
shift_imm(
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
ShiftAmountOverflowBehavior.$overflow_behavior(),
|
||||||
|
),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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::const_zero(),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
shift_imm(None, false),
|
shift_imm(
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
ShiftAmountOverflowBehavior.$overflow_behavior(),
|
||||||
|
),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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;
|
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||||
$encoding:literal;
|
$encoding:literal;
|
||||||
|
$overflow_behavior:ident;
|
||||||
$shift_rotate_mode:ident;
|
$shift_rotate_mode:ident;
|
||||||
) => {{
|
) => {{
|
||||||
retval.push(insn_single(
|
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($src),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
shift_imm(None, true),
|
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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($src),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
shift_imm(None, true),
|
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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;
|
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||||
$encoding:literal;
|
$encoding:literal;
|
||||||
|
$overflow_behavior:ident;
|
||||||
$shift_rotate_mode:ident;
|
$shift_rotate_mode:ident;
|
||||||
) => {{
|
) => {{
|
||||||
retval.push(insn_single(
|
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::const_zero(),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
shift_imm(None, true),
|
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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::const_zero(),
|
||||||
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
MOpRegNum::power_isa_gpr_reg_imm($amount),
|
||||||
],
|
],
|
||||||
shift_imm(None, true),
|
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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(),
|
||||||
MOpRegNum::const_zero(),
|
MOpRegNum::const_zero(),
|
||||||
],
|
],
|
||||||
shift_imm(Some($amount), true),
|
shift_imm(
|
||||||
|
Some($amount),
|
||||||
|
true,
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt6(),
|
||||||
|
),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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(),
|
||||||
MOpRegNum::const_zero(),
|
MOpRegNum::const_zero(),
|
||||||
],
|
],
|
||||||
shift_imm(Some($amount), true),
|
shift_imm(
|
||||||
|
Some($amount),
|
||||||
|
true,
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt6(),
|
||||||
|
),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.$shift_rotate_mode(),
|
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! {
|
shift_left! {
|
||||||
"slw" 3, 4, 5;
|
"slw" 3, 4, 5;
|
||||||
0x7c832830;
|
0x7c832830;
|
||||||
|
WrapToUInt6ZeroIfGE32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
shift_right_unsigned! {
|
shift_right_unsigned! {
|
||||||
"srw" 3, 4, 5;
|
"srw" 3, 4, 5;
|
||||||
0x7c832c30;
|
0x7c832c30;
|
||||||
|
WrapToUInt6ZeroIfGE32;
|
||||||
FunnelShift2x32Bit;
|
FunnelShift2x32Bit;
|
||||||
}
|
}
|
||||||
shift_right_signed_imm! {
|
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! {
|
shift_right_signed! {
|
||||||
"sraw" 3, 4, 5;
|
"sraw" 3, 4, 5;
|
||||||
0x7c832e30;
|
0x7c832e30;
|
||||||
|
WrapToUInt6;
|
||||||
SignExt32To64BitThenShift;
|
SignExt32To64BitThenShift;
|
||||||
}
|
}
|
||||||
shift_left! {
|
shift_left! {
|
||||||
"sld" 3, 4, 5;
|
"sld" 3, 4, 5;
|
||||||
0x7c832836;
|
0x7c832836;
|
||||||
|
WrapToUInt7ZeroIfGE64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
shift_right_unsigned! {
|
shift_right_unsigned! {
|
||||||
"srd" 3, 4, 5;
|
"srd" 3, 4, 5;
|
||||||
0x7c832c36;
|
0x7c832c36;
|
||||||
|
WrapToUInt7ZeroIfGE64;
|
||||||
FunnelShift2x64Bit;
|
FunnelShift2x64Bit;
|
||||||
}
|
}
|
||||||
shift_right_signed_imm! {
|
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! {
|
shift_right_signed! {
|
||||||
"srad" 3, 4, 5;
|
"srad" 3, 4, 5;
|
||||||
0x7c832e34;
|
0x7c832e34;
|
||||||
|
WrapToUInt7;
|
||||||
ShiftSigned64;
|
ShiftSigned64;
|
||||||
}
|
}
|
||||||
macro_rules! extswsli {
|
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(),
|
||||||
MOpRegNum::const_zero(),
|
MOpRegNum::const_zero(),
|
||||||
],
|
],
|
||||||
shift_imm(Some($amount), false),
|
shift_imm(
|
||||||
|
Some($amount),
|
||||||
|
false,
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt6(),
|
||||||
|
),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.SignExt32To64BitThenShift(),
|
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(),
|
||||||
MOpRegNum::const_zero(),
|
MOpRegNum::const_zero(),
|
||||||
],
|
],
|
||||||
shift_imm(Some($amount), false),
|
shift_imm(
|
||||||
|
Some($amount),
|
||||||
|
false,
|
||||||
|
ShiftAmountOverflowBehavior.WrapToUInt6(),
|
||||||
|
),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
ShiftRotateMode.SignExt32To64BitThenShift(),
|
ShiftRotateMode.SignExt32To64BitThenShift(),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue