decoder/simple_power_isa: fix wires being used outside of the if they're declared in, also add TraceAsString

This commit is contained in:
Jacob Lifshay 2026-06-02 00:50:17 -07:00
parent 93e948115d
commit f5d8486d81
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
13 changed files with 4417 additions and 89644 deletions

View file

@ -142,7 +142,8 @@ struct DecodeState<'a> {
output: Expr<ArrayVec<TraceAsString<MOp>, ConstUsize<3>>>, output: Expr<ArrayVec<TraceAsString<MOp>, ConstUsize<3>>>,
is_illegal: Expr<Bool>, is_illegal: Expr<Bool>,
first_input: Expr<UInt<32>>, first_input: Expr<UInt<32>>,
second_input: Expr<HdlOption<UInt<32>>>, has_second_input: Expr<Bool>,
second_input_value: Expr<UInt<32>>,
second_input_used: Expr<Bool>, second_input_used: Expr<Bool>,
field_wires: &'a mut HashMap<String, HashMap<Expr<UInt>, Expr<UInt>>>, field_wires: &'a mut HashMap<String, HashMap<Expr<UInt>, Expr<UInt>>>,
} }
@ -429,10 +430,9 @@ impl DecodeState<'_> {
Entry::Occupied(entry) => *entry.get(), Entry::Occupied(entry) => *entry.get(),
} }
} }
#[hdl]
fn decode_word( fn decode_word(
&mut self, &mut self,
matches: &mut Expr<Bool>, matches: &mut Option<Expr<Bool>>,
fields: &mut BTreeMap<&'static str, Expr<UInt>>, fields: &mut BTreeMap<&'static str, Expr<UInt>>,
word: Expr<UInt<32>>, word: Expr<UInt<32>>,
fields_inner: &'static InstructionBitFieldsInner, fields_inner: &'static InstructionBitFieldsInner,
@ -525,7 +525,10 @@ impl DecodeState<'_> {
} }
} else { } else {
let value: u32 = name.parse().expect("bit field name must have at least one letter, be all `/`, or be a valid decimal number"); let value: u32 = name.parse().expect("bit field name must have at least one letter, be all `/`, or be a valid decimal number");
*matches = *matches & field.cmp_eq(value); *matches = match *matches {
Some(matches) => Some(matches & field.cmp_eq(value)),
None => Some(field.cmp_eq(value)),
};
if orig_name.contains(char::is_alphabetic) { if orig_name.contains(char::is_alphabetic) {
if fields if fields
.insert(orig_name, value.cast_to(field.ty()).to_expr()) .insert(orig_name, value.cast_to(field.ty()).to_expr())
@ -537,20 +540,19 @@ impl DecodeState<'_> {
} }
} }
} }
#[hdl]
#[track_caller] #[track_caller]
fn decode_scope<FS: FieldSet, F: FnOnce(&mut Self, FS)>(&mut self, f: F) { fn decode_scope<FS: FieldSet, F: FnOnce(&mut Self, FS)>(&mut self, f: F) {
let mut fields = BTreeMap::new(); let mut fields = BTreeMap::new();
let mut matches = true.to_expr();
let mut f = Some(f); let mut f = Some(f);
#[hdl] #[hdl]
#[track_caller] #[track_caller]
fn run<'a, FS: FieldSet, F: FnOnce(&mut DecodeState<'a>, FS)>( fn run<'a, FS: FieldSet, F: FnOnce(&mut DecodeState<'a>, FS)>(
this: &mut DecodeState<'a>, this: &mut DecodeState<'a>,
matches: Expr<Bool>, matches: Option<Expr<Bool>>,
fields: &mut BTreeMap<&str, Expr<UInt>>, fields: &mut BTreeMap<&str, Expr<UInt>>,
f: &mut Option<F>, f: &mut Option<F>,
) { ) {
let matches = matches.expect("matches is known to be Some");
#[hdl] #[hdl]
if matches { if matches {
connect( connect(
@ -562,23 +564,22 @@ impl DecodeState<'_> {
} }
} }
if let Some(prefix) = self.header.bit_fields().prefix() { if let Some(prefix) = self.header.bit_fields().prefix() {
#[hdl] let mut matches = Some(self.has_second_input);
if let HdlSome(suffix_word) = self.second_input { self.decode_word(
self.decode_word( &mut matches,
&mut matches, &mut fields,
&mut fields, self.first_input,
self.first_input, prefix.fields_inner(),
prefix.fields_inner(), );
); self.decode_word(
self.decode_word( &mut matches,
&mut matches, &mut fields,
&mut fields, self.second_input_value,
suffix_word, self.header.bit_fields().fields_inner(),
self.header.bit_fields().fields_inner(), );
); run(self, matches, &mut fields, &mut f);
run(self, matches, &mut fields, &mut f);
}
} else { } else {
let mut matches = None;
self.decode_word( self.decode_word(
&mut matches, &mut matches,
&mut fields, &mut fields,
@ -636,7 +637,7 @@ impl DecodeState<'_> {
let no_cr_bit = bo[4]; // BO_0 in specification let no_cr_bit = bo[4]; // BO_0 in specification
let (cr_field, condition_mode) = cr_bit_cond(bi); let (cr_field, condition_mode) = cr_bit_cond(bi);
#[hdl] #[hdl]
let branch_mop = wire(); let branch_mop: TraceAsString<MOp> = wire();
#[hdl] #[hdl]
let branch_lr_dest_reg = wire(); let branch_lr_dest_reg = wire();
connect(branch_lr_dest_reg, MOpRegNum::const_zero()); connect(branch_lr_dest_reg, MOpRegNum::const_zero());
@ -657,7 +658,7 @@ impl DecodeState<'_> {
#[hdl] #[hdl]
if no_ctr & no_cr_bit { if no_ctr & no_cr_bit {
connect( connect(
branch_mop, *branch_mop,
BranchMOp::branch_i( BranchMOp::branch_i(
dest, dest,
[MOpRegNum::const_zero(), src1], [MOpRegNum::const_zero(), src1],
@ -669,7 +670,7 @@ impl DecodeState<'_> {
); );
} else if no_cr_bit { } else if no_cr_bit {
connect( connect(
branch_mop, *branch_mop,
BranchMOp::branch_ctr( BranchMOp::branch_ctr(
dest, dest,
[MOpRegNum::const_zero(), src1, branch_ctr_reg], [MOpRegNum::const_zero(), src1, branch_ctr_reg],
@ -682,7 +683,7 @@ impl DecodeState<'_> {
); );
} else { } else {
connect( connect(
branch_mop, *branch_mop,
BranchMOp::branch_cond_ctr( BranchMOp::branch_cond_ctr(
dest, dest,
[cr_field, src1, branch_ctr_reg], [cr_field, src1, branch_ctr_reg],
@ -702,7 +703,7 @@ impl DecodeState<'_> {
ArrayVec::len(this.output), ArrayVec::len(this.output),
1usize.cast_to_static::<Length<_>>(), 1usize.cast_to_static::<Length<_>>(),
); );
connect(*this.output[0], branch_mop); connect(this.output[0], branch_mop);
connect(branch_ctr_reg, MOpRegNum::const_zero()); connect(branch_ctr_reg, MOpRegNum::const_zero());
} else { } else {
connect( connect(
@ -722,7 +723,7 @@ impl DecodeState<'_> {
false, false,
), ),
); );
connect(*this.output[1], branch_mop); connect(this.output[1], branch_mop);
connect(branch_ctr_reg, MOpRegNum::power_isa_ctr_reg()); connect(branch_ctr_reg, MOpRegNum::power_isa_ctr_reg());
} }
}; };
@ -2761,6 +2762,20 @@ pub fn decode_one_insn() {
connect(second_input_used, false); connect(second_input_used, false);
connect(is_illegal, true); connect(is_illegal, true);
#[hdl]
let has_second_input = wire();
#[hdl]
let second_input_value = wire();
#[hdl]
if let HdlSome(second_input) = second_input {
connect(has_second_input, true);
connect(second_input_value, second_input);
} else {
connect(has_second_input, false);
connect(second_input_value, 0u32);
}
let mut decode_fns = BTreeMap::new(); let mut decode_fns = BTreeMap::new();
for &(mnemonics, decode_fn) in DECODE_FNS { for &(mnemonics, decode_fn) in DECODE_FNS {
for &mnemonic in mnemonics { for &mnemonic in mnemonics {
@ -2810,7 +2825,8 @@ pub fn decode_one_insn() {
output, output,
is_illegal, is_illegal,
first_input, first_input,
second_input, has_second_input,
second_input_value,
second_input_used, second_input_used,
field_wires: &mut field_wires, field_wires: &mut field_wires,
}); });

File diff suppressed because it is too large Load diff

View file

@ -149,7 +149,7 @@ fn test_decode_insn() {
#[derive(Debug)] #[derive(Debug)]
#[expect(dead_code, reason = "used only for Debug formatting")] #[expect(dead_code, reason = "used only for Debug formatting")]
struct FormattedOutput<'a> { struct FormattedOutput<'a> {
insns: &'a [SimValue<MOp>], insns: &'a [SimValue<TraceAsString<MOp>>],
second_input_used: bool, second_input_used: bool,
is_illegal: bool, is_illegal: bool,
} }

View file

@ -16,14 +16,23 @@ mod fixed_point_store;
mod move_to_from_system_register; mod move_to_from_system_register;
mod prefixed_no_operation; mod prefixed_no_operation;
#[hdl(get(|_| 3))]
pub type TestCaseOutputLen<C: PhantomConstGet<()>> = DynSize;
pub struct TestCase { pub struct TestCase {
pub mnemonic: &'static str, pub mnemonic: &'static str,
pub first_input: u32, pub first_input: u32,
pub second_input: Option<u32>, pub second_input: Option<u32>,
pub output: SimValue<ArrayVec<MOp, ConstUsize<3>>>, pub output: SimValue<ArrayVec<TraceAsString<MOp>, TestCaseOutputLen<PhantomConst<()>>>>,
pub loc: &'static std::panic::Location<'static>, pub loc: &'static std::panic::Location<'static>,
} }
impl TestCase {
pub fn output_ty() -> ArrayVec<TraceAsString<MOp>, TestCaseOutputLen<PhantomConst<()>>> {
ArrayVec[TraceAsString[MOp]][TestCaseOutputLen[PhantomConst::default()]]
}
}
impl fmt::Debug for TestCase { impl fmt::Debug for TestCase {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { let Self {
@ -49,90 +58,91 @@ impl fmt::Debug for TestCase {
} }
} }
#[inline(never)] // prevent stack overflow
#[track_caller] #[track_caller]
fn insn_empty(mnemonic: &'static str, first_input: u32, second_input: Option<u32>) -> TestCase { fn insn_empty(mnemonic: &'static str, first_input: u32, second_input: Option<u32>) -> TestCase {
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width()) let zero_mop = UInt::new_dyn(MOp.canonical().bit_width())
.zero() .zero()
.cast_bits_to(MOp); .cast_bits_to(MOp)
.into_trace_as_string();
TestCase { TestCase {
mnemonic, mnemonic,
first_input, first_input,
second_input, second_input,
output: ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop), output: TestCase::output_ty().new_sim(zero_mop),
loc: std::panic::Location::caller(), loc: std::panic::Location::caller(),
} }
} }
#[inline(never)] // prevent stack overflow
#[track_caller] #[track_caller]
fn insn_single( fn insn_single<T: ToSimValue<Type = MOp>>(
mnemonic: &'static str, mnemonic: &'static str,
first_input: u32, first_input: u32,
second_input: Option<u32>, second_input: Option<u32>,
output: impl ToSimValue<Type = MOp>, // use a closure to avoid having too many variables in one function causing a stack overflow
output: impl FnOnce() -> T,
) -> TestCase { ) -> TestCase {
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width()) let mut retval = insn_empty(mnemonic, first_input, second_input);
.zero() ArrayVec::try_push_sim(
.cast_bits_to(MOp); &mut retval.output,
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop); output().into_sim_value().into_trace_as_string(),
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space"); )
ArrayVec::elements_sim_mut(&mut single_storage)[0] = output.to_sim_value(); .expect("known to have space");
TestCase { retval
mnemonic,
first_input,
second_input,
output: single_storage,
loc: std::panic::Location::caller(),
}
} }
#[inline(never)] // prevent stack overflow
#[track_caller] #[track_caller]
fn insn_double( fn insn_double<T: ToSimValue<Type = MOp>>(
mnemonic: &'static str, mnemonic: &'static str,
first_input: u32, first_input: u32,
second_input: Option<u32>, second_input: Option<u32>,
insns: [impl ToSimValue<Type = MOp>; 2], // use a closure to avoid having too many variables in one function causing a stack overflow
insns: impl FnOnce() -> [T; 2],
) -> TestCase { ) -> TestCase {
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width()) let mut retval = insn_empty(mnemonic, first_input, second_input);
.zero() let [insn0, insn1] = insns();
.cast_bits_to(MOp); ArrayVec::try_push_sim(
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop); &mut retval.output,
ArrayVec::try_push_sim(&mut single_storage, &zero_mop).expect("known to have space"); insn0.into_sim_value().into_trace_as_string(),
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space"); )
ArrayVec::elements_sim_mut(&mut single_storage)[0] = insns[0].to_sim_value(); .expect("known to have space");
ArrayVec::elements_sim_mut(&mut single_storage)[1] = insns[1].to_sim_value(); ArrayVec::try_push_sim(
TestCase { &mut retval.output,
mnemonic, insn1.into_sim_value().into_trace_as_string(),
first_input, )
second_input, .expect("known to have space");
output: single_storage, retval
loc: std::panic::Location::caller(),
}
} }
#[inline(never)] // prevent stack overflow
#[track_caller] #[track_caller]
fn insn_triple( fn insn_triple<T: ToSimValue<Type = MOp>>(
mnemonic: &'static str, mnemonic: &'static str,
first_input: u32, first_input: u32,
second_input: Option<u32>, second_input: Option<u32>,
insns: [impl ToSimValue<Type = MOp>; 3], // use a closure to avoid having too many variables in one function causing a stack overflow
insns: impl FnOnce() -> [T; 3],
) -> TestCase { ) -> TestCase {
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width()) let mut retval = insn_empty(mnemonic, first_input, second_input);
.zero() let [insn0, insn1, insn2] = insns();
.cast_bits_to(MOp); ArrayVec::try_push_sim(
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop); &mut retval.output,
ArrayVec::try_push_sim(&mut single_storage, &zero_mop).expect("known to have space"); insn0.into_sim_value().into_trace_as_string(),
ArrayVec::try_push_sim(&mut single_storage, &zero_mop).expect("known to have space"); )
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space"); .expect("known to have space");
ArrayVec::elements_sim_mut(&mut single_storage)[0] = insns[0].to_sim_value(); ArrayVec::try_push_sim(
ArrayVec::elements_sim_mut(&mut single_storage)[1] = insns[1].to_sim_value(); &mut retval.output,
ArrayVec::elements_sim_mut(&mut single_storage)[2] = insns[2].to_sim_value(); insn1.into_sim_value().into_trace_as_string(),
TestCase { )
mnemonic, .expect("known to have space");
first_input, ArrayVec::try_push_sim(
second_input, &mut retval.output,
output: single_storage, insn2.into_sim_value().into_trace_as_string(),
loc: std::panic::Location::caller(), )
} .expect("known to have space");
retval
} }
pub fn test_cases() -> Vec<TestCase> { pub fn test_cases() -> Vec<TestCase> {

View file

@ -9,10 +9,7 @@ use fayalite::prelude::*;
/// covers instructions in PowerISA v3.1C Book I 2.4 Branch Instructions /// covers instructions in PowerISA v3.1C Book I 2.4 Branch Instructions
pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) { pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
retval.push(insn_single( retval.push(insn_single("b 0x345678", 0x48345678, None, || {
"b 0x345678",
0x48345678,
None,
BranchMOp::branch_i( BranchMOp::branch_i(
MOpDestReg::new_sim(&[], &[]), MOpDestReg::new_sim(&[], &[]),
[MOpRegNum::const_zero(); 2], [MOpRegNum::const_zero(); 2],
@ -20,12 +17,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("ba 0x345678", 0x4834567a, None, || {
"ba 0x345678",
0x4834567a,
None,
BranchMOp::branch_i( BranchMOp::branch_i(
MOpDestReg::new_sim(&[], &[]), MOpDestReg::new_sim(&[], &[]),
[MOpRegNum::const_zero(); 2], [MOpRegNum::const_zero(); 2],
@ -33,12 +27,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
false, false,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("bl 0x345678", 0x48345679, None, || {
"bl 0x345678",
0x48345679,
None,
BranchMOp::branch_i( BranchMOp::branch_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]), MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
[MOpRegNum::const_zero(); 2], [MOpRegNum::const_zero(); 2],
@ -46,12 +37,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
true, true,
true, true,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("bla 0x345678", 0x4834567b, None, || {
"bla 0x345678",
0x4834567b,
None,
BranchMOp::branch_i( BranchMOp::branch_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]), MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
[MOpRegNum::const_zero(); 2], [MOpRegNum::const_zero(); 2],
@ -59,18 +47,15 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
false, false,
true, true,
false, false,
), )
)); }));
fn insn_dec_ctr_and( fn insn_dec_ctr_and<T: ToSimValue<Type = MOp>>(
mnemonic: &'static str, mnemonic: &'static str,
first_input: u32, first_input: u32,
second_input: Option<u32>, second_input: Option<u32>,
second_insn: impl ToSimValue<Type = MOp>, second_insn: impl FnOnce() -> T,
) -> TestCase { ) -> TestCase {
insn_double( insn_double(mnemonic, first_input, second_input, || {
mnemonic,
first_input,
second_input,
[ [
AddSubMOp::add_sub_i::<MOp>( AddSubMOp::add_sub_i::<MOp>(
MOpDestReg::new([MOpRegNum::power_isa_ctr_reg()], []), MOpDestReg::new([MOpRegNum::power_isa_ctr_reg()], []),
@ -83,9 +68,9 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
false, false,
) )
.into_sim_value(), .into_sim_value(),
second_insn.into_sim_value(), second_insn().into_sim_value(),
], ]
) })
} }
macro_rules! insn_branch_conds { macro_rules! insn_branch_conds {
( (
@ -137,255 +122,281 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " 0, 0, ", $asm_last_arg), concat!($mnemonic, " 0, 0, ", $asm_last_arg),
$encoding, $encoding,
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SLt(), true,
true, ConditionMode.SLt(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 0, 1, ", $asm_last_arg), concat!($mnemonic, " 0, 1, ", $asm_last_arg),
$encoding | 0x010000, $encoding | 0x010000,
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SGt(), true,
true, ConditionMode.SGt(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 0, 2, ", $asm_last_arg), concat!($mnemonic, " 0, 2, ", $asm_last_arg),
$encoding | 0x020000, $encoding | 0x020000,
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.Eq(), true,
true, ConditionMode.Eq(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 0, 3, ", $asm_last_arg), concat!($mnemonic, " 0, 3, ", $asm_last_arg),
$encoding | 0x030000, $encoding | 0x030000,
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.Overflow(), true,
true, ConditionMode.Overflow(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 0, 9, ", $asm_last_arg), concat!($mnemonic, " 0, 9, ", $asm_last_arg),
$encoding | 0x090000, $encoding | 0x090000,
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(2), [
$src1, MOpRegNum::power_isa_cr_reg_imm(2),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SGt(), true,
true, ConditionMode.SGt(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 2, 0, ", $asm_last_arg), concat!($mnemonic, " 2, 0, ", $asm_last_arg),
$encoding | (2 << 21), $encoding | (2 << 21),
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SLt(), true,
false, ConditionMode.SLt(),
$pc_relative, false,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
} }
retval.push(insn_single( retval.push(insn_single(
concat!($mnemonic, " 4, 0, ", $asm_last_arg), concat!($mnemonic, " 4, 0, ", $asm_last_arg),
$encoding | (4 << 21), $encoding | (4 << 21),
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::const_zero(), $src1,
], MOpRegNum::const_zero(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SLt(), true,
true, ConditionMode.SLt(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
if !$mnemonic.starts_with("bcctr") { if !$mnemonic.starts_with("bcctr") {
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 8, 0, ", $asm_last_arg), concat!($mnemonic, " 8, 0, ", $asm_last_arg),
$encoding | (8 << 21), $encoding | (8 << 21),
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
false, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SLt(), false,
true, ConditionMode.SLt(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 10, 0, ", $asm_last_arg), concat!($mnemonic, " 10, 0, ", $asm_last_arg),
$encoding | (10 << 21), $encoding | (10 << 21),
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
false, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SLt(), false,
false, ConditionMode.SLt(),
$pc_relative, false,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
} }
retval.push(insn_single( retval.push(insn_single(
concat!($mnemonic, " 12, 0, ", $asm_last_arg), concat!($mnemonic, " 12, 0, ", $asm_last_arg),
$encoding | (12 << 21), $encoding | (12 << 21),
None, None,
BranchMOp::branch_cond_ctr( || {
$dest, BranchMOp::branch_cond_ctr(
[ $dest,
MOpRegNum::power_isa_cr_reg_imm(0), [
$src1, MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::const_zero(), $src1,
], MOpRegNum::const_zero(),
$imm.cast_to_static::<SInt<_>>(), ],
false, $imm.cast_to_static::<SInt<_>>(),
ConditionMode.SLt(), false,
true, ConditionMode.SLt(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
if !$mnemonic.starts_with("bcctr") { if !$mnemonic.starts_with("bcctr") {
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 16, 0, ", $asm_last_arg), concat!($mnemonic, " 16, 0, ", $asm_last_arg),
$encoding | (16 << 21), $encoding | (16 << 21),
None, None,
BranchMOp::branch_ctr( || {
$dest, BranchMOp::branch_ctr(
[ $dest,
MOpRegNum::const_zero(), [
$src1, MOpRegNum::const_zero(),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
true, $imm.cast_to_static::<SInt<_>>(),
$pc_relative, true,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
retval.push(insn_dec_ctr_and( retval.push(insn_dec_ctr_and(
concat!($mnemonic, " 18, 0, ", $asm_last_arg), concat!($mnemonic, " 18, 0, ", $asm_last_arg),
$encoding | (18 << 21), $encoding | (18 << 21),
None, None,
BranchMOp::branch_ctr( || {
$dest, BranchMOp::branch_ctr(
[ $dest,
MOpRegNum::const_zero(), [
$src1, MOpRegNum::const_zero(),
MOpRegNum::power_isa_ctr_reg(), $src1,
], MOpRegNum::power_isa_ctr_reg(),
$imm.cast_to_static::<SInt<_>>(), ],
false, $imm.cast_to_static::<SInt<_>>(),
$pc_relative, false,
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
} }
retval.push(insn_single( retval.push(insn_single(
concat!($mnemonic, " 20, 0, ", $asm_last_arg), concat!($mnemonic, " 20, 0, ", $asm_last_arg),
$encoding | (20 << 21), $encoding | (20 << 21),
None, None,
BranchMOp::branch_i( || {
$dest, BranchMOp::branch_i(
[MOpRegNum::const_zero(), $src1], $dest,
$imm.cast_to_static::<SInt<_>>(), [MOpRegNum::const_zero(), $src1],
$pc_relative, $imm.cast_to_static::<SInt<_>>(),
$lk, $pc_relative,
$is_ret, $lk,
), $is_ret,
)
},
)); ));
}; };
} }
@ -435,18 +446,20 @@ pub fn test_cases_book_i_2_4_branch(retval: &mut Vec<TestCase>) {
".long 0x4e400461 # bctarl 18, 0, 0", ".long 0x4e400461 # bctarl 18, 0, 0",
0x4e400461, 0x4e400461,
None, None,
BranchMOp::branch_ctr( || {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]), BranchMOp::branch_ctr(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
MOpRegNum::const_zero(), [
MOpRegNum::power_isa_tar_reg(), MOpRegNum::const_zero(),
MOpRegNum::power_isa_ctr_reg(), MOpRegNum::power_isa_tar_reg(),
], MOpRegNum::power_isa_ctr_reg(),
0.cast_to_static::<SInt<_>>(), ],
false, 0.cast_to_static::<SInt<_>>(),
false, false,
true, false,
false, true,
), false,
)
},
)); ));
} }

View file

@ -20,58 +20,70 @@ pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " 4*cr3+so, 4*cr1+gt, 4*cr5+lt"), concat!($mnemonic, " 4*cr3+so, 4*cr1+gt, 4*cr5+lt"),
$encoding | 0x01e5a000, $encoding | 0x01e5a000,
None, None,
LogicalFlagsMOp::logical_flags( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), LogicalFlagsMOp::logical_flags(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
MOpRegNum::power_isa_cr_reg_imm(1), [
MOpRegNum::power_isa_cr_reg_imm(5), MOpRegNum::power_isa_cr_reg_imm(1),
MOpRegNum::power_isa_cr_reg_imm(3), MOpRegNum::power_isa_cr_reg_imm(5),
], MOpRegNum::power_isa_cr_reg_imm(3),
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| { ],
let mut dest = src2.map(|v| Some(v.into())); LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(
dest.so = Some((src0.cr_gt, src1.cr_lt).into()); |src0, src1, src2| {
dest let mut dest = src2.map(|v| Some(v.into()));
}), dest.so = Some((src0.cr_gt, src1.cr_lt).into());
$lut, dest
), },
),
$lut,
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!($mnemonic, " lt, gt, eq"), concat!($mnemonic, " lt, gt, eq"),
$encoding | 0x00011000, $encoding | 0x00011000,
None, None,
LogicalFlagsMOp::logical_flags( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]), LogicalFlagsMOp::logical_flags(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]),
MOpRegNum::power_isa_cr_reg_imm(0), [
MOpRegNum::power_isa_cr_reg_imm(0), MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_cr_reg_imm(0), MOpRegNum::power_isa_cr_reg_imm(0),
], MOpRegNum::power_isa_cr_reg_imm(0),
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| { ],
let mut dest = src2.map(|v| Some(v.into())); LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(
dest.cr_lt = Some((src0.cr_gt, src1.cr_eq).into()); |src0, src1, src2| {
dest let mut dest = src2.map(|v| Some(v.into()));
}), dest.cr_lt = Some((src0.cr_gt, src1.cr_eq).into());
$lut, dest
), },
),
$lut,
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!($mnemonic, " gt, gt, eq"), concat!($mnemonic, " gt, gt, eq"),
$encoding | 0x00211000, $encoding | 0x00211000,
None, None,
LogicalFlagsMOp::logical_flags( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]), LogicalFlagsMOp::logical_flags(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]),
MOpRegNum::power_isa_cr_reg_imm(0), [
MOpRegNum::power_isa_cr_reg_imm(0), MOpRegNum::power_isa_cr_reg_imm(0),
MOpRegNum::power_isa_cr_reg_imm(0), MOpRegNum::power_isa_cr_reg_imm(0),
], MOpRegNum::power_isa_cr_reg_imm(0),
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| { ],
let mut dest = src2.map(|v| Some(v.into())); LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(
dest.cr_gt = Some((src0.cr_gt, src1.cr_eq).into()); |src0, src1, src2| {
dest let mut dest = src2.map(|v| Some(v.into()));
}), dest.cr_gt = Some((src0.cr_gt, src1.cr_eq).into());
$lut, dest
), },
),
$lut,
)
},
)); ));
}}; }};
} }
@ -89,11 +101,13 @@ pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
concat!("mcrf ", $dest, ", ", $src), concat!("mcrf ", $dest, ", ", $src),
$encoding, $encoding,
None, None,
MoveRegMOp::move_reg( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num($dest)], &[]), MoveRegMOp::move_reg(
[MOpRegNum::power_isa_cr_reg_imm($src)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num($dest)], &[]),
0i8.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_cr_reg_imm($src)],
), 0i8.cast_to_static::<SInt<_>>(),
)
},
)); ));
}; };
} }

View file

@ -7,10 +7,7 @@ use fayalite::prelude::*;
/// covers instructions in PowerISA v3.1C Book I 3.3.9 Fixed-Point Arithmetic Instructions /// covers instructions in PowerISA v3.1C Book I 3.3.9 Fixed-Point Arithmetic Instructions
pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>) { pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>) {
retval.push(insn_single( retval.push(insn_single("addi 3, 4, 0x1234", 0x38641234, None, || {
"addi 3, 4, 0x1234",
0x38641234,
None,
AddSubMOp::add_sub_i( AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()], [MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
@ -20,42 +17,43 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single(
"paddi 3, 4, 0x123456789, 0", "paddi 3, 4, 0x123456789, 0",
0x06012345, 0x06012345,
Some(0x38646789), Some(0x38646789),
AddSubMOp::add_sub_i( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), AddSubMOp::add_sub_i(
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
0x123456789i64.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
OutputIntegerMode.Full64(), 0x123456789i64.cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
"paddi 3, 0, 0x123456789, 1", "paddi 3, 0, 0x123456789, 1",
0x06112345, 0x06112345,
Some(0x38606789), Some(0x38606789),
AddSubMOp::add_sub_i( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), AddSubMOp::add_sub_i(
[MOpRegNum::const_zero(), MOpRegNum::const_zero()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
0x123456789i64.cast_to_static::<SInt<_>>(), [MOpRegNum::const_zero(), MOpRegNum::const_zero()],
OutputIntegerMode.Full64(), 0x123456789i64.cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
true, false,
), true,
)
},
)); ));
retval.push(insn_single( retval.push(insn_single("addis 3, 4, 0x1234", 0x3C641234, None, || {
"addis 3, 4, 0x1234",
0x3C641234,
None,
AddSubMOp::add_sub_i( AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()], [MOpRegNum::power_isa_gpr_reg_imm(4), MOpRegNum::const_zero()],
@ -65,12 +63,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("addpcis 3, 0x1234", 0x4c7a1204, None, || {
"addpcis 3, 0x1234",
0x4c7a1204,
None,
AddSubMOp::add_sub_i( AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::const_zero(); _], [MOpRegNum::const_zero(); _],
@ -80,12 +75,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
false, false,
true, true,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("add. 3, 4, 5", 0x7c642a15, None, || {
"add. 3, 4, 5",
0x7c642a15,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[MOpRegNum::power_isa_gpr_reg_num(3)], &[MOpRegNum::power_isa_gpr_reg_num(3)],
@ -102,12 +94,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("addic. 3, 4, 0x1234", 0x34641234, None, || {
"addic. 3, 4, 0x1234",
0x34641234,
None,
AddSubMOp::add_sub_i( AddSubMOp::add_sub_i(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -123,12 +112,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("subf. 3, 4, 5", 0x7c642851, None, || {
"subf. 3, 4, 5",
0x7c642851,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[MOpRegNum::power_isa_gpr_reg_num(3)], &[MOpRegNum::power_isa_gpr_reg_num(3)],
@ -145,12 +131,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
true, true,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("subfic 3, 4, 0x1234", 0x20641234, None, || {
"subfic 3, 4, 0x1234",
0x20641234,
None,
AddSubMOp::add_sub_i( AddSubMOp::add_sub_i(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -166,12 +149,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
true, true,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("addc. 3, 4, 5", 0x7c642815, None, || {
"addc. 3, 4, 5",
0x7c642815,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -191,12 +171,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("subfc. 3, 4, 5", 0x7c642811, None, || {
"subfc. 3, 4, 5",
0x7c642811,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -216,12 +193,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
true, true,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("adde. 3, 4, 5", 0x7c642915, None, || {
"adde. 3, 4, 5",
0x7c642915,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -241,12 +215,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("subfe. 3, 4, 5", 0x7c642911, None, || {
"subfe. 3, 4, 5",
0x7c642911,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -266,12 +237,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("addme. 3, 4", 0x7c6401d5, None, || {
"addme. 3, 4",
0x7c6401d5,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -291,12 +259,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("subfme. 3, 4", 0x7c6401d1, None, || {
"subfme. 3, 4",
0x7c6401d1,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -316,12 +281,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("addze. 3, 4", 0x7c640195, None, || {
"addze. 3, 4",
0x7c640195,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -341,12 +303,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("subfze. 3, 4", 0x7c640191, None, || {
"subfze. 3, 4",
0x7c640191,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[ &[
@ -366,12 +325,9 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
true, true,
false, false,
false, false,
), )
)); }));
retval.push(insn_single( retval.push(insn_single("neg. 3, 4", 0x7c6400d1, None, || {
"neg. 3, 4",
0x7c6400d1,
None,
AddSubMOp::add_sub( AddSubMOp::add_sub(
MOpDestReg::new_sim( MOpDestReg::new_sim(
&[MOpRegNum::power_isa_gpr_reg_num(3)], &[MOpRegNum::power_isa_gpr_reg_num(3)],
@ -388,6 +344,6 @@ pub fn test_cases_book_i_3_3_9_fixed_point_arithmetic(retval: &mut Vec<TestCase>
false, false,
true, true,
false, false,
), )
)); }));
} }

View file

@ -11,28 +11,29 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
"cmpi 3, 0, 4, 0x1234", "cmpi 3, 0, 4, 0x1234",
0x2d841234, 0x2d841234,
None, None,
CompareMOp::compare_i( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), CompareMOp::compare_i(
[MOpRegNum::power_isa_gpr_reg_imm(4)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
0x1234.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(4)],
CompareMode.S32(), 0x1234.cast_to_static::<SInt<_>>(),
), CompareMode.S32(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
"cmpi 3, 1, 4, -0x7655", "cmpi 3, 1, 4, -0x7655",
0x2da489ab, 0x2da489ab,
None, None,
CompareMOp::compare_i( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), CompareMOp::compare_i(
[MOpRegNum::power_isa_gpr_reg_imm(4)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
(0x89abu16 as i16).cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(4)],
CompareMode.S64(), (0x89abu16 as i16).cast_to_static::<SInt<_>>(),
), CompareMode.S64(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single("cmp 3, 0, 4, 5", 0x7d842800, None, || {
"cmp 3, 0, 4, 5",
0x7d842800,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -40,12 +41,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.S32(), CompareMode.S32(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("cmp 3, 1, 4, 5", 0x7da42800, None, || {
"cmp 3, 1, 4, 5",
0x7da42800,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -53,34 +51,35 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.S64(), CompareMode.S64(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single(
"cmpli 3, 0, 4, 0x1234", "cmpli 3, 0, 4, 0x1234",
0x29841234, 0x29841234,
None, None,
CompareMOp::compare_i( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), CompareMOp::compare_i(
[MOpRegNum::power_isa_gpr_reg_imm(4)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
0x1234.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(4)],
CompareMode.U32(), 0x1234.cast_to_static::<SInt<_>>(),
), CompareMode.U32(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
"cmpli 3, 1, 4, 0x89ab", "cmpli 3, 1, 4, 0x89ab",
0x29a489ab, 0x29a489ab,
None, None,
CompareMOp::compare_i( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), CompareMOp::compare_i(
[MOpRegNum::power_isa_gpr_reg_imm(4)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
0x89ab.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(4)],
CompareMode.U64(), 0x89ab.cast_to_static::<SInt<_>>(),
), CompareMode.U64(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single("cmpl 3, 0, 4, 5", 0x7d842840, None, || {
"cmpl 3, 0, 4, 5",
0x7d842840,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -88,12 +87,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.U32(), CompareMode.U32(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("cmpl 3, 1, 4, 5", 0x7da42840, None, || {
"cmpl 3, 1, 4, 5",
0x7da42840,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -101,12 +97,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.U64(), CompareMode.U64(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("cmprb 3, 0, 4, 5", 0x7d842980, None, || {
"cmprb 3, 0, 4, 5",
0x7d842980,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -114,12 +107,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.CmpRBOne(), CompareMode.CmpRBOne(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("cmprb 3, 1, 4, 5", 0x7da42980, None, || {
"cmprb 3, 1, 4, 5",
0x7da42980,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -127,12 +117,9 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.CmpRBTwo(), CompareMode.CmpRBTwo(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("cmpeqb 3, 4, 5", 0x7d8429c0, None, || {
"cmpeqb 3, 4, 5",
0x7d8429c0,
None,
CompareMOp::compare( CompareMOp::compare(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -140,6 +127,6 @@ pub fn test_cases_book_i_3_3_10_fixed_point_compare(retval: &mut Vec<TestCase>)
MOpRegNum::power_isa_gpr_reg_imm(5), MOpRegNum::power_isa_gpr_reg_imm(5),
], ],
CompareMode.CmpEqB(), CompareMode.CmpEqB(),
), )
)); }));
} }

View file

@ -21,31 +21,33 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $dest, ", ", $disp, "(", $ra, "), ", $r), concat!($mnemonic, " ", $dest, ", ", $disp, "(", $ra, "), ", $r),
$prefix, $prefix,
Some($suffix), Some($suffix),
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
if $r != 0 || $ra == 0 { [
MOpRegNum::const_zero() if $r != 0 || $ra == 0 {
} else { MOpRegNum::const_zero()
MOpRegNum::power_isa_gpr_reg_imm($ra) } else {
}, MOpRegNum::power_isa_gpr_reg_imm($ra)
MOpRegNum::const_zero(), },
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
$r != 0, false,
), $r != 0,
LoadMOp::load( ),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), LoadMOp::load(
[MOpRegNum::power_isa_temp_reg()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
LoadStoreWidth.$width(), [MOpRegNum::power_isa_temp_reg()],
LoadStoreConversion.$conversion(), LoadStoreWidth.$width(),
), LoadStoreConversion.$conversion(),
], ),
]
},
)); ));
}; };
} }
@ -60,31 +62,33 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $dest, ", ", $disp, "(", $ra, ")"), concat!($mnemonic, " ", $dest, ", ", $disp, "(", $ra, ")"),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
if $ra == 0 { [
MOpRegNum::const_zero() if $ra == 0 {
} else { MOpRegNum::const_zero()
MOpRegNum::power_isa_gpr_reg_imm($ra) } else {
}, MOpRegNum::power_isa_gpr_reg_imm($ra)
MOpRegNum::const_zero(), },
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
LoadMOp::load( ),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), LoadMOp::load(
[MOpRegNum::power_isa_temp_reg()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
LoadStoreWidth.$width(), [MOpRegNum::power_isa_temp_reg()],
LoadStoreConversion.$conversion(), LoadStoreWidth.$width(),
), LoadStoreConversion.$conversion(),
], ),
]
},
)); ));
}; };
} }
@ -99,27 +103,29 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $dest, ", ", $disp, "(", $ra, ")"), concat!($mnemonic, " ", $dest, ", ", $disp, "(", $ra, ")"),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
MOpRegNum::power_isa_gpr_reg_imm($ra), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($ra),
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
LoadMOp::load( ),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), LoadMOp::load(
[MOpRegNum::power_isa_gpr_reg_imm($ra)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
LoadStoreWidth.$width(), [MOpRegNum::power_isa_gpr_reg_imm($ra)],
LoadStoreConversion.$conversion(), LoadStoreWidth.$width(),
), LoadStoreConversion.$conversion(),
], ),
]
},
)); ));
}; };
} }
@ -134,31 +140,33 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $dest, ", ", $ra, ", ", $rb), concat!($mnemonic, " ", $dest, ", ", $ra, ", ", $rb),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
if $ra == 0 { [
MOpRegNum::const_zero() if $ra == 0 {
} else { MOpRegNum::const_zero()
MOpRegNum::power_isa_gpr_reg_imm($ra) } else {
}, MOpRegNum::power_isa_gpr_reg_imm($ra)
MOpRegNum::power_isa_gpr_reg_imm($rb), },
], MOpRegNum::power_isa_gpr_reg_imm($rb),
0.cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), 0.cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
LoadMOp::load( ),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), LoadMOp::load(
[MOpRegNum::power_isa_temp_reg()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
LoadStoreWidth.$width(), [MOpRegNum::power_isa_temp_reg()],
LoadStoreConversion.$conversion(), LoadStoreWidth.$width(),
), LoadStoreConversion.$conversion(),
], ),
]
},
)); ));
}; };
} }
@ -173,27 +181,29 @@ pub fn test_cases_book_i_3_3_2_fixed_point_load(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $dest, ", ", $ra, ", ", $rb), concat!($mnemonic, " ", $dest, ", ", $ra, ", ", $rb),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
MOpRegNum::power_isa_gpr_reg_imm($ra), [
MOpRegNum::power_isa_gpr_reg_imm($rb), MOpRegNum::power_isa_gpr_reg_imm($ra),
], MOpRegNum::power_isa_gpr_reg_imm($rb),
0.cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), 0.cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
LoadMOp::load( ),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), LoadMOp::load(
[MOpRegNum::power_isa_gpr_reg_imm($ra)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
LoadStoreWidth.$width(), [MOpRegNum::power_isa_gpr_reg_imm($ra)],
LoadStoreConversion.$conversion(), LoadStoreWidth.$width(),
), LoadStoreConversion.$conversion(),
], ),
]
},
)); ));
}; };
} }

View file

@ -25,21 +25,23 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
), ),
$encoding, $encoding,
None, None,
LogicalMOp::logical_i( || {
MOpDestReg::new_sim( LogicalMOp::logical_i(
&[MOpRegNum::power_isa_gpr_reg_num($dest)], MOpDestReg::new_sim(
if $mnemonic.contains('.') { &[MOpRegNum::power_isa_gpr_reg_num($dest)],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM] if $mnemonic.contains('.') {
} else { &[MOpRegNum::POWER_ISA_CR_0_REG_NUM]
&[] } else {
}, &[]
), },
[MOpRegNum::power_isa_gpr_reg_imm($src)], ),
(($imm as u32) << if $mnemonic.contains('s') { 16 } else { 0 }) [MOpRegNum::power_isa_gpr_reg_imm($src)],
.cast_to_static::<SInt<_>>(), (($imm as u32) << if $mnemonic.contains('s') { 16 } else { 0 })
OutputIntegerMode.Full64(), .cast_to_static::<SInt<_>>(),
Lut4::from_fn(|$a, $b| $lut_fn), OutputIntegerMode.Full64(),
), Lut4::from_fn(|$a, $b| $lut_fn),
)
},
)); ));
}; };
} }
@ -98,23 +100,25 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
), ),
$encoding, $encoding,
None, None,
LogicalMOp::logical( || {
MOpDestReg::new_sim( LogicalMOp::logical(
&[MOpRegNum::power_isa_gpr_reg_num($dest)], MOpDestReg::new_sim(
if $mnemonic.contains('.') { &[MOpRegNum::power_isa_gpr_reg_num($dest)],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM] if $mnemonic.contains('.') {
} else { &[MOpRegNum::POWER_ISA_CR_0_REG_NUM]
&[] } else {
}, &[]
), },
[ ),
MOpRegNum::power_isa_gpr_reg_imm($src0), [
MOpRegNum::power_isa_gpr_reg_imm($src1), MOpRegNum::power_isa_gpr_reg_imm($src0),
], MOpRegNum::power_isa_gpr_reg_imm($src1),
0.cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), 0.cast_to_static::<SInt<_>>(),
Lut4::from_fn(|$a, $b| $lut_fn), OutputIntegerMode.Full64(),
), Lut4::from_fn(|$a, $b| $lut_fn),
)
},
)); ));
}; };
} }
@ -157,11 +161,13 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
"or 3, 4, 4", // mr 3, 4 "or 3, 4, 4", // mr 3, 4
0x7c832378, 0x7c832378,
None, None,
MoveRegMOp::move_reg( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MoveRegMOp::move_reg(
[MOpRegNum::power_isa_gpr_reg_imm(4)], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
0.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(4)],
), 0.cast_to_static::<SInt<_>>(),
)
},
)); ));
insn_logic! { insn_logic! {
"or." 3, 4, 5; "or." 3, 4, 5;
@ -223,20 +229,22 @@ pub fn test_cases_book_i_3_3_13_fixed_point_logical(retval: &mut Vec<TestCase>)
concat!($mnemonic, " ", stringify!($dest), ", ", stringify!($src)), concat!($mnemonic, " ", stringify!($dest), ", ", stringify!($src)),
$encoding, $encoding,
None, None,
LogicalMOp::logical_i( || {
MOpDestReg::new_sim( LogicalMOp::logical_i(
&[MOpRegNum::power_isa_gpr_reg_num($dest)], MOpDestReg::new_sim(
if $mnemonic.contains('.') { &[MOpRegNum::power_isa_gpr_reg_num($dest)],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM] if $mnemonic.contains('.') {
} else { &[MOpRegNum::POWER_ISA_CR_0_REG_NUM]
&[] } else {
}, &[]
), },
[MOpRegNum::power_isa_gpr_reg_imm($src)], ),
0.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm($src)],
OutputIntegerMode.$OutputIntegerMode(), 0.cast_to_static::<SInt<_>>(),
Lut4::from_fn(|a, b| a | b), OutputIntegerMode.$OutputIntegerMode(),
), Lut4::from_fn(|a, b| a | b),
)
},
)); ));
}; };
} }

View file

@ -105,7 +105,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[ [
MOpRegNum::power_isa_gpr_reg_imm($src), MOpRegNum::power_isa_gpr_reg_imm($src),
@ -131,7 +131,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],),
[ [
MOpRegNum::power_isa_gpr_reg_imm($src), MOpRegNum::power_isa_gpr_reg_imm($src),
@ -168,7 +168,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
[ [
MOpRegNum::power_isa_gpr_reg_imm($src), MOpRegNum::power_isa_gpr_reg_imm($src),
@ -199,7 +199,7 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || ShiftRotateMOp::shift_rotate(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],),
[ [
MOpRegNum::power_isa_gpr_reg_imm($src), MOpRegNum::power_isa_gpr_reg_imm($src),
@ -855,21 +855,23 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), ShiftRotateMOp::shift_rotate(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
MOpRegNum::power_isa_gpr_reg_imm($src), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount), MOpRegNum::const_zero(),
], MOpRegNum::power_isa_gpr_reg_imm($amount),
shift_imm( ],
None, shift_imm(
false, None,
ShiftAmountOverflowBehavior.$overflow_behavior(), false,
), ShiftAmountOverflowBehavior.$overflow_behavior(),
OutputIntegerMode.Full64(), ),
ShiftRotateMode.$shift_rotate_mode(), OutputIntegerMode.Full64(),
), ShiftRotateMode.$shift_rotate_mode(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!( concat!(
@ -883,24 +885,26 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( ShiftRotateMOp::shift_rotate(
&[MOpRegNum::power_isa_gpr_reg_num($dest)], MOpDestReg::new_sim(
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM], &[MOpRegNum::power_isa_gpr_reg_num($dest)],
), &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
[ ),
MOpRegNum::power_isa_gpr_reg_imm($src), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::power_isa_gpr_reg_imm($amount), MOpRegNum::const_zero(),
], MOpRegNum::power_isa_gpr_reg_imm($amount),
shift_imm( ],
None, shift_imm(
false, None,
ShiftAmountOverflowBehavior.$overflow_behavior(), false,
), ShiftAmountOverflowBehavior.$overflow_behavior(),
OutputIntegerMode.Full64(), ),
ShiftRotateMode.$shift_rotate_mode(), OutputIntegerMode.Full64(),
), ShiftRotateMode.$shift_rotate_mode(),
)
},
)); ));
}}; }};
} }
@ -923,17 +927,19 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), ShiftRotateMOp::shift_rotate(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
MOpRegNum::const_zero(), [
MOpRegNum::power_isa_gpr_reg_imm($src), MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount), MOpRegNum::power_isa_gpr_reg_imm($src),
], MOpRegNum::power_isa_gpr_reg_imm($amount),
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()), ],
OutputIntegerMode.Full64(), shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
ShiftRotateMode.$shift_rotate_mode(), OutputIntegerMode.Full64(),
), ShiftRotateMode.$shift_rotate_mode(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!( concat!(
@ -947,20 +953,22 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( ShiftRotateMOp::shift_rotate(
&[MOpRegNum::power_isa_gpr_reg_num($dest)], MOpDestReg::new_sim(
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM], &[MOpRegNum::power_isa_gpr_reg_num($dest)],
), &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
[ ),
MOpRegNum::const_zero(), [
MOpRegNum::power_isa_gpr_reg_imm($src), MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount), MOpRegNum::power_isa_gpr_reg_imm($src),
], MOpRegNum::power_isa_gpr_reg_imm($amount),
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()), ],
OutputIntegerMode.Full64(), shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
ShiftRotateMode.$shift_rotate_mode(), OutputIntegerMode.Full64(),
), ShiftRotateMode.$shift_rotate_mode(),
)
},
)); ));
}}; }};
} }
@ -983,23 +991,25 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( 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_num($dest),
MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM,
],
&[],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
], ],
&[], shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
), OutputIntegerMode.Full64(),
[ ShiftRotateMode.$shift_rotate_mode(),
MOpRegNum::power_isa_gpr_reg_imm($src), )
MOpRegNum::const_zero(), },
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!( concat!(
@ -1013,23 +1023,25 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( 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_num($dest),
MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM,
],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::power_isa_gpr_reg_imm($amount),
], ],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM], shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
), OutputIntegerMode.Full64(),
[ ShiftRotateMode.$shift_rotate_mode(),
MOpRegNum::power_isa_gpr_reg_imm($src), )
MOpRegNum::const_zero(), },
MOpRegNum::power_isa_gpr_reg_imm($amount),
],
shift_imm(None, true, ShiftAmountOverflowBehavior.$overflow_behavior()),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
)); ));
}}; }};
} }
@ -1051,27 +1063,29 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( 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_num($dest),
MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM,
],
&[],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
], ],
&[], shift_imm(
), Some($amount),
[ true,
MOpRegNum::power_isa_gpr_reg_imm($src), ShiftAmountOverflowBehavior.WrapToUInt6(),
MOpRegNum::const_zero(), ),
MOpRegNum::const_zero(), OutputIntegerMode.Full64(),
], ShiftRotateMode.$shift_rotate_mode(),
shift_imm( )
Some($amount), },
true,
ShiftAmountOverflowBehavior.WrapToUInt6(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!( concat!(
@ -1085,27 +1099,29 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( 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_num($dest),
MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM,
],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
),
[
MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(),
MOpRegNum::const_zero(),
], ],
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM], shift_imm(
), Some($amount),
[ true,
MOpRegNum::power_isa_gpr_reg_imm($src), ShiftAmountOverflowBehavior.WrapToUInt6(),
MOpRegNum::const_zero(), ),
MOpRegNum::const_zero(), OutputIntegerMode.Full64(),
], ShiftRotateMode.$shift_rotate_mode(),
shift_imm( )
Some($amount), },
true,
ShiftAmountOverflowBehavior.WrapToUInt6(),
),
OutputIntegerMode.Full64(),
ShiftRotateMode.$shift_rotate_mode(),
),
)); ));
}}; }};
} }
@ -1212,21 +1228,23 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding, $encoding,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]), ShiftRotateMOp::shift_rotate(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($dest)], &[]),
MOpRegNum::power_isa_gpr_reg_imm($src), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(), MOpRegNum::const_zero(),
], MOpRegNum::const_zero(),
shift_imm( ],
Some($amount), shift_imm(
false, Some($amount),
ShiftAmountOverflowBehavior.WrapToUInt6(), false,
), ShiftAmountOverflowBehavior.WrapToUInt6(),
OutputIntegerMode.Full64(), ),
ShiftRotateMode.SignExt32To64BitThenShift(), OutputIntegerMode.Full64(),
), ShiftRotateMode.SignExt32To64BitThenShift(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
concat!( concat!(
@ -1240,24 +1258,26 @@ pub fn test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(retval: &mut Vec<Te
), ),
$encoding | 1, $encoding | 1,
None, None,
ShiftRotateMOp::shift_rotate( || {
MOpDestReg::new_sim( ShiftRotateMOp::shift_rotate(
&[MOpRegNum::power_isa_gpr_reg_num($dest)], MOpDestReg::new_sim(
&[MOpRegNum::POWER_ISA_CR_0_REG_NUM], &[MOpRegNum::power_isa_gpr_reg_num($dest)],
), &[MOpRegNum::POWER_ISA_CR_0_REG_NUM],
[ ),
MOpRegNum::power_isa_gpr_reg_imm($src), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($src),
MOpRegNum::const_zero(), MOpRegNum::const_zero(),
], MOpRegNum::const_zero(),
shift_imm( ],
Some($amount), shift_imm(
false, Some($amount),
ShiftAmountOverflowBehavior.WrapToUInt6(), false,
), ShiftAmountOverflowBehavior.WrapToUInt6(),
OutputIntegerMode.Full64(), ),
ShiftRotateMode.SignExt32To64BitThenShift(), OutputIntegerMode.Full64(),
), ShiftRotateMode.SignExt32To64BitThenShift(),
)
},
)); ));
}}; }};
} }

View file

@ -20,34 +20,36 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, "), ", $r), concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, "), ", $r),
$prefix, $prefix,
Some($suffix), Some($suffix),
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
if $r != 0 || $ra == 0 { [
MOpRegNum::const_zero() if $r != 0 || $ra == 0 {
} else { MOpRegNum::const_zero()
MOpRegNum::power_isa_gpr_reg_imm($ra) } else {
}, MOpRegNum::power_isa_gpr_reg_imm($ra)
MOpRegNum::const_zero(), },
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
$r != 0, false,
), $r != 0,
StoreMOp::store( ),
MOpDestReg::new_sim(&[], &[]), StoreMOp::store(
[ MOpDestReg::new_sim(&[], &[]),
MOpRegNum::power_isa_temp_reg(), [
MOpRegNum::power_isa_gpr_reg_imm($rs), MOpRegNum::power_isa_temp_reg(),
], MOpRegNum::power_isa_gpr_reg_imm($rs),
LoadStoreWidth.$width(), ],
LoadStoreConversion.ZeroExt(), LoadStoreWidth.$width(),
), LoadStoreConversion.ZeroExt(),
], ),
]
},
)); ));
}; };
} }
@ -61,34 +63,36 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, ")"), concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, ")"),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
if $ra == 0 { [
MOpRegNum::const_zero() if $ra == 0 {
} else { MOpRegNum::const_zero()
MOpRegNum::power_isa_gpr_reg_imm($ra) } else {
}, MOpRegNum::power_isa_gpr_reg_imm($ra)
MOpRegNum::const_zero(), },
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
StoreMOp::store( ),
MOpDestReg::new_sim(&[], &[]), StoreMOp::store(
[ MOpDestReg::new_sim(&[], &[]),
MOpRegNum::power_isa_temp_reg(), [
MOpRegNum::power_isa_gpr_reg_imm($rs), MOpRegNum::power_isa_temp_reg(),
], MOpRegNum::power_isa_gpr_reg_imm($rs),
LoadStoreWidth.$width(), ],
LoadStoreConversion.ZeroExt(), LoadStoreWidth.$width(),
), LoadStoreConversion.ZeroExt(),
], ),
]
},
)); ));
}; };
} }
@ -103,65 +107,69 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, ")"), concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, ")"),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
MOpRegNum::power_isa_gpr_reg_imm($ra), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($ra),
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
StoreMOp::store( ),
MOpDestReg::new_sim(&[], &[]), StoreMOp::store(
[ MOpDestReg::new_sim(&[], &[]),
MOpRegNum::power_isa_temp_reg(), [
MOpRegNum::power_isa_gpr_reg_imm($rs), MOpRegNum::power_isa_temp_reg(),
], MOpRegNum::power_isa_gpr_reg_imm($rs),
LoadStoreWidth.$width(), ],
LoadStoreConversion.ZeroExt(), LoadStoreWidth.$width(),
), LoadStoreConversion.ZeroExt(),
MoveRegMOp::move_reg( ),
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]), MoveRegMOp::move_reg(
[MOpRegNum::power_isa_temp_reg()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
0.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_temp_reg()],
), 0.cast_to_static::<SInt<_>>(),
], ),
]
},
)); ));
} else { } else {
retval.push(insn_double( retval.push(insn_double(
concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, ")"), concat!($mnemonic, " ", $rs, ", ", $disp, "(", $ra, ")"),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i( [
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]), AddSubMOp::add_sub_i(
[ MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
MOpRegNum::power_isa_gpr_reg_imm($ra), [
MOpRegNum::const_zero(), MOpRegNum::power_isa_gpr_reg_imm($ra),
], MOpRegNum::const_zero(),
($disp as i64).cast_to_static::<SInt<_>>(), ],
OutputIntegerMode.Full64(), ($disp as i64).cast_to_static::<SInt<_>>(),
false, OutputIntegerMode.Full64(),
false, false,
false, false,
false, false,
), false,
StoreMOp::store( ),
MOpDestReg::new_sim(&[], &[]), StoreMOp::store(
[ MOpDestReg::new_sim(&[], &[]),
MOpRegNum::power_isa_gpr_reg_imm($ra), [
MOpRegNum::power_isa_gpr_reg_imm($rs), MOpRegNum::power_isa_gpr_reg_imm($ra),
], MOpRegNum::power_isa_gpr_reg_imm($rs),
LoadStoreWidth.$width(), ],
LoadStoreConversion.ZeroExt(), LoadStoreWidth.$width(),
), LoadStoreConversion.ZeroExt(),
], ),
]
},
)); ));
} }
}; };
@ -176,86 +184,10 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
concat!($mnemonic, " ", $rs, ", ", $ra, ", ", $rb), concat!($mnemonic, " ", $rs, ", ", $ra, ", ", $rb),
$encoding, $encoding,
None, None,
[ || {
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
),
],
));
};
}
macro_rules! store_update_indexed {
(
$mnemonic:literal $rs:literal, $ra:literal, $rb:literal;
$encoding:literal;
$width:ident;
) => {
if $ra == $rs {
retval.push(insn_triple(
concat!($mnemonic, " ", $rs, ", ", $ra, ", ", $rb),
$encoding,
None,
[ [
AddSubMOp::add_sub_i( AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]), MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
),
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[MOpRegNum::power_isa_temp_reg()],
0.cast_to_static::<SInt<_>>(),
),
],
));
} else {
retval.push(insn_double(
concat!($mnemonic, " ", $rs, ", ", $ra, ", ", $rb),
$encoding,
None,
[
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[ [
if $ra == 0 { if $ra == 0 {
MOpRegNum::const_zero() MOpRegNum::const_zero()
@ -274,13 +206,95 @@ pub fn test_cases_book_i_3_3_3_fixed_point_store(retval: &mut Vec<TestCase>) {
StoreMOp::store( StoreMOp::store(
MOpDestReg::new_sim(&[], &[]), MOpDestReg::new_sim(&[], &[]),
[ [
MOpRegNum::power_isa_gpr_reg_imm($ra), MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs), MOpRegNum::power_isa_gpr_reg_imm($rs),
], ],
LoadStoreWidth.$width(), LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(), LoadStoreConversion.ZeroExt(),
), ),
], ]
},
));
};
}
macro_rules! store_update_indexed {
(
$mnemonic:literal $rs:literal, $ra:literal, $rb:literal;
$encoding:literal;
$width:ident;
) => {
if $ra == $rs {
retval.push(insn_triple(
concat!($mnemonic, " ", $rs, ", ", $ra, ", ", $rb),
$encoding,
None,
|| {
[
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TEMP_REG_NUM], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_temp_reg(),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
),
MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[MOpRegNum::power_isa_temp_reg()],
0.cast_to_static::<SInt<_>>(),
),
]
},
));
} else {
retval.push(insn_double(
concat!($mnemonic, " ", $rs, ", ", $ra, ", ", $rb),
$encoding,
None,
|| {
[
AddSubMOp::add_sub_i(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num($ra)], &[]),
[
if $ra == 0 {
MOpRegNum::const_zero()
} else {
MOpRegNum::power_isa_gpr_reg_imm($ra)
},
MOpRegNum::power_isa_gpr_reg_imm($rb),
],
0.cast_to_static::<SInt<_>>(),
OutputIntegerMode.Full64(),
false,
false,
false,
false,
),
StoreMOp::store(
MOpDestReg::new_sim(&[], &[]),
[
MOpRegNum::power_isa_gpr_reg_imm($ra),
MOpRegNum::power_isa_gpr_reg_imm($rs),
],
LoadStoreWidth.$width(),
LoadStoreConversion.ZeroExt(),
),
]
},
)); ));
} }
}; };

View file

@ -23,10 +23,7 @@ pub fn test_cases_book_i_3_3_19_move_to_from_system_register(retval: &mut Vec<Te
dest_count: 6usize.cast_to(LogicalFlagsMOpImm.dest_count), dest_count: 6usize.cast_to(LogicalFlagsMOpImm.dest_count),
} }
} }
retval.push(insn_single( retval.push(insn_single("mcrxrx 3", 0x7d800480, None, || {
"mcrxrx 3",
0x7d800480,
None,
LogicalFlagsMOp::logical_flags( LogicalFlagsMOp::logical_flags(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
[ [
@ -36,114 +33,114 @@ pub fn test_cases_book_i_3_3_19_move_to_from_system_register(retval: &mut Vec<Te
], ],
mcrxrx_imm(), mcrxrx_imm(),
Lut4::from_fn(|a, b| a | b), Lut4::from_fn(|a, b| a | b),
), )
)); }));
} }
/// covers instructions in PowerISA v3.1C Book III 5.4.4 Move To/From System Register Instructions /// covers instructions in PowerISA v3.1C Book III 5.4.4 Move To/From System Register Instructions
pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<TestCase>) { pub fn test_cases_book_iii_5_4_4_move_to_from_system_register(retval: &mut Vec<TestCase>) {
retval.push(insn_single( retval.push(insn_single("mflr 3", 0x7c6802a6, None, || {
"mflr 3",
0x7c6802a6,
None,
MoveRegMOp::move_reg( MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_lr_reg()], [MOpRegNum::power_isa_lr_reg()],
0.cast_to_static::<SInt<_>>(), 0.cast_to_static::<SInt<_>>(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("mtlr 3", 0x7c6803a6, None, || {
"mtlr 3",
0x7c6803a6,
None,
MoveRegMOp::move_reg( MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]), MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_LR_REG_NUM], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(3)], [MOpRegNum::power_isa_gpr_reg_imm(3)],
0.cast_to_static::<SInt<_>>(), 0.cast_to_static::<SInt<_>>(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("mfctr 3", 0x7c6902a6, None, || {
"mfctr 3",
0x7c6902a6,
None,
MoveRegMOp::move_reg( MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
[MOpRegNum::power_isa_ctr_reg()], [MOpRegNum::power_isa_ctr_reg()],
0.cast_to_static::<SInt<_>>(), 0.cast_to_static::<SInt<_>>(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single("mtctr 3", 0x7c6903a6, None, || {
"mtctr 3",
0x7c6903a6,
None,
MoveRegMOp::move_reg( MoveRegMOp::move_reg(
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_CTR_REG_NUM], &[]), MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_CTR_REG_NUM], &[]),
[MOpRegNum::power_isa_gpr_reg_imm(3)], [MOpRegNum::power_isa_gpr_reg_imm(3)],
0.cast_to_static::<SInt<_>>(), 0.cast_to_static::<SInt<_>>(),
), )
)); }));
retval.push(insn_single( retval.push(insn_single(
"mfspr 3, 815 # mftar 3", "mfspr 3, 815 # mftar 3",
0x7c6fcaa6, 0x7c6fcaa6,
None, None,
MoveRegMOp::move_reg( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), MoveRegMOp::move_reg(
[MOpRegNum::power_isa_tar_reg()], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
0.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_tar_reg()],
), 0.cast_to_static::<SInt<_>>(),
)
},
)); ));
retval.push(insn_single( retval.push(insn_single(
"mtspr 815, 3 # mttar 3", "mtspr 815, 3 # mttar 3",
0x7c6fcba6, 0x7c6fcba6,
None, None,
MoveRegMOp::move_reg( || {
MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TAR_REG_NUM], &[]), MoveRegMOp::move_reg(
[MOpRegNum::power_isa_gpr_reg_imm(3)], MOpDestReg::new_sim(&[MOpRegNum::POWER_ISA_TAR_REG_NUM], &[]),
0.cast_to_static::<SInt<_>>(), [MOpRegNum::power_isa_gpr_reg_imm(3)],
), 0.cast_to_static::<SInt<_>>(),
)
},
)); ));
// make sure we generate mfspr and not the phased-out mftb // make sure we generate mfspr and not the phased-out mftb
retval.push(insn_single( retval.push(insn_single(
"mfspr 3, 268 # mftb 3", "mfspr 3, 268 # mftb 3",
0x7c6c42a6, 0x7c6c42a6,
None, None,
ReadSpecialMOp::read_special( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), ReadSpecialMOp::read_special(
[MOpRegNum::const_zero(); 0], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
ReadSpecialMOpImm.PowerIsaTimeBase(), [MOpRegNum::const_zero(); 0],
), ReadSpecialMOpImm.PowerIsaTimeBase(),
)
},
)); ));
// make sure we generate mfspr and not the phased-out mftb // make sure we generate mfspr and not the phased-out mftb
retval.push(insn_single( retval.push(insn_single(
"mfspr 3, 269 # mftbu 3", "mfspr 3, 269 # mftbu 3",
0x7c6d42a6, 0x7c6d42a6,
None, None,
ReadSpecialMOp::read_special( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), ReadSpecialMOp::read_special(
[MOpRegNum::const_zero(); 0], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
ReadSpecialMOpImm.PowerIsaTimeBaseU(), [MOpRegNum::const_zero(); 0],
), ReadSpecialMOpImm.PowerIsaTimeBaseU(),
)
},
)); ));
// phased-out mftb -- not actually generated by the assembler so we have to use .long // phased-out mftb -- not actually generated by the assembler so we have to use .long
retval.push(insn_single( retval.push(insn_single(
".long 0x7c6c42e6 # mftb 3, 268", ".long 0x7c6c42e6 # mftb 3, 268",
0x7c6c42e6, 0x7c6c42e6,
None, None,
ReadSpecialMOp::read_special( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), ReadSpecialMOp::read_special(
[MOpRegNum::const_zero(); 0], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
ReadSpecialMOpImm.PowerIsaTimeBase(), [MOpRegNum::const_zero(); 0],
), ReadSpecialMOpImm.PowerIsaTimeBase(),
)
},
)); ));
// phased-out mftb -- not actually generated by the assembler so we have to use .long // phased-out mftb -- not actually generated by the assembler so we have to use .long
retval.push(insn_single( retval.push(insn_single(
".long 0x7c6d42e6 # mftb 3, 269", ".long 0x7c6d42e6 # mftb 3, 269",
0x7c6d42e6, 0x7c6d42e6,
None, None,
ReadSpecialMOp::read_special( || {
MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]), ReadSpecialMOp::read_special(
[MOpRegNum::const_zero(); 0], MOpDestReg::new_sim(&[MOpRegNum::power_isa_gpr_reg_num(3)], &[]),
ReadSpecialMOpImm.PowerIsaTimeBaseU(), [MOpRegNum::const_zero(); 0],
), ReadSpecialMOpImm.PowerIsaTimeBaseU(),
)
},
)); ));
} }