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},
|
config::{CpuConfig, PhantomConstCpuConfig},
|
||||||
instruction::{
|
instruction::{
|
||||||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
||||||
CommonMOpDefaultImm, CompareMOp, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
|
||||||
OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateMOp,
|
OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateMOp,
|
||||||
},
|
},
|
||||||
next_pc::CallStackOp,
|
next_pc::CallStackOp,
|
||||||
|
|
@ -19,7 +19,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
unit::{DynUnit, DynUnitWrapper, UnitKind, UnitTrait},
|
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};
|
use std::{collections::HashMap, ops::RangeTo};
|
||||||
|
|
||||||
#[hdl]
|
#[hdl]
|
||||||
|
|
@ -293,14 +296,127 @@ fn shift_rotate<C: PhantomConstCpuConfig>(
|
||||||
#[hdl]
|
#[hdl]
|
||||||
fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
fn compare<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
|
||||||
global_state: Expr<GlobalState>,
|
global_state: Expr<GlobalState>,
|
||||||
pc: Expr<UInt<64>>,
|
|
||||||
mop: Expr<CompareMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
mop: Expr<CompareMOp<PRegNum<C>, PRegNum<C>, SrcCount>>,
|
||||||
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
src_values: Expr<Array<TraceAsString<PRegValue>, { COMMON_MOP_SRC_LEN }>>,
|
||||||
) -> Expr<TraceAsString<PRegValue>> {
|
) -> Expr<TraceAsString<PRegValue>> {
|
||||||
#[hdl]
|
#[hdl]
|
||||||
let GlobalState { flags_mode } = global_state;
|
let GlobalState { flags_mode } = global_state;
|
||||||
// TODO: finish
|
#[hdl]
|
||||||
PRegValue::zeroed().to_trace_as_string()
|
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]
|
#[hdl]
|
||||||
|
|
@ -593,16 +709,10 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::Compare(mop) => {
|
AluBranchMOp::<_, _>::Compare(mop) => {
|
||||||
connect(
|
connect(dest_value, compare(global_state, mop, src_values));
|
||||||
dest_value,
|
|
||||||
compare(global_state, mop_instance.pc, mop, src_values),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::CompareI(mop) => {
|
AluBranchMOp::<_, _>::CompareI(mop) => {
|
||||||
connect(
|
connect(dest_value, compare(global_state, mop, src_values));
|
||||||
dest_value,
|
|
||||||
compare(global_state, mop_instance.pc, mop, src_values),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
AluBranchMOp::<_, _>::Branch(mop) => {
|
AluBranchMOp::<_, _>::Branch(mop) => {
|
||||||
let (dest_value_, predictor_op_, caused_cancel_) = branch(
|
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