2024-10-14 16:28:13 -07:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
|
// See Notices.txt for copyright information
|
2024-10-13 01:37:36 -07:00
|
|
|
use fayalite::prelude::*;
|
|
|
|
|
|
|
|
|
|
#[hdl]
|
|
|
|
|
pub enum FlagsMode {
|
|
|
|
|
PowerISA(PRegFlagsPowerISA),
|
|
|
|
|
X86(PRegFlagsX86),
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-19 23:54:41 -08:00
|
|
|
#[hdl(cmp_eq)]
|
2024-10-13 01:37:36 -07:00
|
|
|
pub struct PRegFlagsPowerISA {}
|
|
|
|
|
|
|
|
|
|
impl PRegFlagsPowerISA {
|
|
|
|
|
pub fn xer_ca(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ca_x86_cf
|
|
|
|
|
}
|
|
|
|
|
pub fn xer_ca32(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ca32_x86_af
|
|
|
|
|
}
|
|
|
|
|
pub fn xer_ov(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ov_x86_of
|
|
|
|
|
}
|
|
|
|
|
pub fn xer_ov32(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ov32_x86_df
|
|
|
|
|
}
|
|
|
|
|
/// both `CR<N>.SO` and `XER.SO` since instructions that write to both always write the same value
|
|
|
|
|
pub fn so(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_so
|
|
|
|
|
}
|
|
|
|
|
pub fn cr_lt(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_cr_lt_x86_sf
|
|
|
|
|
}
|
|
|
|
|
pub fn cr_gt(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_cr_gt_x86_pf
|
|
|
|
|
}
|
|
|
|
|
pub fn cr_eq(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_cr_eq_x86_zf
|
|
|
|
|
}
|
|
|
|
|
#[hdl]
|
|
|
|
|
pub fn clear_unused(flags: impl ToExpr<Type = PRegFlags>) {
|
2025-02-20 20:24:14 -08:00
|
|
|
// list all flags explicitly so we don't miss handling any new flags
|
2024-10-13 01:37:36 -07:00
|
|
|
#[hdl]
|
2025-02-20 20:24:14 -08:00
|
|
|
let PRegFlags {
|
|
|
|
|
pwr_ca_x86_cf: _,
|
|
|
|
|
pwr_ca32_x86_af: _,
|
|
|
|
|
pwr_ov_x86_of: _,
|
|
|
|
|
pwr_ov32_x86_df: _,
|
|
|
|
|
pwr_cr_lt_x86_sf: _,
|
|
|
|
|
pwr_cr_gt_x86_pf: _,
|
|
|
|
|
pwr_cr_eq_x86_zf: _,
|
|
|
|
|
pwr_so: _,
|
|
|
|
|
} = flags;
|
2024-10-13 01:37:36 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-19 23:54:41 -08:00
|
|
|
#[hdl(cmp_eq)]
|
2024-10-13 01:37:36 -07:00
|
|
|
pub struct PRegFlagsX86 {}
|
|
|
|
|
|
|
|
|
|
impl PRegFlagsX86 {
|
|
|
|
|
pub fn cf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ca_x86_cf
|
|
|
|
|
}
|
|
|
|
|
pub fn zf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_cr_eq_x86_zf
|
|
|
|
|
}
|
|
|
|
|
pub fn sf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_cr_lt_x86_sf
|
|
|
|
|
}
|
|
|
|
|
pub fn of(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ov_x86_of
|
|
|
|
|
}
|
|
|
|
|
pub fn af(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ca32_x86_af
|
|
|
|
|
}
|
|
|
|
|
pub fn pf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_cr_gt_x86_pf
|
|
|
|
|
}
|
|
|
|
|
pub fn df(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
|
|
|
|
flags.to_expr().pwr_ov32_x86_df
|
|
|
|
|
}
|
|
|
|
|
#[hdl]
|
|
|
|
|
pub fn clear_unused(flags: impl ToExpr<Type = PRegFlags>) {
|
2025-02-20 20:24:14 -08:00
|
|
|
// list all flags explicitly so we don't miss handling any new flags
|
2024-10-13 01:37:36 -07:00
|
|
|
#[hdl]
|
2025-02-20 20:24:14 -08:00
|
|
|
let PRegFlags {
|
|
|
|
|
pwr_ca_x86_cf: _,
|
|
|
|
|
pwr_ca32_x86_af: _,
|
|
|
|
|
pwr_ov_x86_of: _,
|
|
|
|
|
pwr_ov32_x86_df: _,
|
|
|
|
|
pwr_cr_lt_x86_sf: _,
|
|
|
|
|
pwr_cr_gt_x86_pf: _,
|
|
|
|
|
pwr_cr_eq_x86_zf: _,
|
|
|
|
|
pwr_so: unused1,
|
|
|
|
|
} = flags;
|
|
|
|
|
connect(unused1, false);
|
2024-10-13 01:37:36 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-19 23:54:41 -08:00
|
|
|
#[hdl(cmp_eq)]
|
2024-10-13 01:37:36 -07:00
|
|
|
/// this is *not* the same as any particular ISA's flags register,
|
|
|
|
|
/// on PowerISA it is a combination of some bits from XER with a single 4-bit CR field.
|
|
|
|
|
///
|
|
|
|
|
/// Accessor functions depend on the ISA:
|
|
|
|
|
///
|
|
|
|
|
/// * PowerISA: [`struct@PRegFlagsPowerISA`]
|
|
|
|
|
/// * x86: [`struct@PRegFlagsX86`]
|
|
|
|
|
pub struct PRegFlags {
|
|
|
|
|
pwr_ca_x86_cf: Bool,
|
|
|
|
|
pwr_ca32_x86_af: Bool,
|
|
|
|
|
pwr_ov_x86_of: Bool,
|
|
|
|
|
pwr_ov32_x86_df: Bool,
|
|
|
|
|
pwr_cr_lt_x86_sf: Bool,
|
|
|
|
|
pwr_cr_gt_x86_pf: Bool,
|
|
|
|
|
pwr_cr_eq_x86_zf: Bool,
|
|
|
|
|
pwr_so: Bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PRegFlags {
|
|
|
|
|
/// if trying to set all fields individually, prefer using the individual accessor
|
|
|
|
|
/// functions and [`PRegFlagsPowerISA::clear_unused()`]/[`PRegFlagsX86::clear_unused()`]/etc.
|
|
|
|
|
#[hdl]
|
|
|
|
|
pub fn zeroed() -> Expr<PRegFlags> {
|
|
|
|
|
#[hdl]
|
|
|
|
|
PRegFlags {
|
|
|
|
|
pwr_ca_x86_cf: false,
|
|
|
|
|
pwr_ca32_x86_af: false,
|
|
|
|
|
pwr_ov_x86_of: false,
|
|
|
|
|
pwr_ov32_x86_df: false,
|
|
|
|
|
pwr_cr_lt_x86_sf: false,
|
|
|
|
|
pwr_cr_gt_x86_pf: false,
|
|
|
|
|
pwr_cr_eq_x86_zf: false,
|
|
|
|
|
pwr_so: false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-19 23:54:41 -08:00
|
|
|
#[hdl(cmp_eq)]
|
2024-10-13 01:37:36 -07:00
|
|
|
/// Unit output register's value -- a combination of an integer/fp register
|
|
|
|
|
/// and flags register and CR field.
|
|
|
|
|
///
|
|
|
|
|
/// Register Renaming will independently rename the ISA-level integer/fp
|
|
|
|
|
/// register, flags, and CR field portions.
|
|
|
|
|
pub struct PRegValue {
|
|
|
|
|
pub int_fp: UInt<64>,
|
|
|
|
|
pub flags: PRegFlags,
|
|
|
|
|
}
|
2025-02-13 20:55:43 -08:00
|
|
|
|
|
|
|
|
impl PRegValue {
|
|
|
|
|
#[hdl]
|
|
|
|
|
pub fn zeroed() -> Expr<Self> {
|
|
|
|
|
#[hdl]
|
|
|
|
|
PRegValue {
|
|
|
|
|
int_fp: 0u64,
|
|
|
|
|
flags: PRegFlags::zeroed(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|