extract lut out into separate Lut4 type and add test
This commit is contained in:
parent
85ada6e55a
commit
a93dca25ac
6 changed files with 99165 additions and 96934 deletions
|
|
@ -4,8 +4,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::CpuConfig,
|
config::CpuConfig,
|
||||||
instruction::{
|
instruction::{
|
||||||
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LogicalMOp, MOp, MOpDestReg,
|
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LogicalMOp, Lut4, MOp,
|
||||||
MOpRegNum, MoveRegMOp, OutputIntegerMode,
|
MOpDestReg, MOpRegNum, MoveRegMOp, OutputIntegerMode,
|
||||||
},
|
},
|
||||||
powerisa_instructions_xml::{
|
powerisa_instructions_xml::{
|
||||||
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
|
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
|
||||||
|
|
@ -1234,9 +1234,9 @@ impl DecodeState {
|
||||||
fn decode_andis_oris_xoris(&mut self) {
|
fn decode_andis_oris_xoris(&mut self) {
|
||||||
assert_eq!(self.arguments, Some("RA,RS,UI"), "{self:?}");
|
assert_eq!(self.arguments, Some("RA,RS,UI"), "{self:?}");
|
||||||
let lut = match self.mnemonic {
|
let lut = match self.mnemonic {
|
||||||
"andi." | "andis." => LogicalMOp::lut_from_fn(|[a, b]| a & b),
|
"andi." | "andis." => Lut4::from_fn(|a, b| a & b),
|
||||||
"ori" | "oris" => LogicalMOp::lut_from_fn(|[a, b]| a | b),
|
"ori" | "oris" => Lut4::from_fn(|a, b| a | b),
|
||||||
"xori" | "xoris" => LogicalMOp::lut_from_fn(|[a, b]| a ^ b),
|
"xori" | "xoris" => Lut4::from_fn(|a, b| a ^ b),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
self.decode_scope(|this, (FieldRS(rs), FieldRA(ra), FieldUI(ui))| {
|
self.decode_scope(|this, (FieldRS(rs), FieldRA(ra), FieldUI(ui))| {
|
||||||
|
|
@ -1282,14 +1282,14 @@ impl DecodeState {
|
||||||
fn decode_and_xor_nand_or_orc_nor_eqv_andc(&mut self) {
|
fn decode_and_xor_nand_or_orc_nor_eqv_andc(&mut self) {
|
||||||
assert_eq!(self.arguments, Some("RA,RS,RB"));
|
assert_eq!(self.arguments, Some("RA,RS,RB"));
|
||||||
let lut = match self.mnemonic.trim_end_matches('.') {
|
let lut = match self.mnemonic.trim_end_matches('.') {
|
||||||
"and" => LogicalMOp::lut_from_fn(|[a, b]| a & b),
|
"and" => Lut4::from_fn(|a, b| a & b),
|
||||||
"xor" => LogicalMOp::lut_from_fn(|[a, b]| a ^ b),
|
"xor" => Lut4::from_fn(|a, b| a ^ b),
|
||||||
"nand" => LogicalMOp::lut_from_fn(|[a, b]| !(a & b)),
|
"nand" => Lut4::from_fn(|a, b| !(a & b)),
|
||||||
"or" => LogicalMOp::lut_from_fn(|[a, b]| a | b),
|
"or" => Lut4::from_fn(|a, b| a | b),
|
||||||
"orc" => LogicalMOp::lut_from_fn(|[a, b]| a | !b),
|
"orc" => Lut4::from_fn(|a, b| a | !b),
|
||||||
"nor" => LogicalMOp::lut_from_fn(|[a, b]| !(a | b)),
|
"nor" => Lut4::from_fn(|a, b| !(a | b)),
|
||||||
"eqv" => LogicalMOp::lut_from_fn(|[a, b]| a == b),
|
"eqv" => Lut4::from_fn(|a, b| a == b),
|
||||||
"andc" => LogicalMOp::lut_from_fn(|[a, b]| a & !b),
|
"andc" => Lut4::from_fn(|a, b| a & !b),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
self.decode_scope(
|
self.decode_scope(
|
||||||
|
|
@ -1349,7 +1349,7 @@ impl DecodeState {
|
||||||
[gpr(rs).value],
|
[gpr(rs).value],
|
||||||
0.cast_to_static::<SInt<_>>(),
|
0.cast_to_static::<SInt<_>>(),
|
||||||
output_integer_mode,
|
output_integer_mode,
|
||||||
LogicalMOp::lut_from_fn(|[a, b]| a | b),
|
Lut4::from_fn(|a, b| a | b),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
use crate::{unit::UnitMOp, util::range_u32_len};
|
use crate::{unit::UnitMOp, util::range_u32_len};
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
expr::{HdlPartialEqImpl, ops::ArrayLiteral},
|
expr::{CastToImpl, HdlPartialEqImpl, ops::ArrayLiteral},
|
||||||
|
int::BoolOrIntType,
|
||||||
intern::{Intern, InternSlice, Interned},
|
intern::{Intern, InternSlice, Interned},
|
||||||
module::wire_with_loc,
|
module::wire_with_loc,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
ty::StaticType,
|
ty::StaticType,
|
||||||
|
util::ConstBool,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
|
|
@ -893,45 +895,84 @@ impl<DestReg: Type, SrcRegWidth: Size> AddSubMOp<DestReg, SrcRegWidth, ConstUsiz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
common_mop_struct! {
|
#[hdl(cmp_eq)]
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> LogicalMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
pub struct Lut4 {
|
||||||
#[hdl(cmp_eq)]
|
pub lut: Array<Bool, 4>,
|
||||||
/// computes the output like so:
|
}
|
||||||
/// ```
|
|
||||||
/// fn logical_output(src: [u64; 2], lut: u8) -> u64 {
|
impl Lut4 {
|
||||||
/// let mut output = 0u64;
|
#[track_caller]
|
||||||
/// for i in 0..64 {
|
fn output_impl<T, LutBit, A, B, UIntTy, Output>(lut: [LutBit; 4], a: A, b: B) -> Output
|
||||||
/// let mask = 1 << i;
|
where
|
||||||
/// let mut lut_index = 0;
|
T: BoolOrIntType<Signed = ConstBool<false>>,
|
||||||
/// if (src[0] & mask) != 0 {
|
LutBit: ValueType<Type = Bool> + CastTo,
|
||||||
/// lut_index |= 1;
|
A: ValueType<Type = T> + CastToBits<Output = UIntTy>,
|
||||||
/// }
|
B: ValueType<Type = T> + CastToBits<Output = UIntTy>,
|
||||||
/// if (src[1] & mask) != 0 {
|
UIntTy: ValueType<Type = UInt>
|
||||||
/// lut_index |= 2;
|
+ CastBitsTo<Output<T> = Output>
|
||||||
/// }
|
+ std::ops::Not<Output = UIntTy>
|
||||||
/// if (lut & (1 << lut_index)) != 0 {
|
+ std::ops::BitAnd<Output = UIntTy>
|
||||||
/// output |= mask;
|
+ std::ops::BitOr<Output = UIntTy>
|
||||||
/// }
|
+ Clone,
|
||||||
/// }
|
Output: ValueType<Type = T>,
|
||||||
/// output
|
<LutBit as CastTo>::Output<SInt<1>>: CastTo<Output<UInt> = UIntTy>,
|
||||||
/// }
|
{
|
||||||
/// ```
|
let ty = a.ty();
|
||||||
pub struct LogicalMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
assert_eq!(ty, b.ty(), "input types must match");
|
||||||
#[common]
|
let a = a.cast_to_bits();
|
||||||
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
let b = b.cast_to_bits();
|
||||||
pub lut: UInt<4>,
|
let uint_ty = a.ty();
|
||||||
|
let [v0, v1, v2, v3] = std::array::from_fn(|lut_index| {
|
||||||
|
let a = if (lut_index & 1) == 0 {
|
||||||
|
!a.clone()
|
||||||
|
} else {
|
||||||
|
a.clone()
|
||||||
|
};
|
||||||
|
let b = if (lut_index & 2) == 0 {
|
||||||
|
!b.clone()
|
||||||
|
} else {
|
||||||
|
b.clone()
|
||||||
|
};
|
||||||
|
let mask = lut[lut_index].cast_to_static::<SInt<1>>().cast_to(uint_ty);
|
||||||
|
a & b & mask
|
||||||
|
});
|
||||||
|
((v0 | v1) | (v2 | v3)).cast_bits_to(ty)
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn output<T: BoolOrIntType<Signed = ConstBool<false>>>(
|
||||||
|
this: impl ToExpr<Type = Self>,
|
||||||
|
a: impl ToExpr<Type = T>,
|
||||||
|
b: impl ToExpr<Type = T>,
|
||||||
|
) -> Expr<T> {
|
||||||
|
Self::output_impl(*this.to_expr().lut, a.to_expr(), b.to_expr())
|
||||||
|
}
|
||||||
|
#[track_caller]
|
||||||
|
pub fn output_sim<T: BoolOrIntType<Signed = ConstBool<false>>>(
|
||||||
|
this: impl ToSimValue<Type = Self>,
|
||||||
|
a: impl ToSimValue<Type = T>,
|
||||||
|
b: impl ToSimValue<Type = T>,
|
||||||
|
) -> SimValue<T> {
|
||||||
|
Self::output_impl(
|
||||||
|
SimValue::into_value(SimValue::into_value(this.into_sim_value()).lut),
|
||||||
|
a.into_sim_value(),
|
||||||
|
b.into_sim_value(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
#[hdl]
|
||||||
|
pub fn from_fn(f: impl Fn(bool, bool) -> bool) -> SimValue<Self> {
|
||||||
|
let lut = std::array::from_fn(|lut_index| f((lut_index & 1) != 0, (lut_index & 2) != 0));
|
||||||
|
#[hdl(sim)]
|
||||||
|
Self { lut }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogicalMOp<MOpDestReg, ConstUsize<{ MOpRegNum::WIDTH }>, ConstUsize<2>> {
|
common_mop_struct! {
|
||||||
pub fn lut_from_fn(f: impl Fn([bool; 2]) -> bool) -> UIntValue<ConstUsize<4>> {
|
#[mapped(<NewDestReg, NewSrcRegWidth> LogicalMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
||||||
let mut retval = 0u8;
|
#[hdl(cmp_eq)]
|
||||||
for lut_index in 0..4 {
|
pub struct LogicalMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
if f([(lut_index & 1) != 0, (lut_index & 2) != 0]) {
|
#[common]
|
||||||
retval |= 1 << lut_index;
|
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
||||||
}
|
pub lut: Lut4,
|
||||||
}
|
|
||||||
retval.cast_to_static::<UInt<4>>()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -942,7 +983,7 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalMOp<DestReg, SrcRegWidth, ConstUsi
|
||||||
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 2>>,
|
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 2>>,
|
||||||
imm: impl ToExpr<Type = SInt<{ COMMON_MOP_2_IMM_WIDTH }>>,
|
imm: impl ToExpr<Type = SInt<{ COMMON_MOP_2_IMM_WIDTH }>>,
|
||||||
output_integer_mode: impl ToExpr<Type = OutputIntegerMode>,
|
output_integer_mode: impl ToExpr<Type = OutputIntegerMode>,
|
||||||
lut: impl ToExpr<Type = UInt<4>>,
|
lut: impl ToExpr<Type = Lut4>,
|
||||||
) -> Expr<Target>
|
) -> Expr<Target>
|
||||||
where
|
where
|
||||||
Self: MOpInto<Target>,
|
Self: MOpInto<Target>,
|
||||||
|
|
@ -968,7 +1009,7 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalMOp<DestReg, SrcRegWidth, ConstUsi
|
||||||
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 1>>,
|
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 1>>,
|
||||||
imm: impl ToExpr<Type = SInt<{ COMMON_MOP_1_IMM_WIDTH }>>,
|
imm: impl ToExpr<Type = SInt<{ COMMON_MOP_1_IMM_WIDTH }>>,
|
||||||
output_integer_mode: impl ToExpr<Type = OutputIntegerMode>,
|
output_integer_mode: impl ToExpr<Type = OutputIntegerMode>,
|
||||||
lut: impl ToExpr<Type = UInt<4>>,
|
lut: impl ToExpr<Type = Lut4>,
|
||||||
) -> Expr<Target>
|
) -> Expr<Target>
|
||||||
where
|
where
|
||||||
Self: MOpInto<Target>,
|
Self: MOpInto<Target>,
|
||||||
|
|
@ -1794,6 +1835,44 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::{convert::Infallible, fmt::Write, usize};
|
use std::{convert::Infallible, fmt::Write, usize};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_lut() {
|
||||||
|
macro_rules! case {
|
||||||
|
([$lut0:literal, $lut1:literal, $lut2:literal, $lut3:literal], $expected:literal, |$a:ident, $b:ident| $e:expr) => {
|
||||||
|
let lut = Lut4::from_fn(|$a, $b| $e);
|
||||||
|
assert_eq!(
|
||||||
|
lut.lut,
|
||||||
|
[
|
||||||
|
($lut0 != 0).into_sim_value(),
|
||||||
|
($lut1 != 0).into_sim_value(),
|
||||||
|
($lut2 != 0).into_sim_value(),
|
||||||
|
($lut3 != 0).into_sim_value()
|
||||||
|
]
|
||||||
|
.into_sim_value()
|
||||||
|
);
|
||||||
|
let output = Lut4::output_sim(&lut, 0xAAu8, 0xCCu8);
|
||||||
|
let expected = <u8 as ToSimValue>::into_sim_value($expected);
|
||||||
|
assert_eq!(output, expected, "{lut:?}");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case!([0, 0, 0, 0], 0x00, |_a, _b| false);
|
||||||
|
case!([1, 0, 0, 0], 0x11, |a, b| !(a | b));
|
||||||
|
case!([0, 1, 0, 0], 0x22, |a, b| a & !b);
|
||||||
|
case!([1, 1, 0, 0], 0x33, |_a, b| !b);
|
||||||
|
case!([0, 0, 1, 0], 0x44, |a, b| !a & b);
|
||||||
|
case!([1, 0, 1, 0], 0x55, |a, _b| !a);
|
||||||
|
case!([0, 1, 1, 0], 0x66, |a, b| a ^ b);
|
||||||
|
case!([1, 1, 1, 0], 0x77, |a, b| !(a & b));
|
||||||
|
case!([0, 0, 0, 1], 0x88, |a, b| a & b);
|
||||||
|
case!([1, 0, 0, 1], 0x99, |a, b| a == b);
|
||||||
|
case!([0, 1, 0, 1], 0xaa, |a, _b| a);
|
||||||
|
case!([1, 1, 0, 1], 0xbb, |a, b| a | !b);
|
||||||
|
case!([0, 0, 1, 1], 0xcc, |_a, b| b);
|
||||||
|
case!([1, 0, 1, 1], 0xdd, |a, b| !a | b);
|
||||||
|
case!([0, 1, 1, 1], 0xee, |a, b| a | b);
|
||||||
|
case!([1, 1, 1, 1], 0xff, |_a, _b| true);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ensure_reg_fields_are_in_the_same_place() {
|
fn ensure_reg_fields_are_in_the_same_place() {
|
||||||
struct Visitor {
|
struct Visitor {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use cpu::{
|
use cpu::{
|
||||||
config::{CpuConfig, UnitConfig},
|
config::{CpuConfig, UnitConfig},
|
||||||
instruction::{AddSubMOp, LogicalMOp, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode},
|
instruction::{AddSubMOp, LogicalMOp, Lut4, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode},
|
||||||
reg_alloc::{FetchedDecodedMOp, reg_alloc},
|
reg_alloc::{FetchedDecodedMOp, reg_alloc},
|
||||||
register::{FlagsMode, PRegFlagsPowerISA},
|
register::{FlagsMode, PRegFlagsPowerISA},
|
||||||
unit::{GlobalState, UnitKind},
|
unit::{GlobalState, UnitKind},
|
||||||
|
|
@ -101,7 +101,7 @@ fn test_reg_alloc() {
|
||||||
[2u8, 4u8],
|
[2u8, 4u8],
|
||||||
0.cast_to_static::<SInt<_>>(),
|
0.cast_to_static::<SInt<_>>(),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
0b0110_hdl_u4,
|
Lut4::from_fn(|a, b| a ^ b),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
let insns = insns_init.into_iter().chain(insns_loop.into_iter().cycle());
|
let insns = insns_init.into_iter().chain(insns_loop.into_iter().cycle());
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
use cpu::{
|
use cpu::{
|
||||||
decoder::simple_power_isa::decode_one_insn,
|
decoder::simple_power_isa::decode_one_insn,
|
||||||
instruction::{
|
instruction::{
|
||||||
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LogicalMOp, MOp, MOpDestReg,
|
AddSubMOp, BranchMOp, CompareMOp, CompareMode, ConditionMode, LogicalMOp, Lut4, MOp,
|
||||||
MOpRegNum, MoveRegMOp, OutputIntegerMode,
|
MOpDestReg, MOpRegNum, MoveRegMOp, OutputIntegerMode,
|
||||||
},
|
},
|
||||||
util::array_vec::ArrayVec,
|
util::array_vec::ArrayVec,
|
||||||
};
|
};
|
||||||
|
|
@ -663,7 +663,7 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
(
|
(
|
||||||
$mnemonic:literal $dest:literal, $src:literal, $imm:literal;
|
$mnemonic:literal $dest:literal, $src:literal, $imm:literal;
|
||||||
$encoding:literal;
|
$encoding:literal;
|
||||||
|[$a:ident, $b:ident]| $lut_fn:expr;
|
|$a:ident, $b:ident| $lut_fn:expr;
|
||||||
) => {
|
) => {
|
||||||
retval.push(insn_single(
|
retval.push(insn_single(
|
||||||
concat!(
|
concat!(
|
||||||
|
|
@ -690,7 +690,7 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
(($imm as u32) << if $mnemonic.contains('s') { 16 } else { 0 })
|
(($imm as u32) << if $mnemonic.contains('s') { 16 } else { 0 })
|
||||||
.cast_to_static::<SInt<_>>(),
|
.cast_to_static::<SInt<_>>(),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
LogicalMOp::lut_from_fn(|[$a, $b]| $lut_fn),
|
Lut4::from_fn(|$a, $b| $lut_fn),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
@ -698,45 +698,45 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"andi." 3, 4, 0x89ab;
|
"andi." 3, 4, 0x89ab;
|
||||||
0x708389ab;
|
0x708389ab;
|
||||||
|[a, b]| a & b;
|
|a, b| a & b;
|
||||||
}
|
}
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"andis." 3, 4, 0x89ab;
|
"andis." 3, 4, 0x89ab;
|
||||||
0x748389ab;
|
0x748389ab;
|
||||||
|[a, b]| a & b;
|
|a, b| a & b;
|
||||||
}
|
}
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"ori" 3, 4, 0x89ab;
|
"ori" 3, 4, 0x89ab;
|
||||||
0x608389ab;
|
0x608389ab;
|
||||||
|[a, b]| a | b;
|
|a, b| a | b;
|
||||||
}
|
}
|
||||||
// ensure nop decodes to zero instructions
|
// ensure nop decodes to zero instructions
|
||||||
retval.push(insn_empty("ori 0, 0, 0", 0x60000000, None));
|
retval.push(insn_empty("ori 0, 0, 0", 0x60000000, None));
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"oris" 3, 4, 0x89ab;
|
"oris" 3, 4, 0x89ab;
|
||||||
0x648389ab;
|
0x648389ab;
|
||||||
|[a, b]| a | b;
|
|a, b| a | b;
|
||||||
}
|
}
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"xori" 3, 4, 0x89ab;
|
"xori" 3, 4, 0x89ab;
|
||||||
0x688389ab;
|
0x688389ab;
|
||||||
|[a, b]| a ^ b;
|
|a, b| a ^ b;
|
||||||
}
|
}
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"xori" 0, 0, 0; // ensure xnop actually decodes to a normal ALU instruction
|
"xori" 0, 0, 0; // ensure xnop actually decodes to a normal ALU instruction
|
||||||
0x68000000;
|
0x68000000;
|
||||||
|[a, b]| a ^ b;
|
|a, b| a ^ b;
|
||||||
}
|
}
|
||||||
insn_logic_i! {
|
insn_logic_i! {
|
||||||
"xoris" 3, 4, 0x89ab;
|
"xoris" 3, 4, 0x89ab;
|
||||||
0x6c8389ab;
|
0x6c8389ab;
|
||||||
|[a, b]| a ^ b;
|
|a, b| a ^ b;
|
||||||
}
|
}
|
||||||
macro_rules! insn_logic {
|
macro_rules! insn_logic {
|
||||||
(
|
(
|
||||||
$mnemonic:literal $dest:literal, $src0:literal, $src1:literal;
|
$mnemonic:literal $dest:literal, $src0:literal, $src1:literal;
|
||||||
$encoding:literal;
|
$encoding:literal;
|
||||||
|[$a:ident, $b:ident]| $lut_fn:expr;
|
|$a:ident, $b:ident| $lut_fn:expr;
|
||||||
) => {
|
) => {
|
||||||
retval.push(insn_single(
|
retval.push(insn_single(
|
||||||
concat!(
|
concat!(
|
||||||
|
|
@ -765,7 +765,7 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
],
|
],
|
||||||
0.cast_to_static::<SInt<_>>(),
|
0.cast_to_static::<SInt<_>>(),
|
||||||
OutputIntegerMode.Full64(),
|
OutputIntegerMode.Full64(),
|
||||||
LogicalMOp::lut_from_fn(|[$a, $b]| $lut_fn),
|
Lut4::from_fn(|$a, $b| $lut_fn),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
@ -773,37 +773,37 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"and" 3, 4, 5;
|
"and" 3, 4, 5;
|
||||||
0x7c832838;
|
0x7c832838;
|
||||||
|[a, b]| a & b;
|
|a, b| a & b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"and." 3, 4, 5;
|
"and." 3, 4, 5;
|
||||||
0x7c832839;
|
0x7c832839;
|
||||||
|[a, b]| a & b;
|
|a, b| a & b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"xor" 3, 4, 5;
|
"xor" 3, 4, 5;
|
||||||
0x7c832a78;
|
0x7c832a78;
|
||||||
|[a, b]| a ^ b;
|
|a, b| a ^ b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"xor." 3, 4, 5;
|
"xor." 3, 4, 5;
|
||||||
0x7c832a79;
|
0x7c832a79;
|
||||||
|[a, b]| a ^ b;
|
|a, b| a ^ b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"nand" 3, 4, 5;
|
"nand" 3, 4, 5;
|
||||||
0x7c832bb8;
|
0x7c832bb8;
|
||||||
|[a, b]| !(a & b);
|
|a, b| !(a & b);
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"nand." 3, 4, 5;
|
"nand." 3, 4, 5;
|
||||||
0x7c832bb9;
|
0x7c832bb9;
|
||||||
|[a, b]| !(a & b);
|
|a, b| !(a & b);
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"or" 3, 4, 5;
|
"or" 3, 4, 5;
|
||||||
0x7c832b78;
|
0x7c832b78;
|
||||||
|[a, b]| a | b;
|
|a, b| a | b;
|
||||||
}
|
}
|
||||||
retval.push(insn_single(
|
retval.push(insn_single(
|
||||||
"or 3, 4, 4", // mr 3, 4
|
"or 3, 4, 4", // mr 3, 4
|
||||||
|
|
@ -818,52 +818,52 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"or." 3, 4, 5;
|
"or." 3, 4, 5;
|
||||||
0x7c832b79;
|
0x7c832b79;
|
||||||
|[a, b]| a | b;
|
|a, b| a | b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"or." 3, 4, 4; // mr. 3, 4
|
"or." 3, 4, 4; // mr. 3, 4
|
||||||
0x7c832379;
|
0x7c832379;
|
||||||
|[a, b]| a | b;
|
|a, b| a | b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"orc" 3, 4, 5;
|
"orc" 3, 4, 5;
|
||||||
0x7c832b38;
|
0x7c832b38;
|
||||||
|[a, b]| a | !b;
|
|a, b| a | !b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"orc." 3, 4, 5;
|
"orc." 3, 4, 5;
|
||||||
0x7c832b39;
|
0x7c832b39;
|
||||||
|[a, b]| a | !b;
|
|a, b| a | !b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"nor" 3, 4, 5;
|
"nor" 3, 4, 5;
|
||||||
0x7c8328f8;
|
0x7c8328f8;
|
||||||
|[a, b]| !(a | b);
|
|a, b| !(a | b);
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"nor." 3, 4, 5;
|
"nor." 3, 4, 5;
|
||||||
0x7c8328f9;
|
0x7c8328f9;
|
||||||
|[a, b]| !(a | b);
|
|a, b| !(a | b);
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"eqv" 3, 4, 5;
|
"eqv" 3, 4, 5;
|
||||||
0x7c832a38;
|
0x7c832a38;
|
||||||
|[a, b]| a == b;
|
|a, b| a == b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"eqv." 3, 4, 5;
|
"eqv." 3, 4, 5;
|
||||||
0x7c832a39;
|
0x7c832a39;
|
||||||
|[a, b]| a == b;
|
|a, b| a == b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"andc" 3, 4, 5;
|
"andc" 3, 4, 5;
|
||||||
0x7c832878;
|
0x7c832878;
|
||||||
|[a, b]| a & !b;
|
|a, b| a & !b;
|
||||||
}
|
}
|
||||||
insn_logic! {
|
insn_logic! {
|
||||||
"andc." 3, 4, 5;
|
"andc." 3, 4, 5;
|
||||||
0x7c832879;
|
0x7c832879;
|
||||||
|[a, b]| a & !b;
|
|a, b| a & !b;
|
||||||
}
|
}
|
||||||
macro_rules! insn_exts {
|
macro_rules! insn_exts {
|
||||||
(
|
(
|
||||||
|
|
@ -887,7 +887,7 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
[MOpRegNum::power_isa_gpr_reg_imm($src).value],
|
[MOpRegNum::power_isa_gpr_reg_imm($src).value],
|
||||||
0.cast_to_static::<SInt<_>>(),
|
0.cast_to_static::<SInt<_>>(),
|
||||||
OutputIntegerMode.$OutputIntegerMode(),
|
OutputIntegerMode.$OutputIntegerMode(),
|
||||||
LogicalMOp::lut_from_fn(|[a, b]| a | b),
|
Lut4::from_fn(|a, b| a | b),
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue