unit::alu_branch: implement for LogicalMOp

This commit is contained in:
Jacob Lifshay 2026-05-26 19:05:19 -07:00
parent b25448a275
commit 42056ce6b5
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
5 changed files with 2378 additions and 1229 deletions

View file

@ -6,7 +6,7 @@ use crate::{
instruction::{
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
CommonMOpDefaultImm, CompareMOp, CompareMode, ConditionMode, LogicalFlagsMOp, LogicalMOp,
OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
Lut4, OutputIntegerMode, PRegNum, ReadSpecialMOp, ShiftRotateDestLogicOp, ShiftRotateMOp,
ShiftRotateMOpImm, ShiftRotateMode,
},
next_pc::CallStackOp,
@ -254,29 +254,122 @@ fn logical_flags<C: PhantomConstCpuConfig>(
}
#[hdl]
fn logical<C: PhantomConstCpuConfig>(
fn logical<C: PhantomConstCpuConfig, SrcCount: KnownSize>(
global_state: Expr<GlobalState>,
pc: Expr<UInt<64>>,
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<2>>>,
mop: Expr<LogicalMOp<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]
fn logical_i<C: PhantomConstCpuConfig>(
global_state: Expr<GlobalState>,
pc: Expr<UInt<64>>,
mop: Expr<LogicalMOp<PRegNum<C>, PRegNum<C>, ConstUsize<1>>>,
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()
let LogicalMOp::<_, _, _> { alu_common, lut } = mop;
#[hdl]
let AluCommonMOp::<_, _, _, _> {
common,
output_integer_mode,
} = alu_common;
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 lut4_output = wire();
connect(lut4_output, Lut4::output(lut, lhs.int_fp, rhs.int_fp));
#[hdl]
let logical_result: TraceAsString<PRegValue> = wire();
#[hdl]
let x86_sf = wire();
#[hdl]
match flags_mode {
FlagsMode::PowerISA(_) => {
let PRegFlagsPowerISAView {
unused,
xer_ca,
xer_ca32,
xer_ov,
xer_ov32,
cr_lt,
cr_gt,
cr_eq,
so,
} = PRegFlags::view::<PRegFlagsPowerISA>(logical_result.flags);
unused.clear();
connect(xer_ca, false);
connect(xer_ca32, false);
connect(xer_ov, false);
connect(xer_ov32, false);
let signed_result = logical_result.int_fp.cast_to_static::<SInt<64>>();
connect(cr_lt, signed_result.cmp_lt(0i64));
connect(cr_eq, signed_result.cmp_eq(0i64));
connect(cr_gt, !(cr_lt | cr_eq));
connect(so, false); // TODO: need to set from the global SO
}
FlagsMode::X86(_) => {
let PRegFlagsX86View {
unused,
cf,
zf,
sf,
of,
af,
pf,
df,
} = PRegFlags::view::<PRegFlagsX86>(logical_result.flags);
unused.clear();
connect(cf, false);
connect(zf, logical_result.int_fp.cmp_eq(0u64));
connect(sf, x86_sf);
connect(of, false);
connect(af, false);
connect(pf, logical_result.int_fp[..8].parity_even());
connect(df, false);
}
}
let connect_output = |width, signed| {
connect(x86_sf, logical_result.int_fp[width - 1]);
if signed {
connect(
logical_result.int_fp,
lut4_output
.cast_to(SInt[width])
.cast_to_static::<UInt<64>>(),
);
} else {
connect(
logical_result.int_fp,
lut4_output
.cast_to(UInt[width])
.cast_to_static::<UInt<64>>(),
);
}
};
#[hdl]
match output_integer_mode {
OutputIntegerMode::Full64 => connect_output(64, false),
OutputIntegerMode::DupLow32 => {
connect(x86_sf, logical_result.int_fp[31]);
let v = lut4_output.cast_to_static::<UInt<32>>();
connect_any(logical_result.int_fp, v | (v << 32));
}
OutputIntegerMode::ZeroExt32 => connect_output(32, false),
OutputIntegerMode::SignExt32 => connect_output(32, true),
OutputIntegerMode::ZeroExt16 => connect_output(16, false),
OutputIntegerMode::SignExt16 => connect_output(16, true),
OutputIntegerMode::ZeroExt8 => connect_output(8, false),
OutputIntegerMode::SignExt8 => connect_output(8, true),
}
logical_result
}
#[hdl]
@ -897,16 +990,10 @@ pub fn alu_branch(config: PhantomConst<CpuConfig>, unit_index: usize) {
connect(dest_value, logical_flags(global_state, mop, src_values));
}
AluBranchMOp::<_, _>::Logical(mop) => {
connect(
dest_value,
logical(global_state, mop_instance.pc, mop, src_values),
);
connect(dest_value, logical(global_state, mop, src_values));
}
AluBranchMOp::<_, _>::LogicalI(mop) => {
connect(
dest_value,
logical_i(global_state, mop_instance.pc, mop, src_values),
);
connect(dest_value, logical(global_state, mop, src_values));
}
AluBranchMOp::<_, _>::ShiftRotate(mop) => {
connect(dest_value, shift_rotate(global_state, mop, src_values));
@ -1022,7 +1109,7 @@ impl UnitTrait for AluBranch {
self.module
}
fn cd(&self, this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
fn cd(&self, _this: Expr<Self::Type>) -> Option<Expr<ClockDomain>> {
None
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff