forked from libre-chip/cpu
implement decoding condition register logical instructions
This commit is contained in:
parent
5e9d0957f6
commit
33529a2296
4 changed files with 28486 additions and 10353 deletions
|
|
@ -11,10 +11,12 @@ use crate::{
|
||||||
powerisa_instructions_xml::{
|
powerisa_instructions_xml::{
|
||||||
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
|
InstructionBitFieldName, InstructionBitFieldsInner, Instructions, TextLineItem,
|
||||||
},
|
},
|
||||||
register::{PRegFlagsPowerISA, PRegFlagsPowerISAView},
|
register::{
|
||||||
|
PRegFlags, PRegFlagsPowerISA, PRegFlagsPowerISAView, PRegFlagsViewTrait, ViewUnused,
|
||||||
|
},
|
||||||
util::array_vec::{ArrayVec, Length},
|
util::array_vec::{ArrayVec, Length},
|
||||||
};
|
};
|
||||||
use fayalite::{module::wire_with_loc, prelude::*, ty::StaticType};
|
use fayalite::{int::UIntInRange, module::wire_with_loc, prelude::*, ty::StaticType};
|
||||||
use std::{collections::BTreeMap, ops::RangeInclusive};
|
use std::{collections::BTreeMap, ops::RangeInclusive};
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
@ -181,8 +183,14 @@ macro_rules! impl_fields {
|
||||||
impl_fields! {
|
impl_fields! {
|
||||||
#[name = "BF"]
|
#[name = "BF"]
|
||||||
struct FieldBF(FieldCrf);
|
struct FieldBF(FieldCrf);
|
||||||
|
#[name = "BA"]
|
||||||
|
struct FieldBA(FieldCrBit);
|
||||||
|
#[name = "BB"]
|
||||||
|
struct FieldBB(FieldCrBit);
|
||||||
#[name = "BI"]
|
#[name = "BI"]
|
||||||
struct FieldBI(FieldCrBit);
|
struct FieldBI(FieldCrBit);
|
||||||
|
#[name = "BT"]
|
||||||
|
struct FieldBT(FieldCrBit);
|
||||||
#[name = "RA"]
|
#[name = "RA"]
|
||||||
struct FieldRA(FieldGpr);
|
struct FieldRA(FieldGpr);
|
||||||
#[name = "RB"]
|
#[name = "RB"]
|
||||||
|
|
@ -258,7 +266,7 @@ fn crf(this: impl ToExpr<Type = FieldCrf>) -> Expr<MOpRegNum> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn cr_bit(cr_bit: impl ToExpr<Type = FieldCrBit>) -> (Expr<MOpRegNum>, Expr<ConditionMode>) {
|
fn cr_bit_cond(cr_bit: impl ToExpr<Type = FieldCrBit>) -> (Expr<MOpRegNum>, Expr<ConditionMode>) {
|
||||||
let cr_bit = cr_bit.to_expr();
|
let cr_bit = cr_bit.to_expr();
|
||||||
let field_bit = cr_bit.bit_num.cast_to_static::<UInt<2>>();
|
let field_bit = cr_bit.bit_num.cast_to_static::<UInt<2>>();
|
||||||
let field_num = (cr_bit.bit_num >> 2).cast_to_static::<UInt<3>>();
|
let field_num = (cr_bit.bit_num >> 2).cast_to_static::<UInt<3>>();
|
||||||
|
|
@ -269,19 +277,21 @@ fn cr_bit(cr_bit: impl ToExpr<Type = FieldCrBit>) -> (Expr<MOpRegNum>, Expr<Cond
|
||||||
}
|
}
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn cr_bit_sim(
|
fn cr_bit_flag_index(
|
||||||
cr_bit: impl ToSimValue<Type = FieldCrBit>,
|
cr_bit: impl ToExpr<Type = FieldCrBit>,
|
||||||
) -> (SimValue<MOpRegNum>, SimValue<ConditionMode>) {
|
) -> (
|
||||||
let cr_bit = cr_bit.into_sim_value();
|
Expr<MOpRegNum>,
|
||||||
let field_bit = *cr_bit
|
Expr<UIntInRange<0, { PRegFlags::FLAG_COUNT }>>,
|
||||||
.bit_num
|
) {
|
||||||
.cast_to_static::<UInt<2>>()
|
let cr_bit = cr_bit.to_expr();
|
||||||
.cast_to_static::<fayalite::int::UIntInRange<0, 4>>();
|
let field_bit = cr_bit.bit_num.cast_to_static::<UInt<2>>();
|
||||||
let field_num = (&cr_bit.bit_num >> 2).cast_to_static::<UInt<3>>();
|
let field_num = (cr_bit.bit_num >> 2).cast_to_static::<UInt<3>>();
|
||||||
(
|
let flag_indexes = ViewUnused::from_fn(|i| i);
|
||||||
MOpRegNum::power_isa_cr_reg_sim(&field_num),
|
let flag_index = PRegFlagsPowerISA::view_unused_into_view(flag_indexes)
|
||||||
PRegFlagsPowerISA::cr_condition_modes_msb0_sim()[field_bit].clone(),
|
.into_cr_bits_msb0()
|
||||||
)
|
.map(|i| i.cast_to_static::<UIntInRange<_, _>>())
|
||||||
|
.to_expr()[field_bit];
|
||||||
|
(MOpRegNum::power_isa_cr_reg(field_num), flag_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecodeState {
|
impl DecodeState {
|
||||||
|
|
@ -533,7 +543,7 @@ impl DecodeState {
|
||||||
let no_ctr = bo[2]; // BO_2 in specification
|
let no_ctr = bo[2]; // BO_2 in specification
|
||||||
let expected_cr_bit_value = bo[3]; // BO_1 in specification
|
let expected_cr_bit_value = bo[3]; // BO_1 in specification
|
||||||
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(bi);
|
let (cr_field, condition_mode) = cr_bit_cond(bi);
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let branch_mop = wire();
|
let branch_mop = wire();
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -655,6 +665,54 @@ impl DecodeState {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// for crand, crnand, cror, crxor, crnor, creqv, crandc, crorc
|
||||||
|
#[hdl]
|
||||||
|
fn decode_crand_crnand_cror_crxor_crnor_creqv_crandc_crorc(&mut self) {
|
||||||
|
assert_eq!(self.arguments, Some("BT,BA,BB"));
|
||||||
|
let lut = match self.mnemonic {
|
||||||
|
"crand" => Lut4::from_fn(|a, b| a & b),
|
||||||
|
"crnand" => Lut4::from_fn(|a, b| !(a & b)),
|
||||||
|
"cror" => Lut4::from_fn(|a, b| a | b),
|
||||||
|
"crxor" => Lut4::from_fn(|a, b| a ^ b),
|
||||||
|
"crnor" => Lut4::from_fn(|a, b| !(a | b)),
|
||||||
|
"creqv" => Lut4::from_fn(|a, b| a == b),
|
||||||
|
"crandc" => Lut4::from_fn(|a, b| a & !b),
|
||||||
|
"crorc" => Lut4::from_fn(|a, b| a | !b),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
self.decode_scope(|this, (FieldBT(bt), FieldBA(ba), FieldBB(bb))| {
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
let (bt_reg, bt_flag_index) = cr_bit_flag_index(bt);
|
||||||
|
let (ba_reg, ba_flag_index) = cr_bit_flag_index(ba);
|
||||||
|
let (bb_reg, bb_flag_index) = cr_bit_flag_index(bb);
|
||||||
|
let uint_ty = UInt[ba_flag_index.ty().bit_width()];
|
||||||
|
let src0_start = (ba_flag_index.cast_to(uint_ty) + PRegFlags::FLAG_COUNT
|
||||||
|
- bt_flag_index.cast_to(uint_ty))
|
||||||
|
% PRegFlags::FLAG_COUNT;
|
||||||
|
let src1_start = (bb_flag_index.cast_to(uint_ty) + PRegFlags::FLAG_COUNT
|
||||||
|
- bt_flag_index.cast_to(uint_ty))
|
||||||
|
% PRegFlags::FLAG_COUNT;
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
LogicalFlagsMOp::logical_flags(
|
||||||
|
MOpDestReg::new([bt_reg], []),
|
||||||
|
[ba_reg.value, bb_reg.value, bt_reg.value],
|
||||||
|
#[hdl]
|
||||||
|
LogicalFlagsMOpImm {
|
||||||
|
src0_start: src0_start.cast_to(LogicalFlagsMOpImm.src0_start),
|
||||||
|
src1_start: src1_start.cast_to(LogicalFlagsMOpImm.src1_start),
|
||||||
|
src2_start: 0usize.cast_to(LogicalFlagsMOpImm.src2_start),
|
||||||
|
dest_start: bt_flag_index,
|
||||||
|
dest_count: 1usize.cast_to(LogicalFlagsMOpImm.dest_count),
|
||||||
|
},
|
||||||
|
lut,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn decode_addi_paddi(&mut self) {
|
fn decode_addi_paddi(&mut self) {
|
||||||
match self.mnemonic {
|
match self.mnemonic {
|
||||||
|
|
@ -1423,9 +1481,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
||||||
&[
|
&[
|
||||||
"crand", "crnand", "cror", "crxor", "crnor", "creqv", "crandc", "crorc",
|
"crand", "crnand", "cror", "crxor", "crnor", "creqv", "crandc", "crorc",
|
||||||
],
|
],
|
||||||
|_state| {
|
DecodeState::decode_crand_crnand_cror_crxor_crnor_creqv_crandc_crorc,
|
||||||
// TODO
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
(&["mcrf"], |_state| {
|
(&["mcrf"], |_state| {
|
||||||
// TODO
|
// TODO
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -6,6 +6,7 @@ use fayalite::prelude::*;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
mod branch;
|
mod branch;
|
||||||
|
mod condition_register;
|
||||||
mod fixed_point_arithmetic;
|
mod fixed_point_arithmetic;
|
||||||
mod fixed_point_compare;
|
mod fixed_point_compare;
|
||||||
mod fixed_point_logical;
|
mod fixed_point_logical;
|
||||||
|
|
@ -108,6 +109,7 @@ fn insn_double(
|
||||||
pub fn test_cases() -> Vec<TestCase> {
|
pub fn test_cases() -> Vec<TestCase> {
|
||||||
let mut retval = Vec::new();
|
let mut retval = Vec::new();
|
||||||
branch::test_cases_book_i_2_4_branch(&mut retval);
|
branch::test_cases_book_i_2_4_branch(&mut retval);
|
||||||
|
condition_register::test_cases_book_i_2_5_condition_register(&mut retval);
|
||||||
fixed_point_arithmetic::test_cases_book_i_3_3_9_fixed_point_arithmetic(&mut retval);
|
fixed_point_arithmetic::test_cases_book_i_3_3_9_fixed_point_arithmetic(&mut retval);
|
||||||
fixed_point_compare::test_cases_book_i_3_3_10_fixed_point_compare(&mut retval);
|
fixed_point_compare::test_cases_book_i_3_3_10_fixed_point_compare(&mut retval);
|
||||||
fixed_point_logical::test_cases_book_i_3_3_13_fixed_point_logical(&mut retval);
|
fixed_point_logical::test_cases_book_i_3_3_13_fixed_point_logical(&mut retval);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
|
use crate::test_cases::{TestCase, insn_single};
|
||||||
|
use cpu::{
|
||||||
|
instruction::{LogicalFlagsMOp, LogicalFlagsMOpImm, Lut4, MOpDestReg, MOpRegNum},
|
||||||
|
register::PRegFlagsPowerISA,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// covers instructions in PowerISA v3.1C Book I 2.5 Condition Register Instructions
|
||||||
|
pub fn test_cases_book_i_2_5_condition_register(retval: &mut Vec<TestCase>) {
|
||||||
|
macro_rules! cr_bit_logical_op {
|
||||||
|
(
|
||||||
|
$mnemonic:literal,
|
||||||
|
$encoding:literal,
|
||||||
|
$lut:expr
|
||||||
|
) => {{
|
||||||
|
retval.push(insn_single(
|
||||||
|
concat!($mnemonic, " 4*cr3+so, 4*cr1+gt, 4*cr5+lt"),
|
||||||
|
$encoding | 0x01e5a000,
|
||||||
|
None,
|
||||||
|
LogicalFlagsMOp::logical_flags(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(1).value,
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(5).value,
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(3).value,
|
||||||
|
],
|
||||||
|
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
|
||||||
|
let mut dest = src2.map(|v| Some(v.into()));
|
||||||
|
dest.so = Some((src0.cr_gt, src1.cr_lt).into());
|
||||||
|
dest
|
||||||
|
}),
|
||||||
|
$lut,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
concat!($mnemonic, " lt, gt, eq"),
|
||||||
|
$encoding | 0x00011000,
|
||||||
|
None,
|
||||||
|
LogicalFlagsMOp::logical_flags(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(0).value,
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(0).value,
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(0).value,
|
||||||
|
],
|
||||||
|
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
|
||||||
|
let mut dest = src2.map(|v| Some(v.into()));
|
||||||
|
dest.cr_lt = Some((src0.cr_gt, src1.cr_eq).into());
|
||||||
|
dest
|
||||||
|
}),
|
||||||
|
$lut,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
concat!($mnemonic, " gt, gt, eq"),
|
||||||
|
$encoding | 0x00211000,
|
||||||
|
None,
|
||||||
|
LogicalFlagsMOp::logical_flags(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(0)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(0).value,
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(0).value,
|
||||||
|
MOpRegNum::power_isa_cr_reg_imm(0).value,
|
||||||
|
],
|
||||||
|
LogicalFlagsMOpImm::from_swizzle_fn::<PRegFlagsPowerISA>(|src0, src1, src2| {
|
||||||
|
let mut dest = src2.map(|v| Some(v.into()));
|
||||||
|
dest.cr_gt = Some((src0.cr_gt, src1.cr_eq).into());
|
||||||
|
dest
|
||||||
|
}),
|
||||||
|
$lut,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
cr_bit_logical_op!("crand", 0x4c000202, Lut4::from_fn(|a, b| a & b));
|
||||||
|
cr_bit_logical_op!("crnand", 0x4c0001c2, Lut4::from_fn(|a, b| !(a & b)));
|
||||||
|
cr_bit_logical_op!("cror", 0x4c000382, Lut4::from_fn(|a, b| a | b));
|
||||||
|
cr_bit_logical_op!("crxor", 0x4c000182, Lut4::from_fn(|a, b| a ^ b));
|
||||||
|
cr_bit_logical_op!("crnor", 0x4c000042, Lut4::from_fn(|a, b| !(a | b)));
|
||||||
|
cr_bit_logical_op!("creqv", 0x4c000242, Lut4::from_fn(|a, b| a == b));
|
||||||
|
cr_bit_logical_op!("crandc", 0x4c000102, Lut4::from_fn(|a, b| a & !b));
|
||||||
|
cr_bit_logical_op!("crorc", 0x4c000342, Lut4::from_fn(|a, b| a | !b));
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue