unit::alu_branch::compare: implement CmpRBOne/CmpRBTwo/CmpEqB
All checks were successful
/ test (pull_request) Successful in 5m56s
/ test (push) Successful in 6m50s

This commit is contained in:
Jacob Lifshay 2026-05-28 19:12:41 -07:00
parent 7481d079d5
commit 7acfaebfde
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
5 changed files with 5347 additions and 356 deletions

View file

@ -927,9 +927,17 @@ fn compare<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
} = 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));
// create separate wires to avoid a combinatorial loop
#[hdl]
let power_isa_cr_lt = wire();
#[hdl]
let power_isa_cr_eq = wire();
connect(power_isa_cr_lt, lhs_casted.cmp_lt(rhs_casted));
connect(power_isa_cr_eq, lhs_casted.cmp_eq(rhs_casted));
connect(cr_lt, power_isa_cr_lt);
connect(cr_eq, power_isa_cr_eq);
connect(cr_gt, !(power_isa_cr_lt | power_isa_cr_eq));
}
let normal_compare = |x86_sub_mode_v: Expr<OutputIntegerMode>,
@ -937,11 +945,6 @@ fn compare<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
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(output.flags, power_isa_flags),
FlagsMode::X86(_) => connect(output.flags, x86_flags),
}
};
fn do_cast<T: IntType + StaticType>(v: Expr<UInt<64>>) -> Expr<SInt<65>>
@ -952,6 +955,42 @@ fn compare<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
v.cast_to_static::<T>().cast_to_static::<SInt<65>>()
}
let connect_cmprb_cmpeqb_output = |matches| {
connect(
power_isa_flags,
PRegFlags::from_view::<PRegFlagsPowerISA>(PRegFlagsPowerISAView {
cr_gt: matches,
..PRegFlagsPowerISAView::splat(false.to_expr())
}),
);
// this isn't specifically matching any x86 instruction,
// so this can be changed as necessary.
connect(
x86_flags,
PRegFlags::from_view::<PRegFlagsX86>(PRegFlagsX86View {
zf: matches,
..PRegFlagsX86View::splat(false.to_expr())
}),
);
};
#[hdl]
let cmprb_cmpeqb_byte = wire();
connect(cmprb_cmpeqb_byte, lhs.int_fp.cast_to_static::<UInt<8>>());
#[hdl]
let cmprb_low_0: UInt<8> = wire();
connect_any(cmprb_low_0, rhs.int_fp[0..8]);
#[hdl]
let cmprb_high_0: UInt<8> = wire();
connect_any(cmprb_high_0, rhs.int_fp[8..16]);
#[hdl]
let cmprb_low_1: UInt<8> = wire();
connect_any(cmprb_low_1, rhs.int_fp[16..24]);
#[hdl]
let cmprb_high_1: UInt<8> = wire();
connect_any(cmprb_high_1, rhs.int_fp[24..32]);
#[hdl]
match compare_mode {
CompareMode::U64 => normal_compare(OutputIntegerMode.Full64(), do_cast::<UInt<64>>),
@ -962,9 +1001,28 @@ fn compare<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
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
}
CompareMode::CmpRBOne => connect_cmprb_cmpeqb_output(
cmprb_cmpeqb_byte.cmp_ge(cmprb_low_0) & cmprb_cmpeqb_byte.cmp_le(cmprb_high_0),
),
CompareMode::CmpRBTwo => connect_cmprb_cmpeqb_output(
(cmprb_cmpeqb_byte.cmp_ge(cmprb_low_0) & cmprb_cmpeqb_byte.cmp_le(cmprb_high_0))
| (cmprb_cmpeqb_byte.cmp_ge(cmprb_low_1) & cmprb_cmpeqb_byte.cmp_le(cmprb_high_1)),
),
CompareMode::CmpEqB => connect_cmprb_cmpeqb_output(
rhs.int_fp
.cast_bits_to(u64::to_le_bytes(0).ty())
.into_iter()
.map(|b| cmprb_cmpeqb_byte.cmp_eq(b))
.collect::<Vec<_>>()
.cast_to_bits()
.any_one_bits(),
),
}
#[hdl]
match flags_mode {
FlagsMode::PowerISA(_) => connect(output.flags, power_isa_flags),
FlagsMode::X86(_) => connect(output.flags, x86_flags),
}
}

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