forked from libre-chip/cpu
unit::alu_branch: implement for CompareMOp
This commit is contained in:
parent
67abfa2f5d
commit
225ceb0dfa
2 changed files with 12729 additions and 49 deletions
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
config::{CpuConfig, PhantomConstCpuConfig},
|
||||
instruction::{
|
||||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
||||
CommonMOpDefaultImm, CompareMOp, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
||||
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
||||
OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateMOp,
|
||||
},
|
||||
next_pc::CallStackOp,
|
||||
|
|
@ -19,7 +19,10 @@ use crate::{
|
|||
},
|
||||
unit::{DynUnit, DynUnitWrapper, UnitKind, UnitTrait},
|
||||
};
|
||||
use fayalite::{intern::Interned, module::wire_with_loc, prelude::*};
|
||||
use fayalite::{
|
||||
expr::CastToImpl, int::IntType, intern::Interned, module::wire_with_loc, prelude::*,
|
||||
ty::StaticType,
|
||||
};
|
||||
use std::{collections::HashMap, ops::RangeTo};
|
||||
|
||||
#[hdl]
|
||||
|
|
@ -293,14 +296,127 @@ fn shift_rotate<C: PhantomConstCpuConfig>(
|
|||
#[hdl]
|
||||
fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||
global_state: Expr<GlobalState>,
|
||||
pc: Expr<UInt<64>>,
|
||||
mop: Expr<CompareMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
||||
) -> Expr<TraceAsString<PRegValue>> {
|
||||
#[hdl]
|
||||
let GlobalState { flags_mode } = global_state;
|
||||
// TODO: finish
|
||||
PRegValue::zeroed().to_trace_as_string()
|
||||
#[hdl]
|
||||
let CompareMOp::<_, _, _> {
|
||||
common,
|
||||
compare_mode,
|
||||
} = mop;
|
||||
let config = common.dest.unit_num.config.ty();
|
||||
let (lhs, rhs) = match SrcCount::VALUE {
|
||||
1 => (
|
||||
src_values[0],
|
||||
Expr::into_trace_as_string(
|
||||
#[hdl]
|
||||
PRegValue {
|
||||
int_fp: CommonMOpDefaultImm::as_sint_dyn(common.imm)
|
||||
.cast_to_static::<UInt<64>>(),
|
||||
flags: PRegFlags::zeroed(),
|
||||
},
|
||||
),
|
||||
),
|
||||
2 => (src_values[0], src_values[1]),
|
||||
_ => todo!(),
|
||||
};
|
||||
#[hdl]
|
||||
let compare_result = wire();
|
||||
connect(compare_result, PRegValue::zeroed().to_trace_as_string());
|
||||
|
||||
#[hdl]
|
||||
let lhs_casted: SInt<65> = wire();
|
||||
connect(lhs_casted, 0_hdl_i65);
|
||||
#[hdl]
|
||||
let rhs_casted: SInt<65> = wire();
|
||||
connect(rhs_casted, 0_hdl_i65);
|
||||
#[hdl]
|
||||
let x86_sub_mode = wire();
|
||||
connect(x86_sub_mode, OutputIntegerMode.Full64());
|
||||
#[hdl]
|
||||
let x86_flags = wire();
|
||||
let zero_reg = PRegNum[config].const_zero();
|
||||
connect(
|
||||
x86_flags,
|
||||
add_sub(
|
||||
global_state,
|
||||
0u64.to_expr(),
|
||||
AddSubMOp::add_sub_i(
|
||||
zero_reg,
|
||||
repeat(zero_reg, ConstUsize),
|
||||
0.cast_to_static::<SInt<_>>(),
|
||||
x86_sub_mode,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
[rhs, lhs, PRegValue::zeroed().to_trace_as_string()].to_expr(),
|
||||
)
|
||||
.flags,
|
||||
);
|
||||
|
||||
#[hdl]
|
||||
let power_isa_flags = wire();
|
||||
connect(power_isa_flags, PRegFlags::zeroed());
|
||||
|
||||
{
|
||||
let PRegFlagsPowerISAView {
|
||||
unused: _,
|
||||
xer_ca: _,
|
||||
xer_ca32: _,
|
||||
xer_ov: _,
|
||||
xer_ov32: _,
|
||||
cr_lt,
|
||||
cr_gt,
|
||||
cr_eq,
|
||||
so,
|
||||
} = PRegFlags::view::<PRegFlagsPowerISA>(power_isa_flags);
|
||||
|
||||
let _ = so; // TODO: need to set from the global SO
|
||||
connect(cr_lt, lhs_casted.cmp_lt(rhs_casted));
|
||||
connect(cr_eq, lhs_casted.cmp_eq(rhs_casted));
|
||||
connect(cr_gt, !(cr_lt | cr_eq));
|
||||
}
|
||||
|
||||
let normal_compare = |x86_sub_mode_v: Expr<OutputIntegerMode>,
|
||||
do_cast: fn(Expr<UInt<64>>) -> Expr<SInt<65>>| {
|
||||
connect(x86_sub_mode, x86_sub_mode_v);
|
||||
connect(lhs_casted, do_cast(lhs.int_fp));
|
||||
connect(rhs_casted, do_cast(rhs.int_fp));
|
||||
#[hdl]
|
||||
match flags_mode {
|
||||
FlagsMode::PowerISA(_) => connect(compare_result.flags, power_isa_flags),
|
||||
FlagsMode::X86(_) => connect(compare_result.flags, x86_flags),
|
||||
}
|
||||
};
|
||||
|
||||
fn do_cast<T: IntType + StaticType>(v: Expr<UInt<64>>) -> Expr<SInt<65>>
|
||||
where
|
||||
UInt<64>: CastToImpl<T>,
|
||||
T: CastToImpl<SInt<65>>,
|
||||
{
|
||||
v.cast_to_static::<T>().cast_to_static::<SInt<65>>()
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
match compare_mode {
|
||||
CompareMode::U64 => normal_compare(OutputIntegerMode.Full64(), do_cast::<UInt<64>>),
|
||||
CompareMode::S64 => normal_compare(OutputIntegerMode.Full64(), do_cast::<SInt<64>>),
|
||||
CompareMode::U32 => normal_compare(OutputIntegerMode.ZeroExt32(), do_cast::<UInt<32>>),
|
||||
CompareMode::S32 => normal_compare(OutputIntegerMode.SignExt32(), do_cast::<SInt<32>>),
|
||||
CompareMode::U16 => normal_compare(OutputIntegerMode.ZeroExt16(), do_cast::<UInt<16>>),
|
||||
CompareMode::S16 => normal_compare(OutputIntegerMode.SignExt16(), do_cast::<SInt<16>>),
|
||||
CompareMode::U8 => normal_compare(OutputIntegerMode.ZeroExt8(), do_cast::<UInt<8>>),
|
||||
CompareMode::S8 => normal_compare(OutputIntegerMode.SignExt8(), do_cast::<SInt<8>>),
|
||||
CompareMode::CmpRBOne | CompareMode::CmpRBTwo | CompareMode::CmpEqB => {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
compare_result
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
|
|
@ -593,16 +709,10 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
|
|||
);
|
||||
}
|
||||
AluBranchMOp::<_, _>::Compare(mop) => {
|
||||
connect(
|
||||
dest_value,
|
||||
compare(global_state, mop_instance.pc, mop, src_values),
|
||||
);
|
||||
connect(dest_value, compare(global_state, mop, src_values));
|
||||
}
|
||||
AluBranchMOp::<_, _>::CompareI(mop) => {
|
||||
connect(
|
||||
dest_value,
|
||||
compare(global_state, mop_instance.pc, mop, src_values),
|
||||
);
|
||||
connect(dest_value, compare(global_state, mop, src_values));
|
||||
}
|
||||
AluBranchMOp::<_, _>::Branch(mop) => {
|
||||
let (dest_value_, predictor_op_, caused_cancel_) = branch(
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue