refactor PRegFlags to use view structs instead of a long list of accessor methods
This commit is contained in:
parent
0433e4f8f1
commit
ffc3d4283c
2 changed files with 520 additions and 114 deletions
|
|
@ -1,6 +1,8 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
use fayalite::prelude::*;
|
||||
|
||||
use fayalite::{expr::CastToImpl, int::BoolOrIntType, prelude::*};
|
||||
use std::fmt;
|
||||
|
||||
#[hdl]
|
||||
pub enum FlagsMode {
|
||||
|
|
@ -8,92 +10,427 @@ pub enum FlagsMode {
|
|||
X86(PRegFlagsX86),
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct PRegFlagsPowerISA {}
|
||||
trait PRegFlagsViewTraitSealed {
|
||||
type UnusedInner<T>: AsRef<[T]>
|
||||
+ AsMut<[T]>
|
||||
+ IntoIterator<
|
||||
Item = T,
|
||||
IntoIter: DoubleEndedIterator<Item = T>
|
||||
+ ExactSizeIterator
|
||||
+ std::iter::FusedIterator
|
||||
+ Default,
|
||||
>;
|
||||
const UNUSED_INNER_LEN: usize;
|
||||
fn unused_inner_map<T, R>(
|
||||
v: Self::UnusedInner<T>,
|
||||
f: impl FnMut(T) -> R,
|
||||
) -> Self::UnusedInner<R>;
|
||||
fn unused_inner_from_fn<T>(f: impl FnMut(usize) -> T) -> Self::UnusedInner<T>;
|
||||
fn unused_inner_each_ref<T>(v: &Self::UnusedInner<T>) -> Self::UnusedInner<&T>;
|
||||
fn unused_inner_each_mut<T>(v: &mut Self::UnusedInner<T>) -> Self::UnusedInner<&mut T>;
|
||||
}
|
||||
|
||||
impl PRegFlagsPowerISA {
|
||||
pub fn xer_ca(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ca_x86_cf
|
||||
#[expect(private_bounds)]
|
||||
pub trait PRegFlagsViewTrait: Type + PRegFlagsViewTraitSealed {
|
||||
type View<T>;
|
||||
fn view<T: Type>(flags: impl ToExpr<Type = PRegFlags<T>>) -> Self::View<Expr<T>>;
|
||||
fn view_sim<T: Type>(flags: impl ToSimValue<Type = PRegFlags<T>>) -> Self::View<SimValue<T>>;
|
||||
fn view_sim_ref<T: Type>(flags: &SimValue<PRegFlags<T>>) -> Self::View<&SimValue<T>>;
|
||||
fn view_sim_mut<T: Type>(flags: &mut SimValue<PRegFlags<T>>) -> Self::View<&mut SimValue<T>>;
|
||||
fn from_view<T: ToExpr>(view: Self::View<T>) -> Expr<PRegFlags<T::Type>>;
|
||||
fn from_view_sim<T: ToSimValue>(view: Self::View<T>) -> SimValue<PRegFlags<T::Type>>;
|
||||
}
|
||||
|
||||
pub struct ViewUnused<T, V: PRegFlagsViewTrait>(V::UnusedInner<T>);
|
||||
|
||||
pub struct ViewUnusedIntoIter<T, V: PRegFlagsViewTrait>(
|
||||
<V::UnusedInner<T> as IntoIterator>::IntoIter,
|
||||
);
|
||||
|
||||
impl<T, V: PRegFlagsViewTrait> Iterator for ViewUnusedIntoIter<T, V> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.0.next()
|
||||
}
|
||||
pub fn xer_ca32(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ca32_x86_af
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
pub fn xer_ov(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ov_x86_of
|
||||
|
||||
fn fold<B, F>(self, init: B, f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
self.0.fold(init, f)
|
||||
}
|
||||
pub fn xer_ov32(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ov32_x86_df
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
/// 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>) {
|
||||
// list all flags explicitly so we don't miss handling any new flags
|
||||
#[hdl]
|
||||
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;
|
||||
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
self.0.last()
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct PRegFlagsX86 {}
|
||||
impl<T, V: PRegFlagsViewTrait> DoubleEndedIterator for ViewUnusedIntoIter<T, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
self.0.next_back()
|
||||
}
|
||||
|
||||
impl PRegFlagsX86 {
|
||||
pub fn cf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ca_x86_cf
|
||||
fn rfold<B, F>(self, init: B, f: F) -> B
|
||||
where
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
self.0.rfold(init, f)
|
||||
}
|
||||
pub fn zf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_cr_eq_x86_zf
|
||||
}
|
||||
|
||||
impl<T, V: PRegFlagsViewTrait> ExactSizeIterator for ViewUnusedIntoIter<T, V> {
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
pub fn sf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_cr_lt_x86_sf
|
||||
}
|
||||
|
||||
impl<T, V: PRegFlagsViewTrait> std::iter::FusedIterator for ViewUnusedIntoIter<T, V> {}
|
||||
|
||||
impl<T, V: PRegFlagsViewTrait> Default for ViewUnusedIntoIter<T, V> {
|
||||
fn default() -> Self {
|
||||
Self(Default::default())
|
||||
}
|
||||
pub fn of(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ov_x86_of
|
||||
}
|
||||
|
||||
impl<T: Clone, V: PRegFlagsViewTrait> Clone for ViewUnusedIntoIter<T, V>
|
||||
where
|
||||
<V::UnusedInner<T> as IntoIterator>::IntoIter: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
pub fn af(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ca32_x86_af
|
||||
}
|
||||
|
||||
impl<T, V: PRegFlagsViewTrait> IntoIterator for ViewUnused<T, V> {
|
||||
type Item = T;
|
||||
type IntoIter = ViewUnusedIntoIter<T, V>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
ViewUnusedIntoIter(self.0.into_iter())
|
||||
}
|
||||
pub fn pf(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_cr_gt_x86_pf
|
||||
}
|
||||
|
||||
impl<T: Default, V: PRegFlagsViewTrait> Default for ViewUnused<T, V> {
|
||||
fn default() -> Self {
|
||||
Self::from_fn(|_| T::default())
|
||||
}
|
||||
pub fn df(flags: impl ToExpr<Type = PRegFlags>) -> Expr<Bool> {
|
||||
flags.to_expr().pwr_ov32_x86_df
|
||||
}
|
||||
|
||||
impl<T, V: PRegFlagsViewTrait> ViewUnused<T, V> {
|
||||
pub fn iter(&self) -> std::slice::Iter<'_, T> {
|
||||
self.into_iter()
|
||||
}
|
||||
#[hdl]
|
||||
pub fn clear_unused(flags: impl ToExpr<Type = PRegFlags>) {
|
||||
// list all flags explicitly so we don't miss handling any new flags
|
||||
#[hdl]
|
||||
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);
|
||||
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
|
||||
self.into_iter()
|
||||
}
|
||||
pub fn from_fn(f: impl FnMut(usize) -> T) -> Self {
|
||||
ViewUnused(V::unused_inner_from_fn(f))
|
||||
}
|
||||
pub fn each_ref(&self) -> ViewUnused<&T, V> {
|
||||
ViewUnused(V::unused_inner_each_ref(&self.0))
|
||||
}
|
||||
pub fn each_mut(&mut self) -> ViewUnused<&mut T, V> {
|
||||
ViewUnused(V::unused_inner_each_mut(&mut self.0))
|
||||
}
|
||||
pub fn map<R>(self, f: impl FnMut(T) -> R) -> ViewUnused<R, V> {
|
||||
ViewUnused(V::unused_inner_map(self.0, f))
|
||||
}
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
let mut v = Some(v);
|
||||
Self::from_fn(|i| {
|
||||
let v = if i == V::UNUSED_INNER_LEN - 1 {
|
||||
v.take()
|
||||
} else {
|
||||
v.clone()
|
||||
};
|
||||
let Some(v) = v else {
|
||||
unreachable!();
|
||||
};
|
||||
v
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BoolOrIntType, V: PRegFlagsViewTrait> ViewUnused<SimValue<T>, V> {
|
||||
pub fn clear(&mut self) {
|
||||
for i in self.iter_mut() {
|
||||
SimValue::bits_mut(i).bits_mut().fill(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BoolOrIntType, V: PRegFlagsViewTrait> ViewUnused<&'_ mut SimValue<T>, V> {
|
||||
pub fn clear(&mut self) {
|
||||
for i in self.iter_mut() {
|
||||
SimValue::bits_mut(i).bits_mut().fill(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: BoolOrIntType, V: PRegFlagsViewTrait> ViewUnused<Expr<T>, V>
|
||||
where
|
||||
UInt: CastToImpl<T, ValueOutput: ToExpr>,
|
||||
{
|
||||
pub fn clear(self) {
|
||||
for i in self {
|
||||
connect(i, UInt::new_dyn(i.ty().width()).zero().cast_to(i.ty()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, V: PRegFlagsViewTrait> IntoIterator for &'a ViewUnused<T, V> {
|
||||
type Item = &'a T;
|
||||
type IntoIter = std::slice::Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.as_ref().iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, V: PRegFlagsViewTrait> IntoIterator for &'a mut ViewUnused<T, V> {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = std::slice::IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.as_mut().iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, V: PRegFlagsViewTrait> Clone for ViewUnused<T, V>
|
||||
where
|
||||
V::UnusedInner<T>: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, V: PRegFlagsViewTrait> Copy for ViewUnused<T, V> where V::UnusedInner<T>: Copy {}
|
||||
|
||||
impl<T: fmt::Debug, V: PRegFlagsViewTrait> fmt::Debug for ViewUnused<T, V>
|
||||
where
|
||||
V::UnusedInner<T>: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("ViewUnused").field(&self.0).finish()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_view_trait {
|
||||
(
|
||||
$(#[$flags_mode_meta:meta])*
|
||||
$flags_mode_vis:vis struct $FlagsMode:ident {}
|
||||
|
||||
$(#[$view_meta:meta])*
|
||||
$view_vis:vis struct $View:ident {
|
||||
$(#[$unused_field_meta:meta])*
|
||||
$unused_vis:vis $unused:ident: ViewUnused([$($unused_field:ident),* $(,)?]),
|
||||
$($(#[$view_field_meta:meta])*
|
||||
$view_field_vis:vis $view_field:ident: $flags_field:ident,)*
|
||||
}
|
||||
) => {
|
||||
$(#[$flags_mode_meta])*
|
||||
$flags_mode_vis struct $FlagsMode {}
|
||||
|
||||
$(#[$view_meta])*
|
||||
$view_vis struct $View<T> {
|
||||
$(#[$unused_field_meta])*
|
||||
$unused_vis $unused: ViewUnused<T, $FlagsMode>,
|
||||
$($(#[$view_field_meta])*
|
||||
$view_field_vis $view_field: T,)*
|
||||
}
|
||||
|
||||
impl<T> $View<&'_ mut T> {
|
||||
$view_vis const fn reborrow<'a>(&'a mut self) -> $View<&'a mut T> {
|
||||
let $View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
} = self;
|
||||
$View {
|
||||
$unused: ViewUnused([$(&mut **$unused_field,)*]),
|
||||
$($view_field: &mut **$flags_field,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PRegFlagsViewTraitSealed for $FlagsMode {
|
||||
type UnusedInner<T> = [T; Self::UNUSED_INNER_LEN];
|
||||
const UNUSED_INNER_LEN: usize = {
|
||||
let v: &[&str] = &[$(stringify!($unused_field),)*];
|
||||
v.len()
|
||||
};
|
||||
fn unused_inner_map<T, R>(
|
||||
v: Self::UnusedInner<T>,
|
||||
f: impl FnMut(T) -> R,
|
||||
) -> Self::UnusedInner<R> {
|
||||
v.map(f)
|
||||
}
|
||||
fn unused_inner_from_fn<T>(f: impl FnMut(usize) -> T) -> Self::UnusedInner<T> {
|
||||
std::array::from_fn(f)
|
||||
}
|
||||
fn unused_inner_each_ref<T>(
|
||||
v: &Self::UnusedInner<T>,
|
||||
) -> Self::UnusedInner<&T> {
|
||||
v.each_ref()
|
||||
}
|
||||
fn unused_inner_each_mut<T>(
|
||||
v: &mut Self::UnusedInner<T>,
|
||||
) -> Self::UnusedInner<&mut T> {
|
||||
v.each_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl PRegFlagsViewTrait for $FlagsMode {
|
||||
type View<T> = $View<T>;
|
||||
|
||||
#[hdl]
|
||||
fn view<T: Type>(flags: impl ToExpr<Type = PRegFlags<T>>) -> Self::View<Expr<T>> {
|
||||
#[hdl]
|
||||
let PRegFlags::<T> {
|
||||
$($unused_field,)*
|
||||
$($flags_field,)*
|
||||
} = flags.to_expr();
|
||||
$View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn view_sim<T: Type>(flags: impl ToSimValue<Type = PRegFlags<T>>) -> Self::View<SimValue<T>> {
|
||||
#[hdl(sim)]
|
||||
let PRegFlags::<T> {
|
||||
$($unused_field,)*
|
||||
$($flags_field,)*
|
||||
} = flags.into_sim_value();
|
||||
$View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn view_sim_ref<T: Type>(flags: &SimValue<PRegFlags<T>>) -> Self::View<&SimValue<T>> {
|
||||
#[hdl(sim)]
|
||||
let PRegFlags::<T> {
|
||||
$($unused_field,)*
|
||||
$($flags_field,)*
|
||||
} = flags;
|
||||
$View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn view_sim_mut<T: Type>(flags: &mut SimValue<PRegFlags<T>>) -> Self::View<&mut SimValue<T>> {
|
||||
#[hdl(sim)]
|
||||
let PRegFlags::<T> {
|
||||
$($unused_field,)*
|
||||
$($flags_field,)*
|
||||
} = flags;
|
||||
$View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn from_view<T: ToExpr>(view: Self::View<T>) -> Expr<PRegFlags<T::Type>> {
|
||||
let $View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
} = view;
|
||||
#[hdl]
|
||||
PRegFlags::<_> {
|
||||
$($unused_field,)*
|
||||
$($flags_field,)*
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn from_view_sim<T: ToSimValue>(view: Self::View<T>) -> SimValue<PRegFlags<T::Type>> {
|
||||
let $View {
|
||||
$unused: ViewUnused([$($unused_field,)*]),
|
||||
$($view_field: $flags_field,)*
|
||||
} = view;
|
||||
#[hdl(sim)]
|
||||
PRegFlags::<_> {
|
||||
$($unused_field,)*
|
||||
$($flags_field,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_view_trait! {
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct PRegFlagsPowerISA {}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct PRegFlagsPowerISAView {
|
||||
pub unused: ViewUnused([]),
|
||||
pub xer_ca: pwr_ca_x86_cf,
|
||||
pub xer_ca32: pwr_ca32_x86_af,
|
||||
pub xer_ov: pwr_ov_x86_of,
|
||||
pub xer_ov32: pwr_ov32_x86_df,
|
||||
/// both `CR<N>.SO` and `XER.SO` since instructions that write to both always write the same value
|
||||
pub so: pwr_so,
|
||||
pub cr_lt: pwr_cr_lt_x86_sf,
|
||||
pub cr_gt: pwr_cr_gt_x86_pf,
|
||||
pub cr_eq: pwr_cr_eq_x86_zf,
|
||||
}
|
||||
}
|
||||
|
||||
impl_view_trait! {
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct PRegFlagsX86 {}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct PRegFlagsX86View {
|
||||
pub unused: ViewUnused([pwr_so]),
|
||||
pub cf: pwr_ca_x86_cf,
|
||||
pub zf: pwr_cr_eq_x86_zf,
|
||||
pub sf: pwr_cr_lt_x86_sf,
|
||||
pub of: pwr_ov_x86_of,
|
||||
pub af: pwr_ca32_x86_af,
|
||||
pub pf: pwr_cr_gt_x86_pf,
|
||||
pub df: pwr_ov32_x86_df,
|
||||
}
|
||||
}
|
||||
|
||||
impl_view_trait! {
|
||||
#[hdl(cmp_eq)]
|
||||
pub struct PRegFlagsAllUnused {}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct PRegFlagsAllUnusedView {
|
||||
pub unused: ViewUnused([
|
||||
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,
|
||||
]),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,33 +442,90 @@ impl PRegFlagsX86 {
|
|||
///
|
||||
/// * 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,
|
||||
pub struct PRegFlags<T: Type = Bool> {
|
||||
pwr_ca_x86_cf: T,
|
||||
pwr_ca32_x86_af: T,
|
||||
pwr_ov_x86_of: T,
|
||||
pwr_ov32_x86_df: T,
|
||||
pwr_cr_lt_x86_sf: T,
|
||||
pwr_cr_gt_x86_pf: T,
|
||||
pwr_cr_eq_x86_zf: T,
|
||||
pwr_so: T,
|
||||
}
|
||||
|
||||
impl<T: Type> PRegFlags<T> {
|
||||
pub fn view<V: PRegFlagsViewTrait>(flags: impl ToExpr<Type = Self>) -> V::View<Expr<T>> {
|
||||
V::view(flags)
|
||||
}
|
||||
pub fn view_sim<V: PRegFlagsViewTrait>(
|
||||
flags: impl ToSimValue<Type = Self>,
|
||||
) -> V::View<SimValue<T>> {
|
||||
V::view_sim(flags)
|
||||
}
|
||||
pub fn view_sim_ref<V: PRegFlagsViewTrait>(flags: &SimValue<Self>) -> V::View<&SimValue<T>> {
|
||||
V::view_sim_ref(flags)
|
||||
}
|
||||
pub fn view_sim_mut<V: PRegFlagsViewTrait>(
|
||||
flags: &mut SimValue<Self>,
|
||||
) -> V::View<&mut SimValue<T>> {
|
||||
V::view_sim_mut(flags)
|
||||
}
|
||||
pub fn from_view<V: PRegFlagsViewTrait>(view: V::View<impl ToExpr<Type = T>>) -> Expr<Self> {
|
||||
V::from_view(view)
|
||||
}
|
||||
pub fn from_view_sim<V: PRegFlagsViewTrait>(
|
||||
view: V::View<impl ToSimValue<Type = T>>,
|
||||
) -> SimValue<Self> {
|
||||
V::from_view_sim(view)
|
||||
}
|
||||
pub fn fields(flags: impl ToExpr<Type = Self>) -> ViewUnused<Expr<T>, PRegFlagsAllUnused> {
|
||||
Self::view::<PRegFlagsAllUnused>(flags).unused
|
||||
}
|
||||
pub fn fields_sim(
|
||||
flags: impl ToSimValue<Type = Self>,
|
||||
) -> ViewUnused<SimValue<T>, PRegFlagsAllUnused> {
|
||||
Self::view_sim::<PRegFlagsAllUnused>(flags).unused
|
||||
}
|
||||
pub fn fields_sim_ref(flags: &SimValue<Self>) -> ViewUnused<&SimValue<T>, PRegFlagsAllUnused> {
|
||||
Self::view_sim_ref::<PRegFlagsAllUnused>(flags).unused
|
||||
}
|
||||
pub fn fields_sim_mut(
|
||||
flags: &mut SimValue<Self>,
|
||||
) -> ViewUnused<&mut SimValue<T>, PRegFlagsAllUnused> {
|
||||
Self::view_sim_mut::<PRegFlagsAllUnused>(flags).unused
|
||||
}
|
||||
pub fn from_fields(
|
||||
fields: ViewUnused<impl ToExpr<Type = T>, PRegFlagsAllUnused>,
|
||||
) -> Expr<Self> {
|
||||
Self::from_view::<PRegFlagsAllUnused>(PRegFlagsAllUnusedView { unused: fields })
|
||||
}
|
||||
pub fn from_fields_sim(
|
||||
fields: ViewUnused<impl ToSimValue<Type = T>, PRegFlagsAllUnused>,
|
||||
) -> SimValue<Self> {
|
||||
Self::from_view_sim::<PRegFlagsAllUnused>(PRegFlagsAllUnusedView { unused: fields })
|
||||
}
|
||||
/// if trying to set all fields individually, prefer using the individual accessor
|
||||
/// functions and [`PRegFlagsPowerISA::clear_unused()`]/[`PRegFlagsX86::clear_unused()`]/etc.
|
||||
pub fn splat(v: impl ToExpr<Type = T>) -> Expr<Self> {
|
||||
Self::from_fields(ViewUnused::splat(v.to_expr()))
|
||||
}
|
||||
/// if trying to set all fields individually, prefer using the individual accessor
|
||||
/// functions and [`PRegFlagsPowerISA::clear_unused()`]/[`PRegFlagsX86::clear_unused()`]/etc.
|
||||
pub fn splat_sim(v: impl ToSimValue<Type = T>) -> SimValue<Self> {
|
||||
Self::from_fields_sim(ViewUnused::splat(v.into_sim_value()))
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
Self::splat(false)
|
||||
}
|
||||
/// if trying to set all fields individually, prefer using the individual accessor
|
||||
/// functions and [`PRegFlagsPowerISA::clear_unused()`]/[`PRegFlagsX86::clear_unused()`]/etc.
|
||||
pub fn zeroed_sim() -> SimValue<PRegFlags> {
|
||||
Self::splat_sim(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ use crate::{
|
|||
AddSubMOp, AluBranchMOp, AluCommonMOp, BranchMOp, COMMON_MOP_SRC_LEN, CommonMOp,
|
||||
CompareMOp, LogicalMOp, MOpTrait, OutputIntegerMode, RenamedMOp, UnitOutRegNum,
|
||||
},
|
||||
register::{FlagsMode, PRegFlagsPowerISA, PRegFlagsX86, PRegValue},
|
||||
register::{
|
||||
FlagsMode, PRegFlagsPowerISA, PRegFlagsPowerISAView, PRegFlagsViewTrait, PRegFlagsX86,
|
||||
PRegFlagsX86View, PRegValue, ViewUnused,
|
||||
},
|
||||
unit::{
|
||||
DynUnit, DynUnitWrapper, GlobalState, UnitKind, UnitMOp, UnitOutput, UnitResult,
|
||||
UnitResultCompleted, UnitTrait,
|
||||
|
|
@ -56,13 +59,13 @@ fn add_sub<SrcCount: KnownSize>(
|
|||
FlagsMode::PowerISA(_) => {
|
||||
connect(
|
||||
carry_in_before_inversion,
|
||||
PRegFlagsPowerISA::xer_ca(src_values[1].flags),
|
||||
PRegFlagsPowerISA::view(src_values[1].flags).xer_ca,
|
||||
);
|
||||
}
|
||||
FlagsMode::X86(_) => {
|
||||
connect(
|
||||
carry_in_before_inversion,
|
||||
PRegFlagsX86::cf(src_values[1].flags),
|
||||
PRegFlagsX86::view(src_values[1].flags).cf,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -199,27 +202,36 @@ fn add_sub<SrcCount: KnownSize>(
|
|||
#[hdl]
|
||||
match flags_mode {
|
||||
FlagsMode::PowerISA(_) => {
|
||||
PRegFlagsPowerISA::clear_unused(flags);
|
||||
connect(PRegFlagsPowerISA::xer_ca(flags), pwr_ca);
|
||||
connect(PRegFlagsPowerISA::xer_ca32(flags), pwr_ca32);
|
||||
connect(PRegFlagsPowerISA::xer_ov(flags), pwr_ov);
|
||||
connect(PRegFlagsPowerISA::xer_ov32(flags), pwr_ov32);
|
||||
connect(PRegFlagsPowerISA::cr_lt(flags), pwr_cr_lt);
|
||||
connect(PRegFlagsPowerISA::cr_gt(flags), pwr_cr_gt);
|
||||
connect(PRegFlagsPowerISA::cr_eq(flags), pwr_cr_eq);
|
||||
connect(PRegFlagsPowerISA::so(flags), pwr_so);
|
||||
connect(
|
||||
flags,
|
||||
PRegFlagsPowerISA::from_view(PRegFlagsPowerISAView {
|
||||
unused: ViewUnused::splat(false.to_expr()),
|
||||
xer_ca: pwr_ca,
|
||||
xer_ca32: pwr_ca32,
|
||||
xer_ov: pwr_ov,
|
||||
xer_ov32: pwr_ov32,
|
||||
so: pwr_so,
|
||||
cr_lt: pwr_cr_lt,
|
||||
cr_gt: pwr_cr_gt,
|
||||
cr_eq: pwr_cr_eq,
|
||||
}),
|
||||
);
|
||||
}
|
||||
FlagsMode::X86(_) => {
|
||||
PRegFlagsX86::clear_unused(flags);
|
||||
connect(PRegFlagsX86::cf(flags), x86_cf);
|
||||
connect(PRegFlagsX86::af(flags), x86_af);
|
||||
connect(PRegFlagsX86::of(flags), x86_of);
|
||||
connect(PRegFlagsX86::sf(flags), x86_sf);
|
||||
connect(PRegFlagsX86::pf(flags), x86_pf);
|
||||
connect(PRegFlagsX86::zf(flags), x86_zf);
|
||||
|
||||
// this insn doesn't write DF, so it's output isn't used for reading DF
|
||||
connect(PRegFlagsX86::df(flags), false);
|
||||
connect(
|
||||
flags,
|
||||
PRegFlagsX86::from_view(PRegFlagsX86View {
|
||||
unused: ViewUnused::splat(false.to_expr()),
|
||||
cf: x86_cf,
|
||||
zf: x86_zf,
|
||||
sf: x86_sf,
|
||||
of: x86_of,
|
||||
af: x86_af,
|
||||
pf: x86_pf,
|
||||
// this insn doesn't write DF, so it's output isn't used for reading DF
|
||||
df: false.to_expr(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
#[hdl]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue