implement decoding all rotate instructions
Some checks failed
/ test (pull_request) Failing after 27m11s
Some checks failed
/ test (pull_request) Failing after 27m11s
This commit is contained in:
parent
130c1b2892
commit
a42b76b468
5 changed files with 31516 additions and 764 deletions
|
|
@ -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),
|
||||
),
|
||||
(
|
||||
&[
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue