Compare commits

...

3 commits

7 changed files with 176565 additions and 155430 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) {
@ -2044,6 +2288,37 @@ impl DecodeState<'_> {
);
}
}
/// for `extswsli[.]`
#[hdl]
fn decode_extswsli(&mut self) {
self.decode_scope(
|this, (FieldRA(ra), FieldRS(rs), FieldSh(sh), FieldRc(rc))| {
connect(
ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(),
);
connect(
this.output[0],
ShiftRotateMOp::shift_rotate(
MOpDestReg::new([gpr(ra)], [(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)]),
[
gpr(rs).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
],
#[hdl]
ShiftRotateMOpImm {
shift_rotate_amount: HdlSome(sh.rotate_right(1)),
shift_rotate_right: false,
dest_logic_op: HdlNone(),
},
OutputIntegerMode.Full64(),
ShiftRotateMode.SignExt32To64BitThenShift(),
),
);
},
);
}
/// for `mcrxrx`
#[hdl]
fn decode_mcrxrx(&mut self) {
@ -2268,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),
),
(
&[
@ -2279,8 +2552,8 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
],
|state| DecodeState::decode_shift(state),
),
(&["extswsli", "extswsli."], |_state| {
// TODO
(&["extswsli", "extswsli."], |state| {
DecodeState::decode_extswsli(state)
}),
(&["cdtbcd", "cbcdtd", "addg6s"], |_state| {
// TODO

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,7 @@
use crate::{
config::CpuConfig,
instruction::{
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOpDefaultImm,
CompareMOp, LogicalFlagsMOp, LogicalMOp, MOpTrait, OutputIntegerMode, RenamedMOp,
ShiftRotateMOp, UnitOutRegNum,
},
@ -42,11 +42,11 @@ fn add_sub<SrcCount: KnownSize>(
add_pc,
} = mop;
#[hdl]
let AluCommonMOp::<_, _, _> {
let AluCommonMOp::<_, _, _, _> {
common,
output_integer_mode,
} = alu_common;
let imm: Expr<UInt<64>> = CommonMOp::imm(common).cast_to_static();
let imm = CommonMOpDefaultImm::as_sint_dyn(common.imm).cast_to_static::<UInt<64>>();
#[hdl]
let carry_in_before_inversion = wire();
connect(carry_in_before_inversion, false);

File diff suppressed because it is too large Load diff

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 {
(
@ -360,5 +1058,86 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
0x7c832e34;
ShiftSigned64;
}
// TODO: extswsli
macro_rules! extswsli {
(
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
$encoding:literal;
) => {{
retval.push(insn_single(
concat!(
$mnemonic,
" ",
stringify!($dest),
", ",
stringify!($src),
", ",
stringify!($amount)
),
$encoding,
None,
ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($src).value,
MOpRegNum::const_zero().value,
MOpRegNum::const_zero().value,
],
shift_imm(Some($amount), false),
OutputIntegerMode.Full64(),
ShiftRotateMode.SignExt32To64BitThenShift(),
),
));
retval.push(insn_single(
concat!(
$mnemonic,
". ",
stringify!($dest),
", ",
stringify!($src),
", ",
stringify!($amount)
),
$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::const_zero().value,
MOpRegNum::const_zero().value,
],
shift_imm(Some($amount), false),
OutputIntegerMode.Full64(),
ShiftRotateMode.SignExt32To64BitThenShift(),
),
));
}};
}
extswsli! {
"extswsli" 3, 4, 0;
0x7c8306f4;
}
extswsli! {
"extswsli" 3, 4, 5;
0x7c832ef4;
}
extswsli! {
"extswsli" 3, 4, 16;
0x7c8386f4;
}
extswsli! {
"extswsli" 3, 4, 31;
0x7c83fef4;
}
extswsli! {
"extswsli" 3, 4, 32;
0x7c8306f6;
}
extswsli! {
"extswsli" 3, 4, 63;
0x7c83fef6;
}
}