forked from libre-chip/cpu
decode fixed-point compare instructions
This commit is contained in:
parent
a4b052f5f3
commit
3a35a698e2
6 changed files with 3730 additions and 1532 deletions
|
|
@ -1,7 +1,9 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use crate::instruction::{AddSubMOp, MOpDestReg, MOpRegNum, OutputIntegerMode};
|
use crate::instruction::{
|
||||||
|
AddSubMOp, CompareMOp, CompareMode, MOpDestReg, MOpRegNum, OutputIntegerMode,
|
||||||
|
};
|
||||||
use crate::powerisa_instructions_xml::{
|
use crate::powerisa_instructions_xml::{
|
||||||
InstructionBitFieldName, InstructionBitFieldsInner, TextLineItem,
|
InstructionBitFieldName, InstructionBitFieldsInner, TextLineItem,
|
||||||
};
|
};
|
||||||
|
|
@ -177,6 +179,8 @@ macro_rules! impl_fields {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_fields! {
|
impl_fields! {
|
||||||
|
#[name = "BF"]
|
||||||
|
struct FieldBF(FieldCrf);
|
||||||
#[name = "RA"]
|
#[name = "RA"]
|
||||||
struct FieldRA(FieldGpr);
|
struct FieldRA(FieldGpr);
|
||||||
#[name = "RB"]
|
#[name = "RB"]
|
||||||
|
|
@ -189,12 +193,16 @@ impl_fields! {
|
||||||
struct FieldSi0(SInt<18>);
|
struct FieldSi0(SInt<18>);
|
||||||
#[name = "si1"]
|
#[name = "si1"]
|
||||||
struct FieldSi1(UInt<16>);
|
struct FieldSi1(UInt<16>);
|
||||||
|
#[name = "UI"]
|
||||||
|
struct FieldUI(UInt<16>);
|
||||||
#[name = "d0"]
|
#[name = "d0"]
|
||||||
struct FieldAddPcISD0(SInt<10>);
|
struct FieldAddPcISD0(SInt<10>);
|
||||||
#[name = "d1"]
|
#[name = "d1"]
|
||||||
struct FieldAddPcISD1(UInt<5>);
|
struct FieldAddPcISD1(UInt<5>);
|
||||||
#[name = "d2"]
|
#[name = "d2"]
|
||||||
struct FieldAddPcISD2(UInt<1>);
|
struct FieldAddPcISD2(UInt<1>);
|
||||||
|
#[name = "L"]
|
||||||
|
struct FieldL(Bool);
|
||||||
#[name = "OE"]
|
#[name = "OE"]
|
||||||
struct FieldOE(Bool);
|
struct FieldOE(Bool);
|
||||||
#[name = "R"]
|
#[name = "R"]
|
||||||
|
|
@ -203,11 +211,18 @@ impl_fields! {
|
||||||
struct FieldRc(Bool);
|
struct FieldRc(Bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// general-purpose register
|
||||||
#[hdl]
|
#[hdl]
|
||||||
struct FieldGpr {
|
struct FieldGpr {
|
||||||
reg_num: UInt<5>,
|
reg_num: UInt<5>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// condition register field -- a 4-bit field of the condition register
|
||||||
|
#[hdl]
|
||||||
|
struct FieldCrf {
|
||||||
|
reg_num: UInt<3>,
|
||||||
|
}
|
||||||
|
|
||||||
fn gpr(this: impl ToExpr<Type = FieldGpr>) -> Expr<MOpRegNum> {
|
fn gpr(this: impl ToExpr<Type = FieldGpr>) -> Expr<MOpRegNum> {
|
||||||
MOpRegNum::power_isa_gpr_reg(this.to_expr().reg_num)
|
MOpRegNum::power_isa_gpr_reg(this.to_expr().reg_num)
|
||||||
}
|
}
|
||||||
|
|
@ -216,6 +231,10 @@ fn gpr_or_zero(this: impl ToExpr<Type = FieldGpr>) -> Expr<MOpRegNum> {
|
||||||
MOpRegNum::power_isa_gpr_or_zero_reg(this.to_expr().reg_num)
|
MOpRegNum::power_isa_gpr_or_zero_reg(this.to_expr().reg_num)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn crf(this: impl ToExpr<Type = FieldCrf>) -> Expr<MOpRegNum> {
|
||||||
|
MOpRegNum::power_isa_cr_reg(this.to_expr().reg_num)
|
||||||
|
}
|
||||||
|
|
||||||
impl DecodeState {
|
impl DecodeState {
|
||||||
fn form(&self) -> &'static str {
|
fn form(&self) -> &'static str {
|
||||||
let mut title_words = self
|
let mut title_words = self
|
||||||
|
|
@ -839,6 +858,172 @@ impl DecodeState {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/// for `cmpi`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_cmpi(&mut self) {
|
||||||
|
self.decode_scope(|this, (FieldBF(bf), FieldL(l), FieldRA(ra), FieldSI(si))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
#[hdl]
|
||||||
|
let compare_mode = wire();
|
||||||
|
#[hdl]
|
||||||
|
if l {
|
||||||
|
connect(compare_mode, CompareMode.S64());
|
||||||
|
} else {
|
||||||
|
connect(compare_mode, CompareMode.S32());
|
||||||
|
}
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
CompareMOp::compare_i(
|
||||||
|
MOpDestReg::new([crf(bf)], []),
|
||||||
|
[gpr(ra).value],
|
||||||
|
si.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.Full64(),
|
||||||
|
compare_mode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// for `cmp`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_cmp(&mut self) {
|
||||||
|
self.decode_scope(|this, (FieldBF(bf), FieldL(l), FieldRA(ra), FieldRB(rb))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
#[hdl]
|
||||||
|
let compare_mode = wire();
|
||||||
|
#[hdl]
|
||||||
|
if l {
|
||||||
|
connect(compare_mode, CompareMode.S64());
|
||||||
|
} else {
|
||||||
|
connect(compare_mode, CompareMode.S32());
|
||||||
|
}
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new([crf(bf)], []),
|
||||||
|
[gpr(ra).value, gpr(rb).value],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.Full64(),
|
||||||
|
compare_mode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// for `cmpli`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_cmpli(&mut self) {
|
||||||
|
self.decode_scope(|this, (FieldBF(bf), FieldL(l), FieldRA(ra), FieldUI(ui))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
#[hdl]
|
||||||
|
let compare_mode = wire();
|
||||||
|
#[hdl]
|
||||||
|
if l {
|
||||||
|
connect(compare_mode, CompareMode.U64());
|
||||||
|
} else {
|
||||||
|
connect(compare_mode, CompareMode.U32());
|
||||||
|
}
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
CompareMOp::compare_i(
|
||||||
|
MOpDestReg::new([crf(bf)], []),
|
||||||
|
[gpr(ra).value],
|
||||||
|
ui.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.Full64(),
|
||||||
|
compare_mode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// for `cmpl`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_cmpl(&mut self) {
|
||||||
|
self.decode_scope(|this, (FieldBF(bf), FieldL(l), FieldRA(ra), FieldRB(rb))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
#[hdl]
|
||||||
|
let compare_mode = wire();
|
||||||
|
#[hdl]
|
||||||
|
if l {
|
||||||
|
connect(compare_mode, CompareMode.U64());
|
||||||
|
} else {
|
||||||
|
connect(compare_mode, CompareMode.U32());
|
||||||
|
}
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new([crf(bf)], []),
|
||||||
|
[gpr(ra).value, gpr(rb).value],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.Full64(),
|
||||||
|
compare_mode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// for `cmprb`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_cmprb(&mut self) {
|
||||||
|
self.decode_scope(|this, (FieldBF(bf), FieldL(l), FieldRA(ra), FieldRB(rb))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
#[hdl]
|
||||||
|
let compare_mode = wire();
|
||||||
|
#[hdl]
|
||||||
|
if l {
|
||||||
|
connect(compare_mode, CompareMode.CmpRBTwo());
|
||||||
|
} else {
|
||||||
|
connect(compare_mode, CompareMode.CmpRBOne());
|
||||||
|
}
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new([crf(bf)], []),
|
||||||
|
[gpr(ra).value, gpr(rb).value],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.Full64(),
|
||||||
|
compare_mode,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/// for `cmpeqb`
|
||||||
|
#[hdl]
|
||||||
|
fn decode_cmpeqb(&mut self) {
|
||||||
|
self.decode_scope(|this, (FieldBF(bf), FieldRA(ra), FieldRB(rb))| {
|
||||||
|
// TODO: handle SO propagation
|
||||||
|
connect(
|
||||||
|
ArrayVec::len(this.output),
|
||||||
|
1usize.cast_to_static::<Length<_>>(),
|
||||||
|
);
|
||||||
|
connect(
|
||||||
|
this.output[0],
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new([crf(bf)], []),
|
||||||
|
[gpr(ra).value, gpr(rb).value],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
OutputIntegerMode.Full64(),
|
||||||
|
CompareMode.CmpEqB(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DecodeFn = fn(&mut DecodeState);
|
type DecodeFn = fn(&mut DecodeState);
|
||||||
|
|
@ -982,12 +1167,12 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
|
||||||
// TODO
|
// TODO
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
(&["cmpi", "cmp", "cmpli", "cmpl"], |_state| {
|
(&["cmpi"], DecodeState::decode_cmpi),
|
||||||
// TODO
|
(&["cmp"], DecodeState::decode_cmp),
|
||||||
}),
|
(&["cmpli"], DecodeState::decode_cmpli),
|
||||||
(&["cmprb", "cmpeqb"], |_state| {
|
(&["cmpl"], DecodeState::decode_cmpl),
|
||||||
// TODO
|
(&["cmprb"], DecodeState::decode_cmprb),
|
||||||
}),
|
(&["cmpeqb"], DecodeState::decode_cmpeqb),
|
||||||
(&["twi", "tw", "tdi", "td"], |_state| {
|
(&["twi", "tw", "tdi", "td"], |_state| {
|
||||||
// TODO
|
// TODO
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -736,6 +736,120 @@ impl<DestReg: Type, SrcRegWidth: Size> LogicalMOp<DestReg, SrcRegWidth> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
pub enum CompareMode {
|
||||||
|
U64,
|
||||||
|
S64,
|
||||||
|
U32,
|
||||||
|
S32,
|
||||||
|
U16,
|
||||||
|
S16,
|
||||||
|
U8,
|
||||||
|
S8,
|
||||||
|
/// compare one ranged byte -- like the PowerISA `cmprb _, 0, ..` instruction
|
||||||
|
CmpRBOne,
|
||||||
|
/// compare two ranged bytes -- like the PowerISA `cmprb _, 1, ..` instruction
|
||||||
|
CmpRBTwo,
|
||||||
|
/// like the PowerISA `cmpeqb` instruction
|
||||||
|
CmpEqB,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HdlPartialEqImpl<Self> for CompareMode {
|
||||||
|
#[track_caller]
|
||||||
|
fn cmp_value_eq(
|
||||||
|
lhs: Self,
|
||||||
|
lhs_value: Cow<'_, Self::SimValue>,
|
||||||
|
rhs: Self,
|
||||||
|
rhs_value: Cow<'_, Self::SimValue>,
|
||||||
|
) -> bool {
|
||||||
|
SimValue::opaque(&SimValue::from_value(lhs, lhs_value.into_owned()))
|
||||||
|
== SimValue::opaque(&SimValue::from_value(rhs, rhs_value.into_owned()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn cmp_sim_value_eq(
|
||||||
|
lhs: Cow<'_, SimValue<Self>>,
|
||||||
|
rhs: Cow<'_, SimValue<Self>>,
|
||||||
|
) -> SimValue<Bool> {
|
||||||
|
(SimValue::opaque(&lhs) == SimValue::opaque(&rhs)).to_sim_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn cmp_sim_value_ne(
|
||||||
|
lhs: Cow<'_, SimValue<Self>>,
|
||||||
|
rhs: Cow<'_, SimValue<Self>>,
|
||||||
|
) -> SimValue<Bool> {
|
||||||
|
(SimValue::opaque(&lhs) != SimValue::opaque(&rhs)).to_sim_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn cmp_expr_eq(lhs: Expr<Self>, rhs: Expr<Self>) -> Expr<Bool> {
|
||||||
|
lhs.cast_to_bits().cmp_eq(rhs.cast_to_bits())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
common_mop_struct! {
|
||||||
|
#[mapped(<NewDestReg, NewSrcRegWidth> CompareMOp<NewDestReg, NewSrcRegWidth, SrcCount>)]
|
||||||
|
#[hdl(cmp_eq)]
|
||||||
|
pub struct CompareMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
|
#[common]
|
||||||
|
pub alu_common: AluCommonMOp<DestReg, SrcRegWidth, SrcCount>,
|
||||||
|
pub compare_mode: CompareMode,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<DestReg: Type, SrcRegWidth: Size> CompareMOp<DestReg, SrcRegWidth, ConstUsize<2>> {
|
||||||
|
#[hdl]
|
||||||
|
pub fn compare<Target: MOpTrait>(
|
||||||
|
dest: impl ToExpr<Type = DestReg>,
|
||||||
|
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 2>>,
|
||||||
|
imm: impl ToExpr<Type = SInt<{ COMMON_MOP_2_IMM_WIDTH }>>,
|
||||||
|
output_integer_mode: impl ToExpr<Type = OutputIntegerMode>,
|
||||||
|
compare_mode: impl ToExpr<Type = CompareMode>,
|
||||||
|
) -> Expr<Target>
|
||||||
|
where
|
||||||
|
Self: MOpInto<Target>,
|
||||||
|
{
|
||||||
|
MOpInto::mop_into(
|
||||||
|
#[hdl]
|
||||||
|
CompareMOp {
|
||||||
|
alu_common: #[hdl]
|
||||||
|
AluCommonMOp {
|
||||||
|
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||||
|
output_integer_mode,
|
||||||
|
},
|
||||||
|
compare_mode,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<DestReg: Type, SrcRegWidth: Size> CompareMOp<DestReg, SrcRegWidth, ConstUsize<1>> {
|
||||||
|
#[hdl]
|
||||||
|
pub fn compare_i<Target: MOpTrait>(
|
||||||
|
dest: impl ToExpr<Type = DestReg>,
|
||||||
|
src: impl ToExpr<Type = Array<UIntType<SrcRegWidth>, 1>>,
|
||||||
|
imm: impl ToExpr<Type = SInt<{ COMMON_MOP_1_IMM_WIDTH }>>,
|
||||||
|
output_integer_mode: impl ToExpr<Type = OutputIntegerMode>,
|
||||||
|
compare_mode: impl ToExpr<Type = CompareMode>,
|
||||||
|
) -> Expr<Target>
|
||||||
|
where
|
||||||
|
Self: MOpInto<Target>,
|
||||||
|
{
|
||||||
|
MOpInto::mop_into(
|
||||||
|
#[hdl]
|
||||||
|
CompareMOp {
|
||||||
|
alu_common: #[hdl]
|
||||||
|
AluCommonMOp {
|
||||||
|
common: CommonMOp::new(0_hdl_u0, dest, src, Expr::as_dyn_int(imm.to_expr())),
|
||||||
|
output_integer_mode,
|
||||||
|
},
|
||||||
|
compare_mode,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
common_mop_struct! {
|
common_mop_struct! {
|
||||||
#[mapped(<NewDestReg, NewSrcRegWidth> BranchMOp<NewDestReg, NewSrcRegWidth>)]
|
#[mapped(<NewDestReg, NewSrcRegWidth> BranchMOp<NewDestReg, NewSrcRegWidth>)]
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
|
|
@ -753,6 +867,8 @@ mop_enum! {
|
||||||
AddSub(AddSubMOp<DestReg, SrcRegWidth, ConstUsize<3>>),
|
AddSub(AddSubMOp<DestReg, SrcRegWidth, ConstUsize<3>>),
|
||||||
AddSubI(AddSubMOp<DestReg, SrcRegWidth, ConstUsize<2>>),
|
AddSubI(AddSubMOp<DestReg, SrcRegWidth, ConstUsize<2>>),
|
||||||
Logical(LogicalMOp<DestReg, SrcRegWidth>),
|
Logical(LogicalMOp<DestReg, SrcRegWidth>),
|
||||||
|
Compare(CompareMOp<DestReg, SrcRegWidth, ConstUsize<2>>),
|
||||||
|
CompareI(CompareMOp<DestReg, SrcRegWidth, ConstUsize<1>>),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ impl MOpRegNum {
|
||||||
} else {
|
} else {
|
||||||
connect_any(
|
connect_any(
|
||||||
power_isa_cr_reg.value,
|
power_isa_cr_reg.value,
|
||||||
Self::POWER_ISA_CR_1_THRU_7_REG_NUMS.start + field_num,
|
Self::POWER_ISA_CR_1_THRU_7_REG_NUMS.start - 1 + field_num,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
power_isa_cr_reg
|
power_isa_cr_reg
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::CpuConfig,
|
config::CpuConfig,
|
||||||
instruction::{
|
instruction::{
|
||||||
AddSubMOp, AluBranchMOp, AluCommonMOp, COMMON_MOP_SRC_LEN, CommonMOp, LogicalMOp, MOpTrait,
|
AddSubMOp, AluBranchMOp, AluCommonMOp, COMMON_MOP_SRC_LEN, CommonMOp, CompareMOp,
|
||||||
OutputIntegerMode, RenamedMOp, UnitOutRegNum,
|
LogicalMOp, MOpTrait, OutputIntegerMode, RenamedMOp, UnitOutRegNum,
|
||||||
},
|
},
|
||||||
register::{FlagsMode, PRegFlagsPowerISA, PRegFlagsX86, PRegValue},
|
register::{FlagsMode, PRegFlagsPowerISA, PRegFlagsX86, PRegValue},
|
||||||
unit::{
|
unit::{
|
||||||
|
|
@ -244,6 +244,20 @@ fn logical(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[hdl]
|
||||||
|
fn compare<SrcCount: KnownSize>(
|
||||||
|
mop: Expr<CompareMOp<UnitOutRegNum<DynSize>, DynSize, SrcCount>>,
|
||||||
|
flags_mode: Expr<FlagsMode>,
|
||||||
|
src_values: Expr<Array<PRegValue, { COMMON_MOP_SRC_LEN }>>,
|
||||||
|
) -> Expr<UnitResultCompleted<()>> {
|
||||||
|
// TODO: finish
|
||||||
|
#[hdl]
|
||||||
|
UnitResultCompleted::<_> {
|
||||||
|
value: PRegValue::zeroed(),
|
||||||
|
extra_out: (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[hdl_module]
|
#[hdl_module]
|
||||||
pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -336,6 +350,40 @@ pub fn alu_branch(config: &CpuConfig, unit_index: usize) {
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
AluBranchMOp::<_, _>::Compare(mop) => connect(
|
||||||
|
unit_base.execute_end,
|
||||||
|
HdlSome(
|
||||||
|
#[hdl]
|
||||||
|
ExecuteEnd::<_, _> {
|
||||||
|
unit_output: #[hdl]
|
||||||
|
UnitOutput::<_, _> {
|
||||||
|
which: MOpTrait::dest_reg(mop),
|
||||||
|
result: UnitResult[()].Completed(compare(
|
||||||
|
mop,
|
||||||
|
global_state.flags_mode,
|
||||||
|
src_values,
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
AluBranchMOp::<_, _>::CompareI(mop) => connect(
|
||||||
|
unit_base.execute_end,
|
||||||
|
HdlSome(
|
||||||
|
#[hdl]
|
||||||
|
ExecuteEnd::<_, _> {
|
||||||
|
unit_output: #[hdl]
|
||||||
|
UnitOutput::<_, _> {
|
||||||
|
which: MOpTrait::dest_reg(mop),
|
||||||
|
result: UnitResult[()].Completed(compare(
|
||||||
|
mop,
|
||||||
|
global_state.flags_mode,
|
||||||
|
src_values,
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -3,7 +3,9 @@
|
||||||
|
|
||||||
use cpu::{
|
use cpu::{
|
||||||
decoder::simple_power_isa::decode_one_insn,
|
decoder::simple_power_isa::decode_one_insn,
|
||||||
instruction::{AddSubMOp, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode},
|
instruction::{
|
||||||
|
AddSubMOp, CompareMOp, CompareMode, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode,
|
||||||
|
},
|
||||||
util::array_vec::ArrayVec,
|
util::array_vec::ArrayVec,
|
||||||
};
|
};
|
||||||
use fayalite::{prelude::*, sim::vcd::VcdWriterDecls, util::RcWriter};
|
use fayalite::{prelude::*, sim::vcd::VcdWriterDecls, util::RcWriter};
|
||||||
|
|
@ -486,6 +488,181 @@ fn test_cases() -> Vec<TestCase> {
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpi 3, 0, 4, 0x1234",
|
||||||
|
0x2d841234,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare_i(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value],
|
||||||
|
0x1234.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::S32(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpi 3, 1, 4, -0x7655",
|
||||||
|
0x2da489ab,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare_i(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value],
|
||||||
|
(0x89abu16 as i16).cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::S64(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmp 3, 0, 4, 5",
|
||||||
|
0x7d842800,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::S32(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmp 3, 1, 4, 5",
|
||||||
|
0x7da42800,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::S64(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpli 3, 0, 4, 0x1234",
|
||||||
|
0x29841234,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare_i(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value],
|
||||||
|
0x1234.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::U32(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpli 3, 1, 4, 0x89ab",
|
||||||
|
0x29a489ab,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare_i(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value],
|
||||||
|
0x89ab.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::U64(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpl 3, 0, 4, 5",
|
||||||
|
0x7d842840,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::U32(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpl 3, 1, 4, 5",
|
||||||
|
0x7da42840,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::U64(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmprb 3, 0, 4, 5",
|
||||||
|
0x7d842980,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::CmpRBOne(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmprb 3, 1, 4, 5",
|
||||||
|
0x7da42980,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::CmpRBTwo(),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
retval.push(insn_single(
|
||||||
|
"cmpeqb 3, 4, 5",
|
||||||
|
0x7d8429c0,
|
||||||
|
None,
|
||||||
|
CompareMOp::compare(
|
||||||
|
MOpDestReg::new_sim(&[MOpRegNum::power_isa_cr_reg_num(3)], &[]),
|
||||||
|
[
|
||||||
|
MOpRegNum::power_isa_gpr_reg(4_hdl_u5).value,
|
||||||
|
MOpRegNum::power_isa_gpr_reg(5_hdl_u5).value,
|
||||||
|
],
|
||||||
|
0.cast_to_static::<SInt<_>>(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
OutputIntegerMode::Full64(),
|
||||||
|
#[hdl(sim)]
|
||||||
|
CompareMode::CmpEqB(),
|
||||||
|
),
|
||||||
|
));
|
||||||
retval
|
retval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue