1use crate::Error;
4use serde::{Deserialize, Serialize};
5use std::{
6 cmp::Ordering,
7 convert::Infallible,
8 fmt::{Display, Formatter},
9};
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
13pub enum RegisterDataType {
14 UnsignedInteger(usize),
16 FloatingPoint(usize),
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
24pub enum RegisterRole {
25 Core(&'static str),
27 Argument(&'static str),
29 Return(&'static str),
31 ProgramCounter,
33 FramePointer,
35 StackPointer,
37 MainStackPointer,
39 ProcessStackPointer,
41 ProcessorStatus,
43 ReturnAddress,
45 FloatingPoint,
47 FloatingPointStatus,
49 Other(&'static str),
51}
52
53impl Display for RegisterRole {
54 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
55 match self {
56 RegisterRole::Core(name) => write!(f, "{name}"),
57 RegisterRole::Argument(name) => write!(f, "{name}"),
58 RegisterRole::Return(name) => write!(f, "{name}"),
59 RegisterRole::ProgramCounter => write!(f, "PC"),
60 RegisterRole::FramePointer => write!(f, "FP"),
61 RegisterRole::StackPointer => write!(f, "SP"),
62 RegisterRole::MainStackPointer => write!(f, "MSP"),
63 RegisterRole::ProcessStackPointer => write!(f, "PSP"),
64 RegisterRole::ProcessorStatus => write!(f, "PSR"),
65 RegisterRole::ReturnAddress => write!(f, "LR"),
66 RegisterRole::FloatingPoint => write!(f, "FPU"),
67 RegisterRole::FloatingPointStatus => write!(f, "FPSR"),
68 RegisterRole::Other(name) => write!(f, "{name}"),
69 }
70 }
71}
72
73#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
85pub enum UnwindRule {
86 Preserve,
90 #[default]
96 Clear,
97 SpecialRule,
101}
102
103#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
106pub struct CoreRegister {
107 pub id: RegisterId,
109 pub roles: &'static [RegisterRole],
111 pub data_type: RegisterDataType,
113 #[serde(skip_serializing)]
115 pub unwind_rule: UnwindRule,
116}
117
118impl PartialOrd for CoreRegister {
119 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
120 Some(self.cmp(other))
121 }
122}
123
124impl Ord for CoreRegister {
125 fn cmp(&self, other: &Self) -> Ordering {
126 self.id.cmp(&other.id)
127 }
128}
129
130impl Display for CoreRegister {
131 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
132 let primary_name = self.name();
133 write!(f, "{primary_name}")?;
134 if !self.roles.is_empty() {
135 for role in self.roles {
136 if primary_name != role.to_string() {
137 write!(f, "/{role}")?;
138 }
139 }
140 }
141 Ok(())
142 }
143}
144
145impl CoreRegister {
146 pub fn name(&self) -> &'static str {
148 self.roles
149 .iter()
150 .find_map(|role| match role {
151 RegisterRole::Core(name) => Some(*name),
152 _ => None,
153 })
154 .unwrap_or("Unknown")
155 }
156
157 pub fn id(&self) -> RegisterId {
159 self.id
160 }
161
162 pub fn data_type(&self) -> RegisterDataType {
164 self.data_type.clone()
165 }
166
167 pub fn size_in_bits(&self) -> usize {
169 match self.data_type() {
170 RegisterDataType::UnsignedInteger(size_in_bits) => size_in_bits,
171 RegisterDataType::FloatingPoint(size_in_bits) => size_in_bits,
172 }
173 }
174
175 pub fn size_in_bytes(&self) -> usize {
177 self.size_in_bits().div_ceil(8)
179 }
180
181 pub fn format_hex_width(&self) -> usize {
184 (self.size_in_bytes() * 2) + 2
185 }
186
187 pub fn register_has_role(&self, role: RegisterRole) -> bool {
189 for r in self.roles {
190 if r == &role {
191 return true;
192 }
193 }
194 false
195 }
196}
197
198impl From<CoreRegister> for RegisterId {
199 fn from(description: CoreRegister) -> RegisterId {
200 description.id
201 }
202}
203
204impl From<&CoreRegister> for RegisterId {
205 fn from(description: &CoreRegister) -> RegisterId {
206 description.id
207 }
208}
209
210#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
212#[serde(transparent)]
213pub struct RegisterId(pub u16);
214
215impl From<RegisterId> for u32 {
216 fn from(value: RegisterId) -> Self {
217 u32::from(value.0)
218 }
219}
220
221impl From<u16> for RegisterId {
222 fn from(value: u16) -> Self {
223 RegisterId(value)
224 }
225}
226
227#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
233pub enum RegisterValue {
234 U32(u32),
236 U64(u64),
238 U128(u128),
240}
241
242impl RegisterValue {
243 pub fn increment_address(&mut self, bytes: usize) -> Result<(), Error> {
245 match self {
246 RegisterValue::U32(value) => {
247 if let Some(reg_val) = value.checked_add(bytes as u32) {
248 *value = reg_val;
249 Ok(())
250 } else {
251 Err(Error::Other(format!(
252 "Overflow error: Attempting to add {bytes} bytes to Register value {self}"
253 )))
254 }
255 }
256 RegisterValue::U64(value) => {
257 if let Some(reg_val) = value.checked_add(bytes as u64) {
258 *value = reg_val;
259 Ok(())
260 } else {
261 Err(Error::Other(format!(
262 "Overflow error: Attempting to add {bytes} bytes to Register value {self}"
263 )))
264 }
265 }
266 RegisterValue::U128(value) => {
267 if let Some(reg_val) = value.checked_add(bytes as u128) {
268 *value = reg_val;
269 Ok(())
270 } else {
271 Err(Error::Other(format!(
272 "Overflow error: Attempting to add {bytes} bytes to Register value {self}"
273 )))
274 }
275 }
276 }
277 }
278
279 pub fn decrement_address(&mut self, bytes: usize) -> Result<(), Error> {
281 match self {
282 RegisterValue::U32(value) => {
283 if let Some(reg_val) = value.checked_sub(bytes as u32) {
284 *value = reg_val;
285 Ok(())
286 } else {
287 Err(Error::Other(format!(
288 "Overflow error: Attempting to subtract {bytes} bytes to Register value {self}"
289 )))
290 }
291 }
292 RegisterValue::U64(value) => {
293 if let Some(reg_val) = value.checked_sub(bytes as u64) {
294 *value = reg_val;
295 Ok(())
296 } else {
297 Err(Error::Other(format!(
298 "Overflow error: Attempting to subtract {bytes} bytes to Register value {self}"
299 )))
300 }
301 }
302 RegisterValue::U128(value) => {
303 if let Some(reg_val) = value.checked_sub(bytes as u128) {
304 *value = reg_val;
305 Ok(())
306 } else {
307 Err(Error::Other(format!(
308 "Overflow error: Attempting to subtract {bytes} bytes to Register value {self}"
309 )))
310 }
311 }
312 }
313 }
314
315 pub fn is_max_value(&self) -> bool {
317 match self {
318 RegisterValue::U32(register_value) => *register_value == u32::MAX,
319 RegisterValue::U64(register_value) => *register_value == u64::MAX,
320 RegisterValue::U128(register_value) => *register_value == u128::MAX,
321 }
322 }
323
324 pub fn is_zero(&self) -> bool {
326 matches!(
327 self,
328 RegisterValue::U32(0) | RegisterValue::U64(0) | RegisterValue::U128(0)
329 )
330 }
331}
332
333impl Default for RegisterValue {
334 fn default() -> Self {
335 RegisterValue::U32(0_u32)
337 }
338}
339
340impl PartialOrd for RegisterValue {
341 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
342 let self_value = match self {
343 RegisterValue::U32(self_value) => *self_value as u128,
344 RegisterValue::U64(self_value) => *self_value as u128,
345 RegisterValue::U128(self_value) => *self_value,
346 };
347 let other_value = match other {
348 RegisterValue::U32(other_value) => *other_value as u128,
349 RegisterValue::U64(other_value) => *other_value as u128,
350 RegisterValue::U128(other_value) => *other_value,
351 };
352 self_value.partial_cmp(&other_value)
353 }
354}
355
356impl PartialEq for RegisterValue {
357 fn eq(&self, other: &Self) -> bool {
358 let self_value = match self {
359 RegisterValue::U32(self_value) => *self_value as u128,
360 RegisterValue::U64(self_value) => *self_value as u128,
361 RegisterValue::U128(self_value) => *self_value,
362 };
363 let other_value = match other {
364 RegisterValue::U32(other_value) => *other_value as u128,
365 RegisterValue::U64(other_value) => *other_value as u128,
366 RegisterValue::U128(other_value) => *other_value,
367 };
368 self_value == other_value
369 }
370}
371
372impl core::fmt::Display for RegisterValue {
373 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
374 match self {
375 RegisterValue::U32(register_value) => write!(f, "{register_value:#010x}"),
376 RegisterValue::U64(register_value) => write!(f, "{register_value:#018x}"),
377 RegisterValue::U128(register_value) => write!(f, "{register_value:#034x}"),
378 }
379 }
380}
381
382impl From<u32> for RegisterValue {
383 fn from(val: u32) -> Self {
384 Self::U32(val)
385 }
386}
387
388impl From<u64> for RegisterValue {
389 fn from(val: u64) -> Self {
390 Self::U64(val)
391 }
392}
393
394impl From<u128> for RegisterValue {
395 fn from(val: u128) -> Self {
396 Self::U128(val)
397 }
398}
399
400impl TryInto<u32> for RegisterValue {
401 type Error = crate::Error;
402
403 fn try_into(self) -> Result<u32, Self::Error> {
404 match self {
405 Self::U32(v) => Ok(v),
406 Self::U64(v) => v
407 .try_into()
408 .map_err(|_| crate::Error::Other(format!("Value '{v}' too large for u32"))),
409 Self::U128(v) => v
410 .try_into()
411 .map_err(|_| crate::Error::Other(format!("Value '{v}' too large for u32"))),
412 }
413 }
414}
415
416impl TryInto<u64> for RegisterValue {
417 type Error = crate::Error;
418
419 fn try_into(self) -> Result<u64, Self::Error> {
420 match self {
421 Self::U32(v) => Ok(v.into()),
422 Self::U64(v) => Ok(v),
423 Self::U128(v) => v
424 .try_into()
425 .map_err(|_| crate::Error::Other(format!("Value '{v}' too large for u64"))),
426 }
427 }
428}
429
430impl TryInto<u128> for RegisterValue {
431 type Error = crate::Error;
432
433 fn try_into(self) -> Result<u128, Self::Error> {
434 match self {
435 Self::U32(v) => Ok(v.into()),
436 Self::U64(v) => Ok(v.into()),
437 Self::U128(v) => Ok(v),
438 }
439 }
440}
441
442pub trait RegisterValueResultExt<T> {
445 fn into_crate_error(self) -> Result<T, Error>;
447}
448
449impl<T> RegisterValueResultExt<T> for Result<T, Error> {
451 fn into_crate_error(self) -> Result<T, Error> {
452 self
453 }
454}
455
456impl<T> RegisterValueResultExt<T> for Result<T, Infallible> {
458 fn into_crate_error(self) -> Result<T, Error> {
459 Ok(self.unwrap())
460 }
461}
462
463#[derive(Debug, PartialEq)]
465pub struct CoreRegisters(Vec<&'static CoreRegister>);
466
467impl CoreRegisters {
468 pub fn new(core_registers: Vec<&'static CoreRegister>) -> CoreRegisters {
471 CoreRegisters(core_registers)
472 }
473
474 pub fn core_registers(&self) -> impl Iterator<Item = &CoreRegister> {
476 self.0
477 .iter()
478 .filter(|r| {
479 !r.roles.iter().any(|role| {
480 matches!(
481 role,
482 RegisterRole::FloatingPoint | RegisterRole::FloatingPointStatus
483 )
484 })
485 })
486 .cloned()
487 }
488
489 pub fn all_registers(&self) -> impl Iterator<Item = &CoreRegister> {
491 self.0.iter().cloned()
492 }
493
494 pub fn core_register(&self, index: usize) -> &CoreRegister {
500 self.core_registers().nth(index).unwrap()
501 }
502
503 pub fn get_core_register(&self, index: usize) -> Option<&CoreRegister> {
505 self.core_registers().nth(index)
506 }
507
508 pub fn argument_register(&self, index: usize) -> &CoreRegister {
514 self.get_argument_register(index).unwrap()
515 }
516
517 pub fn get_argument_register(&self, index: usize) -> Option<&CoreRegister> {
519 self.0
520 .iter()
521 .filter(|r| {
522 r.roles
523 .iter()
524 .any(|role| matches!(role, RegisterRole::Argument(_)))
525 })
526 .cloned()
527 .nth(index)
528 }
529
530 pub fn result_register(&self, index: usize) -> &CoreRegister {
536 self.get_result_register(index).unwrap()
537 }
538
539 pub fn get_result_register(&self, index: usize) -> Option<&CoreRegister> {
541 self.0
542 .iter()
543 .filter(|r| {
544 r.roles
545 .iter()
546 .any(|role| matches!(role, RegisterRole::Return(_)))
547 })
548 .cloned()
549 .nth(index)
550 }
551
552 pub fn pc(&self) -> Option<&CoreRegister> {
554 self.0
555 .iter()
556 .find(|r| r.register_has_role(RegisterRole::ProgramCounter))
557 .cloned()
558 }
559
560 pub fn msp(&self) -> Option<&CoreRegister> {
562 self.0
563 .iter()
564 .find(|r| r.register_has_role(RegisterRole::MainStackPointer))
565 .cloned()
566 }
567
568 pub fn psp(&self) -> Option<&CoreRegister> {
570 self.0
571 .iter()
572 .find(|r| r.register_has_role(RegisterRole::ProcessStackPointer))
573 .cloned()
574 }
575
576 pub fn psr(&self) -> Option<&CoreRegister> {
578 self.0
579 .iter()
580 .find(|r| r.register_has_role(RegisterRole::ProcessorStatus))
581 .cloned()
582 }
583
584 pub fn other_by_name(&self, name: &str) -> Option<&CoreRegister> {
586 self.0
587 .iter()
588 .find(|r| {
589 r.roles
590 .iter()
591 .any(|role| matches!(role, RegisterRole::Other(n) if *n == name))
592 })
593 .cloned()
594 }
595
596 pub fn fpsr(&self) -> Option<&CoreRegister> {
598 self.0
599 .iter()
600 .find(|r| r.register_has_role(RegisterRole::FloatingPointStatus))
601 .cloned()
602 }
603
604 pub fn fpu_status_registers(&self) -> Option<impl Iterator<Item = &CoreRegister>> {
606 let mut fpu_registers = self
607 .0
608 .iter()
609 .filter(|r| r.register_has_role(RegisterRole::FloatingPointStatus))
610 .peekable();
611 if fpu_registers.peek().is_some() {
612 Some(fpu_registers.cloned())
613 } else {
614 None
615 }
616 }
617
618 pub fn fpu_registers(&self) -> Option<impl Iterator<Item = &CoreRegister>> {
620 let mut fpu_registers = self
621 .0
622 .iter()
623 .filter(|r| r.register_has_role(RegisterRole::FloatingPoint))
624 .peekable();
625 if fpu_registers.peek().is_some() {
626 Some(fpu_registers.cloned())
627 } else {
628 None
629 }
630 }
631
632 pub fn fpu_register(&self, index: usize) -> &CoreRegister {
638 self.get_fpu_register(index).unwrap()
639 }
640
641 pub fn get_fpu_register(&self, index: usize) -> Option<&CoreRegister> {
643 self.0
644 .iter()
645 .filter(|r| r.register_has_role(RegisterRole::FloatingPoint))
646 .cloned()
647 .nth(index)
648 }
649}