implement decoding all rotate instructions
Some checks failed
/ test (pull_request) Failing after 27m11s

This commit is contained in:
Jacob Lifshay 2026-01-26 21:42:22 -08:00
parent 130c1b2892
commit a42b76b468
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
5 changed files with 31516 additions and 764 deletions

View file

@ -6,8 +6,8 @@ use crate::{
instruction::{
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LoadMOp, LoadStoreConversion,
LoadStoreWidth, LogicalFlagsMOp, LogicalFlagsMOpImm, LogicalMOp, Lut4, MOp, MOpDestReg,
MOpRegNum, MoveRegMOp, OutputIntegerMode, ShiftRotateMOp, ShiftRotateMOpImm,
ShiftRotateMode, StoreMOp,
MOpRegNum, MoveRegMOp, OutputIntegerMode, ShiftRotateDestLogicOp, ShiftRotateMOp,
ShiftRotateMOpImm, ShiftRotateMode, StoreMOp,
},
powerisa_instructions_xml::{
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
@ -221,6 +221,14 @@ impl_fields! {
struct FieldDS(SInt<14>);
#[name = "LI"]
struct FieldLI(SInt<24>);
#[name = "MB"]
struct FieldMB(UInt<5>);
#[name = "mb"]
struct FieldMb(UInt<6>);
#[name = "ME"]
struct FieldME(UInt<5>);
#[name = "me"]
struct FieldMe(UInt<6>);
#[name = "SH"]
struct FieldSH(UInt<5>);
#[name = "sh"]
@ -1911,6 +1919,242 @@ impl DecodeState<'_> {
);
});
}
#[hdl]
fn rotate_dest_logic_op(
&mut self,
msb0_mask_begin_: Expr<UInt<6>>,
msb0_mask_end_: Expr<UInt<6>>,
fallback_is_src2: bool,
) -> Expr<HdlOption<ShiftRotateDestLogicOp>> {
#[hdl]
let msb0_mask_begin = wire();
connect(msb0_mask_begin, msb0_mask_begin_);
#[hdl]
let msb0_mask_end = wire();
connect(msb0_mask_end, msb0_mask_end_);
#[hdl]
let rotated_output_start: UInt<6> = wire();
#[hdl]
let rotated_output_len: UInt<6> = wire();
// gives the correct value modulo 2^6 even when `msb0_mask_begin > msb0_mask_end`
connect_any(
rotated_output_len,
msb0_mask_end - msb0_mask_begin + 1_hdl_u6,
);
// account for lsb0 vs. msb0
connect(rotated_output_start, !msb0_mask_end);
#[hdl]
let rotate_dest_logic_op = wire();
#[hdl]
if rotated_output_len.cmp_eq(0_hdl_u6) {
// it's really 64, it wrapped around to 0
connect(rotate_dest_logic_op, HdlNone());
} else {
connect(
rotate_dest_logic_op,
HdlSome(
#[hdl]
ShiftRotateDestLogicOp {
rotated_output_start,
rotated_output_len,
fallback_is_src2,
},
),
);
}
rotate_dest_logic_op
}
#[hdl]
fn rotate_helper(
&mut self,
is_32bit: bool,
msb0_mask_begin: Expr<UInt<6>>,
msb0_mask_end: Expr<UInt<6>>,
ra: FieldRA,
rs: FieldRS,
rb: FieldRB,
rc: FieldRc,
) {
// TODO: handle SO propagation
connect(
ArrayVec::len(self.output),
1usize.cast_to_static::<Length<_>>(),
);
let dest_logic_op = self.rotate_dest_logic_op(msb0_mask_begin, msb0_mask_end, false);
connect(
self.output[0],
ShiftRotateMOp::shift_rotate(
MOpDestReg::new([gpr(ra.0)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc.0)]),
[gpr(rs.0).value, gpr(rs.0).value, gpr(rb.0).value],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlNone(),
shift_rotate_right: false,
dest_logic_op,
},
OutputIntegerMode.Full64(),
if is_32bit {
ShiftRotateMode.FunnelShift2x32Bit()
} else {
ShiftRotateMode.FunnelShift2x64Bit()
},
),
);
}
#[hdl]
fn rotate_imm_helper(
&mut self,
is_32bit: bool,
fallback_is_src2: bool,
msb0_mask_begin: Expr<UInt<6>>,
msb0_mask_end: Expr<UInt<6>>,
rotate_amount: Expr<UInt<6>>,
ra: FieldRA,
rs: FieldRS,
rc: FieldRc,
) {
// TODO: handle SO propagation
connect(
ArrayVec::len(self.output),
1usize.cast_to_static::<Length<_>>(),
);
let dest_logic_op =
self.rotate_dest_logic_op(msb0_mask_begin, msb0_mask_end, fallback_is_src2);
#[hdl]
let rotate_imm_src2 = wire();
connect(rotate_imm_src2, MOpRegNum::const_zero().value);
// if dest_logic_op is HdlNone, we don't need to read from src2
#[hdl]
if let HdlSome(dest_logic_op) = dest_logic_op {
#[hdl]
if dest_logic_op.fallback_is_src2 {
connect(rotate_imm_src2, gpr(ra.0).value);
}
}
connect(
self.output[0],
ShiftRotateMOp::shift_rotate(
MOpDestReg::new([gpr(ra.0)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc.0)]),
[gpr(rs.0).value, gpr(rs.0).value, rotate_imm_src2],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(rotate_amount),
shift_rotate_right: false,
dest_logic_op,
},
OutputIntegerMode.Full64(),
if is_32bit {
ShiftRotateMode.FunnelShift2x32Bit()
} else {
ShiftRotateMode.FunnelShift2x64Bit()
},
),
);
}
/// for `rlwinm[.]/rlwnm[.]/rlwimi[.]/rldicl[.]/rldicr[.]/rldic[.]/rldcl[.]/rldcr[.]/rldimi[.]`
#[hdl]
fn decode_rotate(&mut self) {
match self.mnemonic.trim_end_matches('.') {
"rlwinm" => self.decode_scope(
|this, (ra, rs, FieldSH(sh), FieldMB(mb), FieldME(me), rc)| {
this.rotate_imm_helper(
true,
false,
(mb + 32u8).cast_to_static::<UInt<_>>(),
(me + 32u8).cast_to_static::<UInt<_>>(),
sh.cast_to_static::<UInt<_>>(),
ra,
rs,
rc,
);
},
),
"rlwnm" => self.decode_scope(|this, (ra, rs, rb, FieldMB(mb), FieldME(me), rc)| {
this.rotate_helper(
true,
(mb + 32u8).cast_to_static::<UInt<_>>(),
(me + 32u8).cast_to_static::<UInt<_>>(),
ra,
rs,
rb,
rc,
);
}),
"rlwimi" => self.decode_scope(
|this, (ra, rs, FieldSH(sh), FieldMB(mb), FieldME(me), rc)| {
this.rotate_imm_helper(
true,
true,
(mb + 32u8).cast_to_static::<UInt<_>>(),
(me + 32u8).cast_to_static::<UInt<_>>(),
sh.cast_to_static::<UInt<_>>(),
ra,
rs,
rc,
);
},
),
"rldicl" => self.decode_scope(|this, (ra, rs, FieldSh(sh), FieldMb(mb), rc)| {
this.rotate_imm_helper(
false,
false,
mb.rotate_right(1),
63_hdl_u6,
sh.rotate_right(1),
ra,
rs,
rc,
);
}),
"rldicr" => self.decode_scope(|this, (ra, rs, FieldSh(sh), FieldMe(me), rc)| {
this.rotate_imm_helper(
false,
false,
0_hdl_u6,
me.rotate_right(1),
sh.rotate_right(1),
ra,
rs,
rc,
);
}),
"rldic" => self.decode_scope(|this, (ra, rs, FieldSh(sh), FieldMb(mb), rc)| {
this.rotate_imm_helper(
false,
false,
mb.rotate_right(1),
!sh.rotate_right(1),
sh.rotate_right(1),
ra,
rs,
rc,
);
}),
"rldcl" => self.decode_scope(|this, (ra, rs, rb, FieldMb(mb), rc)| {
this.rotate_helper(false, mb.rotate_right(1), 63_hdl_u6, ra, rs, rb, rc);
}),
"rldcr" => self.decode_scope(|this, (ra, rs, rb, FieldMe(me), rc)| {
this.rotate_helper(false, 0_hdl_u6, me.rotate_right(1), ra, rs, rb, rc);
}),
"rldimi" => self.decode_scope(|this, (ra, rs, FieldSh(sh), FieldMb(mb), rc)| {
this.rotate_imm_helper(
false,
true,
mb.rotate_right(1),
!sh.rotate_right(1),
sh.rotate_right(1),
ra,
rs,
rc,
);
}),
_ => unreachable!("{:?}", self.mnemonic),
}
}
/// for `slw[.]/srw[.]/srawi[.]/sraw[.]/sld[.]/sradi[.]/srd[.]/srad[.]`
#[hdl]
fn decode_shift(&mut self) {
@ -2299,9 +2543,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
"rldicr", "rldicr.", "rldic", "rldic.", "rldcl", "rldcl.", "rldcr", "rldcr.", "rldimi",
"rldimi.",
],
|_state| {
// TODO
},
|state| DecodeState::decode_rotate(state),
),
(
&[

View file

@ -1780,8 +1780,8 @@ impl HdlPartialEqImpl<Self> for ShiftRotateMode {
pub struct ShiftRotateDestLogicOp {
pub rotated_output_start: UInt<6>,
pub rotated_output_len: UInt<6>,
/// `false` for fallback is zeros, `true` for fallback is `src1`
pub fallback_is_src1: Bool,
/// `false` for fallback is zeros, `true` for fallback is `src2`
pub fallback_is_src2: Bool,
}
impl ShiftRotateDestLogicOp {
@ -1789,9 +1789,9 @@ impl ShiftRotateDestLogicOp {
fn operation_impl<U64, U6, U, B, S1>(
rotated_output_start: U6,
rotated_output_len: U6,
fallback_is_src1: B,
fallback_is_src2: B,
rotated_output: U64,
src1: U64,
src2: U64,
) -> U64
where
U64: ValueType<Type = UInt<64>>
@ -1812,47 +1812,47 @@ impl ShiftRotateDestLogicOp {
{
let unrotated_mask = ((1u8 << rotated_output_len) - 1u8).cast_to_static::<UInt<64>>();
let mask = unrotated_mask.rotate_left(rotated_output_start);
let src1_mask = fallback_is_src1
let src1_mask = fallback_is_src2
.cast_to_static::<SInt<1>>()
.cast_to_static::<UInt<64>>();
((rotated_output & mask.clone()) | (src1_mask & src1 & !mask)).cast_to_static::<UInt<64>>()
((rotated_output & mask.clone()) | (src1_mask & src2 & !mask)).cast_to_static::<UInt<64>>()
}
pub fn operation(
this: impl ToExpr<Type = Self>,
rotated_output: impl ToExpr<Type = UInt<64>>,
src1: impl ToExpr<Type = UInt<64>>,
src2: impl ToExpr<Type = UInt<64>>,
) -> Expr<UInt<64>> {
let this = this.to_expr();
let rotated_output = rotated_output.to_expr();
let src1 = src1.to_expr();
let src2 = src2.to_expr();
Self::operation_impl(
this.rotated_output_start,
this.rotated_output_len,
this.fallback_is_src1,
this.fallback_is_src2,
rotated_output,
src1,
src2,
)
}
#[hdl]
pub fn operation_sim(
this: impl ToSimValue<Type = Self>,
rotated_output: impl ToSimValue<Type = UInt<64>>,
src1: impl ToSimValue<Type = UInt<64>>,
src2: impl ToSimValue<Type = UInt<64>>,
) -> SimValue<UInt<64>> {
#[hdl(sim)]
let Self {
rotated_output_start,
rotated_output_len,
fallback_is_src1,
fallback_is_src2,
} = this.into_sim_value();
let rotated_output = rotated_output.into_sim_value();
let src1 = src1.into_sim_value();
let src2 = src2.into_sim_value();
Self::operation_impl(
rotated_output_start,
rotated_output_len,
fallback_is_src1,
fallback_is_src2,
rotated_output,
src1,
src2,
)
}
}

File diff suppressed because it is too large Load diff

View file

@ -54,6 +54,17 @@ fn test_test_cases_assembly() -> std::io::Result<()> {
let mut lines = stdout.lines();
let text_line = lines.next();
assert_eq!(text_line, Some("\t.text"));
let mut any_error = false;
macro_rules! assert_eq_cont {
($l:expr, $r:expr, $($msg:tt)+) => {
match (&$l, &$r) {
(l, r) => if l != r {
eprintln!("assertion failed: {}\nl={l:#?}\nr={r:#?}", format_args!($($msg)+));
any_error = true;
}
}
};
}
for test_case @ TestCase {
mnemonic: _,
first_input,
@ -95,14 +106,18 @@ fn test_test_cases_assembly() -> std::io::Result<()> {
} else {
format!(" encoding: [0x{b0:02x},0x{b1:02x},0x{b2:02x},0x{b3:02x}]")
};
assert_eq!(
comment, expected_comment,
assert_eq_cont!(
comment,
expected_comment,
"test_case={test_case:?}\nline:\n{line}"
);
}
for line in lines {
assert!(line.trim().is_empty(), "bad trailing output line: {line:?}");
}
if any_error {
panic!();
}
Ok(())
}

View file

@ -3,8 +3,8 @@
use crate::test_cases::{TestCase, insn_single};
use cpu::instruction::{
AddSubMOp, MOpDestReg, MOpRegNum, OutputIntegerMode, ShiftRotateMOp, ShiftRotateMOpImm,
ShiftRotateMode,
MOpDestReg, MOpRegNum, OutputIntegerMode, ShiftRotateDestLogicOp, ShiftRotateMOp,
ShiftRotateMOpImm, ShiftRotateMode,
};
use fayalite::prelude::*;
@ -22,9 +22,707 @@ fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
}
}
#[hdl]
fn rotate_imm(
amount: Option<u8>,
rotated_output_start_and_len: Option<(u8, u8)>,
fallback_is_src2: bool,
) -> SimValue<ShiftRotateMOpImm> {
#[hdl(sim)]
ShiftRotateMOpImm {
shift_rotate_amount: if let Some(amount) = amount {
#[hdl(sim)]
HdlSome(amount.cast_to_static::<UInt<_>>())
} else {
#[hdl(sim)]
HdlNone()
},
shift_rotate_right: false,
dest_logic_op: if let Some((rotated_output_start, rotated_output_len)) =
rotated_output_start_and_len
{
#[hdl(sim)]
HdlSome(
#[hdl(sim)]
ShiftRotateDestLogicOp {
rotated_output_start: rotated_output_start.cast_to_static::<UInt<_>>(),
rotated_output_len: rotated_output_len.cast_to_static::<UInt<_>>(),
fallback_is_src2,
},
)
} else {
#[hdl(sim)]
HdlNone()
},
}
}
#[hdl]
fn rotate_imm_src2(imm: &SimValue<ShiftRotateMOpImm>, dest: usize) -> Expr<MOpRegNum> {
#[hdl(sim)]
match &imm.dest_logic_op {
HdlSome(dest_logic_op) => {
if *dest_logic_op.fallback_is_src2 {
MOpRegNum::power_isa_gpr_reg_imm(dest)
} else {
MOpRegNum::const_zero()
}
}
_ => MOpRegNum::const_zero(),
}
}
/// covers instructions in PowerISA v3.1C Book I 3.3.14 Fixed-Point Rotate and Shift Instructions
pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<TestCase>) {
// TODO: rotate instructions
macro_rules! rotate_imm {
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal $(, $args:literal)*;
$encoding:literal;
$rotated_output_start_and_len:expr;
$fallback_is_src2:literal;
$shift_rotate_mode:ident;
) => {{
let imm = rotate_imm(Some($amount), $rotated_output_start_and_len, $fallback_is_src2);
let src2 = rotate_imm_src2(&imm, $dest);
retval.push(insn_single(
concat!(
$mnemonic,
" ",
stringify!($dest),
", ",
stringify!($src),
", ",
stringify!($amount),
$(", ",
stringify!($args),)*
),
$encoding,
None,
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
src2.value,
],
&imm,
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
retval.push(insn_single(
concat!(
$mnemonic,
". ",
stringify!($dest),
", ",
stringify!($src),
", ",
stringify!($amount),
$(", ",
stringify!($args),)*
),
$encoding | 1,
None,
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
src2.value,
],
imm,
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
}};
}
macro_rules! rotate {
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal $(, $args:literal)*;
$encoding:literal;
$rotated_output_start_and_len:expr;
$shift_rotate_mode:ident;
) => {{
retval.push(insn_single(
concat!(
$mnemonic,
" ",
stringify!($dest),
", ",
stringify!($src),
", ",
stringify!($amount),
$(", ",
stringify!($args),)*
),
$encoding,
None,
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
],
rotate_imm(None, $rotated_output_start_and_len, false),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
retval.push(insn_single(
concat!(
$mnemonic,
". ",
stringify!($dest),
", ",
stringify!($src),
", ",
stringify!($amount),
$(", ",
stringify!($args),)*
),
$encoding | 1,
None,
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
],
rotate_imm(None, $rotated_output_start_and_len, false),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
));
}};
}
rotate_imm! {
"rlwinm" 3, 4, 0, 0, 0;
0x54830000;
Some((31, 1));
false;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwinm" 3, 4, 5, 0, 0;
0x54832800;
Some((31, 1));
false;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwinm" 3, 4, 31, 0, 0;
0x5483f800;
Some((31, 1));
false;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwinm" 3, 4, 5, 0, 16;
0x54832820;
Some((15, 17));
false;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwinm" 3, 4, 5, 0, 31;
0x5483283e;
Some((0, 32));
false;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwinm" 3, 4, 5, 31, 31;
0x54832ffe;
Some((0, 1));
false;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwinm" 3, 4, 5, 31, 0;
0x54832fc0;
Some((31, 34));
false;
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 0, 0;
0x5c832800;
Some((31, 1));
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 0, 16;
0x5c832820;
Some((15, 17));
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 0, 31;
0x5c83283e;
Some((0, 32));
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 31, 31;
0x5c832ffe;
Some((0, 1));
FunnelShift2x32Bit;
}
rotate! {
"rlwnm" 3, 4, 5, 31, 0;
0x5c832fc0;
Some((31, 34));
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 0, 0, 0;
0x50830000;
Some((31, 1));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 5, 0, 0;
0x50832800;
Some((31, 1));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 31, 0, 0;
0x5083f800;
Some((31, 1));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 5, 0, 16;
0x50832820;
Some((15, 17));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 5, 0, 31;
0x5083283e;
Some((0, 32));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 5, 31, 31;
0x50832ffe;
Some((0, 1));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rlwimi" 3, 4, 5, 31, 0;
0x50832fc0;
Some((31, 34));
true;
FunnelShift2x32Bit;
}
rotate_imm! {
"rldicl" 3, 4, 0, 0;
0x78830000;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 5, 0;
0x78832800;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 16, 0;
0x78838000;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 31, 0;
0x7883f800;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 32, 0;
0x78830002;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 63, 0;
0x7883f802;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 5, 5;
0x78832940;
Some((0, 59));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 5, 16;
0x78832c00;
Some((0, 48));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 5, 31;
0x78832fc0;
Some((0, 33));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 5, 32;
0x78832820;
Some((0, 32));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicl" 3, 4, 5, 63;
0x78832fe0;
Some((0, 1));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 0, 63;
0x788307e4;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 63;
0x78832fe4;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 16, 63;
0x788387e4;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 31, 63;
0x7883ffe4;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 32, 63;
0x788307e6;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 63, 63;
0x7883ffe6;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 0;
0x78832804;
Some((63, 1));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 5;
0x78832944;
Some((58, 6));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 16;
0x78832c04;
Some((47, 17));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 31;
0x78832fc4;
Some((32, 32));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 32;
0x78832824;
Some((31, 33));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldicr" 3, 4, 5, 63;
0x78832fe4;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 0, 0;
0x78830008;
None;
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 0, 16;
0x78830408;
Some((0, 48));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 0, 31;
0x788307c8;
Some((0, 33));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 0, 32;
0x78830028;
Some((0, 32));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 0, 63;
0x788307e8;
Some((0, 1));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 16, 63;
0x788387e8;
Some((16, 49));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 31, 63;
0x7883ffe8;
Some((31, 34));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 32, 63;
0x788307ea;
Some((32, 33));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 63, 63;
0x7883ffea;
Some((63, 2));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 63, 32;
0x7883f82a;
Some((63, 33));
false;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldic" 3, 4, 63, 0;
0x7883f80a;
Some((63, 1));
false;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 0;
0x78832810;
None;
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 5;
0x78832950;
Some((0, 59));
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 16;
0x78832c10;
Some((0, 48));
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 31;
0x78832fd0;
Some((0, 33));
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 32;
0x78832830;
Some((0, 32));
FunnelShift2x64Bit;
}
rotate! {
"rldcl" 3, 4, 5, 63;
0x78832ff0;
Some((0, 1));
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 0;
0x78832812;
Some((63, 1));
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 5;
0x78832952;
Some((58, 6));
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 16;
0x78832c12;
Some((47, 17));
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 31;
0x78832fd2;
Some((32, 32));
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 32;
0x78832832;
Some((31, 33));
FunnelShift2x64Bit;
}
rotate! {
"rldcr" 3, 4, 5, 63;
0x78832ff2;
None;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 0, 0;
0x7883000c;
None;
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 0, 16;
0x7883040c;
Some((0, 48));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 0, 31;
0x788307cc;
Some((0, 33));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 0, 32;
0x7883002c;
Some((0, 32));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 0, 63;
0x788307ec;
Some((0, 1));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 16, 63;
0x788387ec;
Some((16, 49));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 31, 63;
0x7883ffec;
Some((31, 34));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 32, 63;
0x788307ee;
Some((32, 33));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 63, 63;
0x7883ffee;
Some((63, 2));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 63, 32;
0x7883f82e;
Some((63, 33));
true;
FunnelShift2x64Bit;
}
rotate_imm! {
"rldimi" 3, 4, 63, 0;
0x7883f80e;
Some((63, 1));
true;
FunnelShift2x64Bit;
}
macro_rules! shift_left {
(