implement decoding shifts: s[lr][wd][.] and sra[wd][i][.]
This commit is contained in:
parent
59874b9b29
commit
1db65ae753
6 changed files with 11897 additions and 253 deletions
|
|
@ -6,7 +6,8 @@ use crate::{
|
|||
instruction::{
|
||||
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LoadMOp, LoadStoreConversion,
|
||||
LoadStoreWidth, LogicalFlagsMOp, LogicalFlagsMOpImm, LogicalMOp, Lut4, MOp, MOpDestReg,
|
||||
MOpRegNum, MoveRegMOp, OutputIntegerMode, StoreMOp,
|
||||
MOpRegNum, MoveRegMOp, OutputIntegerMode, ShiftRotateMOp, ShiftRotateMOpImm,
|
||||
ShiftRotateMode, StoreMOp,
|
||||
},
|
||||
powerisa_instructions_xml::{
|
||||
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
|
||||
|
|
@ -14,7 +15,10 @@ use crate::{
|
|||
register::{
|
||||
PRegFlags, PRegFlagsPowerISA, PRegFlagsPowerISAView, PRegFlagsViewTrait, ViewUnused,
|
||||
},
|
||||
util::array_vec::{ArrayVec, Length},
|
||||
util::{
|
||||
Rotate,
|
||||
array_vec::{ArrayVec, Length},
|
||||
},
|
||||
};
|
||||
use fayalite::{
|
||||
int::{BoolOrIntType, UIntInRange},
|
||||
|
|
@ -22,7 +26,10 @@ use fayalite::{
|
|||
prelude::*,
|
||||
ty::StaticType,
|
||||
};
|
||||
use std::{collections::BTreeMap, ops::RangeInclusive};
|
||||
use std::{
|
||||
collections::{BTreeMap, btree_map::Entry},
|
||||
ops::RangeInclusive,
|
||||
};
|
||||
|
||||
#[rustfmt::skip]
|
||||
const FP_MNEMONICS: &[&str] = &[
|
||||
|
|
@ -218,6 +225,10 @@ impl_fields! {
|
|||
struct FieldDS(SInt<14>);
|
||||
#[name = "LI"]
|
||||
struct FieldLI(SInt<24>);
|
||||
#[name = "SH"]
|
||||
struct FieldSH(UInt<5>);
|
||||
#[name = "sh"]
|
||||
struct FieldSh(UInt<6>);
|
||||
#[name = "SI"]
|
||||
struct FieldSI(SInt<16>);
|
||||
#[name = "si0"]
|
||||
|
|
@ -397,6 +408,20 @@ impl DecodeState {
|
|||
fields_inner: &'static InstructionBitFieldsInner,
|
||||
) {
|
||||
let mut last_start = word.ty().width();
|
||||
struct FieldPieces {
|
||||
filled_pieces: Vec<Expr<UInt>>,
|
||||
piece_count: usize,
|
||||
}
|
||||
let mut fields_pieces = BTreeMap::new();
|
||||
for bit_field in fields_inner.fields() {
|
||||
fields_pieces
|
||||
.entry(Self::bit_field_name(bit_field.name()))
|
||||
.or_insert_with(|| FieldPieces {
|
||||
filled_pieces: Vec::with_capacity(1),
|
||||
piece_count: 0,
|
||||
})
|
||||
.piece_count += 1;
|
||||
}
|
||||
for bit_field in fields_inner.fields().iter().rev() {
|
||||
let bit_number_text = match bit_field.bit_number().text() {
|
||||
"3031" => "30 31",
|
||||
|
|
@ -436,6 +461,10 @@ impl DecodeState {
|
|||
if name.contains(char::is_alphabetic) {
|
||||
for (cond_name, cond_value) in self.conditions() {
|
||||
if name == cond_name {
|
||||
assert_eq!(
|
||||
fields_pieces[name].piece_count, 1,
|
||||
"can't apply conditions to a field with more than one piece: name {name:?}",
|
||||
);
|
||||
name = cond_value;
|
||||
break;
|
||||
}
|
||||
|
|
@ -444,15 +473,33 @@ impl DecodeState {
|
|||
if name == "any value*" || name.bytes().all(|b| b == b'/') {
|
||||
// wildcard
|
||||
} else if name.contains(char::is_alphabetic) {
|
||||
let wire = wire_with_loc(
|
||||
&format!("{}_{name}", self.mnemonic)
|
||||
.replace(|c: char| !c.is_ascii_alphanumeric(), "_"),
|
||||
SourceLocation::caller(),
|
||||
field.ty(),
|
||||
);
|
||||
connect(wire, field);
|
||||
if fields.insert(name, wire).is_some() {
|
||||
panic!("duplicate field name: {name:?}\nheader: {:#?}", self.header);
|
||||
let Some(field_pieces) = fields_pieces.get_mut(name) else {
|
||||
unreachable!();
|
||||
};
|
||||
field_pieces.filled_pieces.push(field);
|
||||
if field_pieces.filled_pieces.len() == field_pieces.piece_count {
|
||||
let wire = wire_with_loc(
|
||||
&format!("{}_{name}", self.mnemonic)
|
||||
.replace(|c: char| !c.is_ascii_alphanumeric(), "_"),
|
||||
SourceLocation::caller(),
|
||||
UInt[field_pieces
|
||||
.filled_pieces
|
||||
.iter()
|
||||
.map(|v| v.ty().width())
|
||||
.sum::<usize>()],
|
||||
);
|
||||
// filled_pieces are in lsb to msb order
|
||||
let mut filled_pieces = field_pieces.filled_pieces.drain(..);
|
||||
let Some(mut value) = filled_pieces.next() else {
|
||||
unreachable!();
|
||||
};
|
||||
let mut shift = value.ty().width();
|
||||
for next_value in filled_pieces {
|
||||
value = value | (next_value << shift);
|
||||
shift += next_value.ty().width();
|
||||
}
|
||||
connect(wire, value);
|
||||
fields.insert(name, wire);
|
||||
}
|
||||
} else {
|
||||
let value: u32 = name.parse().expect("bit field name must have at least one letter, be all `/`, or be a valid decimal number");
|
||||
|
|
@ -1856,6 +1903,139 @@ impl DecodeState {
|
|||
);
|
||||
});
|
||||
}
|
||||
/// for `slw[.]/srw[.]/srawi[.]/sraw[.]/sld[.]/sradi[.]/srd[.]/srad[.]`
|
||||
#[hdl]
|
||||
fn decode_shift(&mut self) {
|
||||
let (is_32bit, is_signed, is_right_shift, is_immediate) =
|
||||
match self.mnemonic.trim_end_matches('.') {
|
||||
"slw" => (true, false, false, false),
|
||||
"srw" => (true, false, true, false),
|
||||
"srawi" => (true, true, true, true),
|
||||
"sraw" => (true, true, true, false),
|
||||
"sld" => (false, false, false, false),
|
||||
"sradi" => (false, true, true, true),
|
||||
"srd" => (false, false, true, false),
|
||||
"srad" => (false, true, true, false),
|
||||
_ => unreachable!("{:?}", self.mnemonic),
|
||||
};
|
||||
if is_immediate {
|
||||
assert!(is_signed);
|
||||
assert!(is_right_shift);
|
||||
assert_eq!(self.arguments, Some("RA,RS,SH"));
|
||||
if is_32bit {
|
||||
self.decode_scope(
|
||||
|this, (FieldRA(ra), FieldRS(rs), FieldSH(sh), FieldRc(rc))| {
|
||||
// TODO: handle SO propagation
|
||||
connect(
|
||||
ArrayVec::len(this.output),
|
||||
1usize.cast_to_static::<Length<_>>(),
|
||||
);
|
||||
connect(
|
||||
this.output[0],
|
||||
ShiftRotateMOp::shift_rotate(
|
||||
MOpDestReg::new(
|
||||
[gpr(ra), MOpRegNum::power_isa_xer_ca_ca32_reg()],
|
||||
[(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.cast_to_static::<UInt<_>>()),
|
||||
shift_rotate_right: true,
|
||||
dest_logic_op: HdlNone(),
|
||||
},
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.SignExt32To64BitThenShift(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
self.decode_scope(
|
||||
|this, (FieldRA(ra), FieldRS(rs), FieldSh(sh), FieldRc(rc))| {
|
||||
// TODO: handle SO propagation
|
||||
connect(
|
||||
ArrayVec::len(this.output),
|
||||
1usize.cast_to_static::<Length<_>>(),
|
||||
);
|
||||
connect(
|
||||
this.output[0],
|
||||
ShiftRotateMOp::shift_rotate(
|
||||
MOpDestReg::new(
|
||||
[gpr(ra), MOpRegNum::power_isa_xer_ca_ca32_reg()],
|
||||
[(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: true,
|
||||
dest_logic_op: HdlNone(),
|
||||
},
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.ShiftSigned64(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
assert_eq!(self.arguments, Some("RA,RS,RB"));
|
||||
self.decode_scope(
|
||||
|this, (FieldRA(ra), FieldRS(rs), FieldRB(rb), FieldRc(rc))| {
|
||||
// TODO: handle SO propagation
|
||||
connect(
|
||||
ArrayVec::len(this.output),
|
||||
1usize.cast_to_static::<Length<_>>(),
|
||||
);
|
||||
connect(
|
||||
this.output[0],
|
||||
ShiftRotateMOp::shift_rotate(
|
||||
MOpDestReg::new(
|
||||
[
|
||||
gpr(ra),
|
||||
if is_signed && is_right_shift {
|
||||
MOpRegNum::power_isa_xer_ca_ca32_reg()
|
||||
} else {
|
||||
MOpRegNum::const_zero()
|
||||
},
|
||||
],
|
||||
[(MOpRegNum::POWER_ISA_CR_0_REG_NUM, rc)],
|
||||
),
|
||||
if !is_signed && is_right_shift {
|
||||
[MOpRegNum::const_zero().value, gpr(rs).value, gpr(rb).value]
|
||||
} else {
|
||||
[gpr(rs).value, MOpRegNum::const_zero().value, gpr(rb).value]
|
||||
},
|
||||
#[hdl]
|
||||
ShiftRotateMOpImm {
|
||||
shift_rotate_amount: HdlNone(),
|
||||
shift_rotate_right: is_right_shift,
|
||||
dest_logic_op: HdlNone(),
|
||||
},
|
||||
OutputIntegerMode.Full64(),
|
||||
match (is_32bit, is_signed, is_right_shift) {
|
||||
(false, _, false) => ShiftRotateMode.FunnelShift2x64Bit(),
|
||||
(false, false, true) => ShiftRotateMode.FunnelShift2x64Bit(),
|
||||
(false, true, true) => ShiftRotateMode.ShiftSigned64(),
|
||||
(true, _, false) => ShiftRotateMode.FunnelShift2x32Bit(),
|
||||
(true, false, true) => ShiftRotateMode.FunnelShift2x32Bit(),
|
||||
(true, true, true) => ShiftRotateMode.SignExt32To64BitThenShift(),
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
/// for `mcrxrx`
|
||||
#[hdl]
|
||||
fn decode_mcrxrx(&mut self) {
|
||||
|
|
@ -2084,9 +2264,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
|||
"slw", "slw.", "srw", "srw.", "srawi", "srawi.", "sraw", "sraw.", "sld", "sld.",
|
||||
"sradi", "sradi.", "srd", "srd.", "srad", "srad.",
|
||||
],
|
||||
|_state| {
|
||||
// TODO
|
||||
},
|
||||
DecodeState::decode_shift,
|
||||
),
|
||||
(&["extswsli", "extswsli."], |_state| {
|
||||
// TODO
|
||||
|
|
|
|||
|
|
@ -1605,17 +1605,22 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalMOp<DestReg, SrcRegWidth, ConstUsi
|
|||
|
||||
#[hdl]
|
||||
pub enum ShiftRotateMode {
|
||||
/// like `llvm.fsh[lr].i8(src0, src1, src2)`
|
||||
/// like `llvm.fsh[lr].i8(src0, src1, shift_rotate_amount.unwrap_or(src2))`
|
||||
FunnelShift2x8Bit,
|
||||
/// like `llvm.fsh[lr].i16(src0, src1, src2)`
|
||||
/// like `llvm.fsh[lr].i16(src0, src1, shift_rotate_amount.unwrap_or(src2))`
|
||||
FunnelShift2x16Bit,
|
||||
/// like `llvm.fsh[lr].i32(src0, src1, src2)`
|
||||
/// like `llvm.fsh[lr].i32(src0, src1, shift_rotate_amount.unwrap_or(src2))`
|
||||
FunnelShift2x32Bit,
|
||||
/// like `llvm.fsh[lr].i64(src0, src1, src2)`
|
||||
/// like `llvm.fsh[lr].i64(src0, src1, shift_rotate_amount.unwrap_or(src2))`
|
||||
FunnelShift2x64Bit,
|
||||
/// `shift(src0 as i8 as i64, shift_rotate_amount.unwrap_or(src2))`
|
||||
SignExt8To64BitThenShift,
|
||||
/// `shift(src0 as i16 as i64, shift_rotate_amount.unwrap_or(src2))`
|
||||
SignExt16To64BitThenShift,
|
||||
/// `shift(src0 as i32 as i64, shift_rotate_amount.unwrap_or(src2))`
|
||||
SignExt32To64BitThenShift,
|
||||
/// `shift(src0 as i64, shift_rotate_amount.unwrap_or(src2))`
|
||||
ShiftSigned64,
|
||||
}
|
||||
|
||||
impl HdlPartialEqImpl<Self> for ShiftRotateMode {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,54 @@ pub trait Rotate<Amount> {
|
|||
fn rotate_right(&self, amount: Amount) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<VSz: Size> Rotate<usize> for Expr<UIntType<VSz>> {
|
||||
type Output = Self;
|
||||
/// like [`usize::rotate_left`]
|
||||
fn rotate_left(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().width() == 0 {
|
||||
return *self;
|
||||
}
|
||||
let amount = amount % self.ty().width();
|
||||
let l = *self << amount;
|
||||
let r = *self >> (self.ty().width() - amount);
|
||||
(l | r).cast_to(self.ty())
|
||||
}
|
||||
/// like [`usize::rotate_right`]
|
||||
fn rotate_right(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().width() == 0 {
|
||||
return *self;
|
||||
}
|
||||
let amount = amount % self.ty().width();
|
||||
let l = *self << (self.ty().width() - amount);
|
||||
let r = *self >> amount;
|
||||
(l | r).cast_to(self.ty())
|
||||
}
|
||||
}
|
||||
|
||||
impl<VSz: Size> Rotate<usize> for SimValue<UIntType<VSz>> {
|
||||
type Output = Self;
|
||||
/// like [`usize::rotate_left`]
|
||||
fn rotate_left(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().width() == 0 {
|
||||
return self.clone();
|
||||
}
|
||||
let amount = amount % self.ty().width();
|
||||
let l = self << amount;
|
||||
let r = self >> (self.ty().width() - amount);
|
||||
(l | r).cast_to(self.ty())
|
||||
}
|
||||
/// like [`usize::rotate_right`]
|
||||
fn rotate_right(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().width() == 0 {
|
||||
return self.clone();
|
||||
}
|
||||
let amount = amount % self.ty().width();
|
||||
let l = self << (self.ty().width() - amount);
|
||||
let r = self >> amount;
|
||||
(l | r).cast_to(self.ty())
|
||||
}
|
||||
}
|
||||
|
||||
impl<VSz: Size, ASz: Size> Rotate<Expr<UIntType<ASz>>> for Expr<UIntType<VSz>> {
|
||||
type Output = Self;
|
||||
/// like [`usize::rotate_left`]
|
||||
|
|
@ -176,3 +224,59 @@ impl<T: Type, N: Size, AmountSize: Size> Rotate<SimValue<UIntType<AmountSize>>>
|
|||
retval
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Type, N: Size> Rotate<usize> for Expr<ArrayType<T, N>> {
|
||||
type Output = Self;
|
||||
/// like [`<[T]>::rotate_left`](slice::rotate_left)
|
||||
fn rotate_left(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().len() == 0 {
|
||||
return self.clone();
|
||||
}
|
||||
let amount = amount % self.ty().len();
|
||||
let mut retval = Vec::from_iter(*self);
|
||||
retval.rotate_left(amount);
|
||||
ArrayLiteral::new(
|
||||
self.ty().element(),
|
||||
retval.into_iter().map(Expr::canonical).collect(),
|
||||
)
|
||||
.to_expr()
|
||||
}
|
||||
/// like [`<[T]>::rotate_right`](slice::rotate_right)
|
||||
fn rotate_right(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().len() == 0 {
|
||||
return self.clone();
|
||||
}
|
||||
let amount = amount % self.ty().len();
|
||||
let mut retval = Vec::from_iter(*self);
|
||||
retval.rotate_right(amount);
|
||||
ArrayLiteral::new(
|
||||
self.ty().element(),
|
||||
retval.into_iter().map(Expr::canonical).collect(),
|
||||
)
|
||||
.to_expr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Type, N: Size> Rotate<usize> for SimValue<ArrayType<T, N>> {
|
||||
type Output = Self;
|
||||
/// like [`<[T]>::rotate_left`](slice::rotate_left)
|
||||
fn rotate_left(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().len() == 0 {
|
||||
return self.clone();
|
||||
}
|
||||
let amount = amount % self.ty().len();
|
||||
let mut retval = self.clone();
|
||||
AsMut::<[SimValue<T>]>::as_mut(&mut SimValue::value_mut(&mut retval)).rotate_left(amount);
|
||||
retval
|
||||
}
|
||||
/// like [`<[T]>::rotate_right`](slice::rotate_right)
|
||||
fn rotate_right(&self, amount: usize) -> Self::Output {
|
||||
if self.ty().len() == 0 {
|
||||
return self.clone();
|
||||
}
|
||||
let amount = amount % self.ty().len();
|
||||
let mut retval = self.clone();
|
||||
AsMut::<[SimValue<T>]>::as_mut(&mut SimValue::value_mut(&mut retval)).rotate_right(amount);
|
||||
retval
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -11,6 +11,7 @@ mod fixed_point_arithmetic;
|
|||
mod fixed_point_compare;
|
||||
mod fixed_point_load;
|
||||
mod fixed_point_logical;
|
||||
mod fixed_point_rotate_and_shift;
|
||||
mod fixed_point_store;
|
||||
mod move_to_from_system_register;
|
||||
mod prefixed_no_operation;
|
||||
|
|
@ -143,6 +144,9 @@ pub fn test_cases() -> Vec<TestCase> {
|
|||
fixed_point_arithmetic::test_cases_book_i_3_3_9_fixed_point_arithmetic(&mut retval);
|
||||
fixed_point_compare::test_cases_book_i_3_3_10_fixed_point_compare(&mut retval);
|
||||
fixed_point_logical::test_cases_book_i_3_3_13_fixed_point_logical(&mut retval);
|
||||
fixed_point_rotate_and_shift::test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(
|
||||
&mut retval,
|
||||
);
|
||||
move_to_from_system_register::test_cases_book_i_3_3_19_move_to_from_system_register(
|
||||
&mut retval,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,364 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::test_cases::{TestCase, insn_single};
|
||||
use cpu::instruction::{
|
||||
AddSubMOp, MOpDestReg, MOpRegNum, OutputIntegerMode, ShiftRotateMOp, ShiftRotateMOpImm,
|
||||
ShiftRotateMode,
|
||||
};
|
||||
use fayalite::prelude::*;
|
||||
|
||||
#[hdl]
|
||||
fn shift_imm(amount: Option<u8>, shift_right: bool) -> Expr<ShiftRotateMOpImm> {
|
||||
#[hdl]
|
||||
ShiftRotateMOpImm {
|
||||
shift_rotate_amount: if let Some(amount) = amount {
|
||||
HdlSome(amount.cast_to_static::<UInt<_>>())
|
||||
} else {
|
||||
HdlNone()
|
||||
},
|
||||
shift_rotate_right: shift_right,
|
||||
dest_logic_op: HdlNone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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! shift_left {
|
||||
(
|
||||
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||
$encoding:literal;
|
||||
$shift_rotate_mode:ident;
|
||||
) => {{
|
||||
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::power_isa_gpr_reg_imm($amount).value,
|
||||
],
|
||||
shift_imm(None, false),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
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::power_isa_gpr_reg_imm($amount).value,
|
||||
],
|
||||
shift_imm(None, false),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
}};
|
||||
}
|
||||
macro_rules! shift_right_unsigned {
|
||||
(
|
||||
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||
$encoding:literal;
|
||||
$shift_rotate_mode:ident;
|
||||
) => {{
|
||||
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::const_zero().value,
|
||||
MOpRegNum::power_isa_gpr_reg_imm($src).value,
|
||||
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
|
||||
],
|
||||
shift_imm(None, true),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
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::const_zero().value,
|
||||
MOpRegNum::power_isa_gpr_reg_imm($src).value,
|
||||
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
|
||||
],
|
||||
shift_imm(None, true),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
}};
|
||||
}
|
||||
macro_rules! shift_right_signed {
|
||||
(
|
||||
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||
$encoding:literal;
|
||||
$shift_rotate_mode:ident;
|
||||
) => {{
|
||||
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_XER_CA_CA32_REG_NUM,
|
||||
],
|
||||
&[],
|
||||
),
|
||||
[
|
||||
MOpRegNum::power_isa_gpr_reg_imm($src).value,
|
||||
MOpRegNum::const_zero().value,
|
||||
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
|
||||
],
|
||||
shift_imm(None, true),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
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_XER_CA_CA32_REG_NUM,
|
||||
],
|
||||
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
|
||||
),
|
||||
[
|
||||
MOpRegNum::power_isa_gpr_reg_imm($src).value,
|
||||
MOpRegNum::const_zero().value,
|
||||
MOpRegNum::power_isa_gpr_reg_imm($amount).value,
|
||||
],
|
||||
shift_imm(None, true),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
}};
|
||||
}
|
||||
macro_rules! shift_right_signed_imm {
|
||||
(
|
||||
$mnemonic:literal $dest:literal, $src:literal, $amount:literal;
|
||||
$encoding:literal;
|
||||
$shift_rotate_mode:ident;
|
||||
) => {{
|
||||
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_XER_CA_CA32_REG_NUM,
|
||||
],
|
||||
&[],
|
||||
),
|
||||
[
|
||||
MOpRegNum::power_isa_gpr_reg_imm($src).value,
|
||||
MOpRegNum::const_zero().value,
|
||||
MOpRegNum::const_zero().value,
|
||||
],
|
||||
shift_imm(Some($amount), true),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
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_XER_CA_CA32_REG_NUM,
|
||||
],
|
||||
&[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), true),
|
||||
OutputIntegerMode.Full64(),
|
||||
ShiftRotateMode.$shift_rotate_mode(),
|
||||
),
|
||||
));
|
||||
}};
|
||||
}
|
||||
shift_left! {
|
||||
"slw" 3, 4, 5;
|
||||
0x7c832830;
|
||||
FunnelShift2x32Bit;
|
||||
}
|
||||
shift_right_unsigned! {
|
||||
"srw" 3, 4, 5;
|
||||
0x7c832c30;
|
||||
FunnelShift2x32Bit;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"srawi" 3, 4, 0;
|
||||
0x7c830670;
|
||||
SignExt32To64BitThenShift;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"srawi" 3, 4, 5;
|
||||
0x7c832e70;
|
||||
SignExt32To64BitThenShift;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"srawi" 3, 4, 16;
|
||||
0x7c838670;
|
||||
SignExt32To64BitThenShift;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"srawi" 3, 4, 31;
|
||||
0x7c83fe70;
|
||||
SignExt32To64BitThenShift;
|
||||
}
|
||||
shift_right_signed! {
|
||||
"sraw" 3, 4, 5;
|
||||
0x7c832e30;
|
||||
SignExt32To64BitThenShift;
|
||||
}
|
||||
shift_left! {
|
||||
"sld" 3, 4, 5;
|
||||
0x7c832836;
|
||||
FunnelShift2x64Bit;
|
||||
}
|
||||
shift_right_unsigned! {
|
||||
"srd" 3, 4, 5;
|
||||
0x7c832c36;
|
||||
FunnelShift2x64Bit;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"sradi" 3, 4, 0;
|
||||
0x7c830674;
|
||||
ShiftSigned64;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"sradi" 3, 4, 5;
|
||||
0x7c832e74;
|
||||
ShiftSigned64;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"sradi" 3, 4, 16;
|
||||
0x7c838674;
|
||||
ShiftSigned64;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"sradi" 3, 4, 31;
|
||||
0x7c83fe74;
|
||||
ShiftSigned64;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"sradi" 3, 4, 32;
|
||||
0x7c830676;
|
||||
ShiftSigned64;
|
||||
}
|
||||
shift_right_signed_imm! {
|
||||
"sradi" 3, 4, 63;
|
||||
0x7c83fe76;
|
||||
ShiftSigned64;
|
||||
}
|
||||
shift_right_signed! {
|
||||
"srad" 3, 4, 5;
|
||||
0x7c832e34;
|
||||
ShiftSigned64;
|
||||
}
|
||||
// TODO: extswsli
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue