Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/aarch64_sys_reg/src/lib.rs
5392 views
1
// Copyright 2025 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
//! AArch64 system register names and encoding.
6
7
mod consts;
8
mod funcs;
9
mod gen;
10
11
#[cfg(test)]
12
mod tests;
13
14
pub use consts::*;
15
pub use funcs::*;
16
pub use gen::*;
17
use serde::Deserialize;
18
use serde::Serialize;
19
use thiserror::Error;
20
21
#[derive(Error, Debug)]
22
pub enum Error {
23
#[error("invalid CRm {0}")]
24
InvalidCrm(u8),
25
#[error("invalid CRn {0}")]
26
InvalidCrn(u8),
27
#[error("invalid Op0 {0}")]
28
InvalidOp0(u8),
29
#[error("invalid Op1 {0}")]
30
InvalidOp1(u8),
31
#[error("invalid Op2 {0}")]
32
InvalidOp2(u8),
33
}
34
35
pub type Result<T> = std::result::Result<T, Error>;
36
37
/// AArch64 system register as used in MSR/MRS instructions.
38
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
39
#[serde(transparent)]
40
pub struct AArch64SysRegId(u16);
41
42
impl AArch64SysRegId {
43
/// Construct a system register ID from Op0, Op1, CRn, CRm, Op2.
44
///
45
/// The meanings of the arguments are described in the ARMv8 Architecture Reference Manual
46
/// "System instruction class encoding overview" section.
47
pub fn new(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Result<Self> {
48
if op0 > 0b11 {
49
return Err(Error::InvalidOp0(op0));
50
}
51
if op1 > 0b111 {
52
return Err(Error::InvalidOp1(op1));
53
}
54
if crn > 0b1111 {
55
return Err(Error::InvalidCrn(crn));
56
}
57
if crm > 0b1111 {
58
return Err(Error::InvalidCrm(crm));
59
}
60
if op2 > 0b111 {
61
return Err(Error::InvalidOp2(op2));
62
}
63
64
Ok(Self::new_unchecked(op0, op1, crn, crm, op2))
65
}
66
67
/// Construct a system register ID from Op0, Op1, CRn, CRm, Op2.
68
///
69
/// Out-of-range values will be silently truncated.
70
pub const fn new_unchecked(op0: u8, op1: u8, crn: u8, crm: u8, op2: u8) -> Self {
71
let op0 = (op0 as u16 & 0b11) << 14;
72
let op1 = (op1 as u16 & 0b111) << 11;
73
let crn = (crn as u16 & 0b1111) << 7;
74
let crm = (crm as u16 & 0b1111) << 3;
75
let op2 = op2 as u16 & 0b111;
76
Self(op0 | op1 | crn | crm | op2)
77
}
78
79
#[inline]
80
pub fn from_encoded(v: u16) -> Self {
81
Self(v)
82
}
83
84
#[inline]
85
pub const fn op0(&self) -> u8 {
86
((self.0 >> 14) & 0b11) as u8
87
}
88
89
#[inline]
90
pub const fn op1(&self) -> u8 {
91
((self.0 >> 11) & 0b111) as u8
92
}
93
94
#[inline]
95
pub const fn crn(&self) -> u8 {
96
((self.0 >> 7) & 0b1111) as u8
97
}
98
99
#[inline]
100
pub const fn crm(&self) -> u8 {
101
((self.0 >> 3) & 0b1111) as u8
102
}
103
104
#[inline]
105
pub const fn op2(&self) -> u8 {
106
(self.0 & 0b111) as u8
107
}
108
109
/// Returns the system register as encoded in bits 5-20 of MRS and MSR instructions.
110
#[inline]
111
pub const fn encoded(&self) -> u16 {
112
self.0
113
}
114
}
115
116
impl std::fmt::Debug for AArch64SysRegId {
117
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118
f.debug_struct("AArch64SysRegId")
119
.field("Op0", &self.op0())
120
.field("Op1", &self.op1())
121
.field("CRn", &self.crn())
122
.field("CRm", &self.crm())
123
.field("Op2", &self.op2())
124
.finish()
125
}
126
}
127
128