unit::alu_branch: implement for CompareMOp

This commit is contained in:
Jacob Lifshay 2026-05-25 18:41:49 -07:00
parent 67abfa2f5d
commit 225ceb0dfa
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
2 changed files with 12729 additions and 49 deletions

View file

@ -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