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.id.cmp(&other.id))
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 to Register value {}",
253 bytes, self
254 )))
255 }
256 }
257 RegisterValue::U64(value) => {
258 if let Some(reg_val) = value.checked_add(bytes as u64) {
259 *value = reg_val;
260 Ok(())
261 } else {
262 Err(Error::Other(format!(
263 "Overflow error: Attempting to add {} bytes to Register value {}",
264 bytes, self
265 )))
266 }
267 }
268 RegisterValue::U128(value) => {
269 if let Some(reg_val) = value.checked_add(bytes as u128) {
270 *value = reg_val;
271 Ok(())
272 } else {
273 Err(Error::Other(format!(
274 "Overflow error: Attempting to add {} bytes to Register value {}",
275 bytes, self
276 )))
277 }
278 }
279 }
280 }
281
282 pub fn decrement_address(&mut self, bytes: usize) -> Result<(), Error> {
284 match self {
285 RegisterValue::U32(value) => {
286 if let Some(reg_val) = value.checked_sub(bytes as u32) {
287 *value = reg_val;
288 Ok(())
289 } else {
290 Err(Error::Other(format!(
291 "Overflow error: Attempting to subtract {} bytes to Register value {}",
292 bytes, self
293 )))
294 }
295 }
296 RegisterValue::U64(value) => {
297 if let Some(reg_val) = value.checked_sub(bytes as u64) {
298 *value = reg_val;
299 Ok(())
300 } else {
301 Err(Error::Other(format!(
302 "Overflow error: Attempting to subtract {} bytes to Register value {}",
303 bytes, self
304 )))
305 }
306 }
307 RegisterValue::U128(value) => {
308 if let Some(reg_val) = value.checked_sub(bytes as u128) {
309 *value = reg_val;
310 Ok(())
311 } else {
312 Err(Error::Other(format!(
313 "Overflow error: Attempting to subtract {} bytes to Register value {}",
314 bytes, self
315 )))
316 }
317 }
318 }
319 }
320
321 pub fn is_max_value(&self) -> bool {
323 match self {
324 RegisterValue::U32(register_value) => *register_value == u32::MAX,
325 RegisterValue::U64(register_value) => *register_value == u64::MAX,
326 RegisterValue::U128(register_value) => *register_value == u128::MAX,
327 }
328 }
329
330 pub fn is_zero(&self) -> bool {
332 matches!(
333 self,
334 RegisterValue::U32(0) | RegisterValue::U64(0) | RegisterValue::U128(0)
335 )
336 }
337}
338
339impl Default for RegisterValue {
340 fn default() -> Self {
341 RegisterValue::U32(0_u32)
343 }
344}
345
346impl PartialOrd for RegisterValue {
347 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
348 let self_value = match self {
349 RegisterValue::U32(self_value) => *self_value as u128,
350 RegisterValue::U64(self_value) => *self_value as u128,
351 RegisterValue::U128(self_value) => *self_value,
352 };
353 let other_value = match other {
354 RegisterValue::U32(other_value) => *other_value as u128,
355 RegisterValue::U64(other_value) => *other_value as u128,
356 RegisterValue::U128(other_value) => *other_value,
357 };
358 self_value.partial_cmp(&other_value)
359 }
360}
361
362impl PartialEq for RegisterValue {
363 fn eq(&self, other: &Self) -> bool {
364 let self_value = match self {
365 RegisterValue::U32(self_value) => *self_value as u128,
366 RegisterValue::U64(self_value) => *self_value as u128,
367 RegisterValue::U128(self_value) => *self_value,
368 };
369 let other_value = match other {
370 RegisterValue::U32(other_value) => *other_value as u128,
371 RegisterValue::U64(other_value) => *other_value as u128,
372 RegisterValue::U128(other_value) => *other_value,
373 };
374 self_value == other_value
375 }
376}
377
378impl core::fmt::Display for RegisterValue {
379 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
380 match self {
381 RegisterValue::U32(register_value) => write!(f, "{register_value:#010x}"),
382 RegisterValue::U64(register_value) => write!(f, "{register_value:#018x}"),
383 RegisterValue::U128(register_value) => write!(f, "{register_value:#034x}"),
384 }
385 }
386}
387
388impl From<u32> for RegisterValue {
389 fn from(val: u32) -> Self {
390 Self::U32(val)
391 }
392}
393
394impl From<u64> for RegisterValue {
395 fn from(val: u64) -> Self {
396 Self::U64(val)
397 }
398}
399
400impl From<u128> for RegisterValue {
401 fn from(val: u128) -> Self {
402 Self::U128(val)
403 }
404}
405
406impl TryInto<u32> for RegisterValue {
407 type Error = crate::Error;
408
409 fn try_into(self) -> Result<u32, Self::Error> {
410 match self {
411 Self::U32(v) => Ok(v),
412 Self::U64(v) => v
413 .try_into()
414 .map_err(|_| crate::Error::Other(format!("Value '{}' too large for u32", v))),
415 Self::U128(v) => v
416 .try_into()
417 .map_err(|_| crate::Error::Other(format!("Value '{}' too large for u32", v))),
418 }
419 }
420}
421
422impl TryInto<u64> for RegisterValue {
423 type Error = crate::Error;
424
425 fn try_into(self) -> Result<u64, Self::Error> {
426 match self {
427 Self::U32(v) => Ok(v.into()),
428 Self::U64(v) => Ok(v),
429 Self::U128(v) => v
430 .try_into()
431 .map_err(|_| crate::Error::Other(format!("Value '{}' too large for u64", v))),
432 }
433 }
434}
435
436impl TryInto<u128> for RegisterValue {
437 type Error = crate::Error;
438
439 fn try_into(self) -> Result<u128, Self::Error> {
440 match self {
441 Self::U32(v) => Ok(v.into()),
442 Self::U64(v) => Ok(v.into()),
443 Self::U128(v) => Ok(v),
444 }
445 }
446}
447
448pub trait RegisterValueResultExt<T> {
451 fn into_crate_error(self) -> Result<T, Error>;
453}
454
455impl<T> RegisterValueResultExt<T> for Result<T, Error> {
457 fn into_crate_error(self) -> Result<T, Error> {
458 self
459 }
460}
461
462impl<T> RegisterValueResultExt<T> for Result<T, Infallible> {
464 fn into_crate_error(self) -> Result<T, Error> {
465 Ok(self.unwrap())
466 }
467}
468
469#[derive(Debug, PartialEq)]
471pub struct CoreRegisters(Vec<&'static CoreRegister>);
472
473impl CoreRegisters {
474 pub fn new(core_registers: Vec<&'static CoreRegister>) -> CoreRegisters {
477 CoreRegisters(core_registers)
478 }
479
480 pub fn core_registers(&self) -> impl Iterator<Item = &CoreRegister> {
482 self.0
483 .iter()
484 .filter(|r| {
485 !r.roles.iter().any(|role| {
486 matches!(
487 role,
488 RegisterRole::FloatingPoint | RegisterRole::FloatingPointStatus
489 )
490 })
491 })
492 .cloned()
493 }
494
495 pub fn all_registers(&self) -> impl Iterator<Item = &CoreRegister> {
497 self.0.iter().cloned()
498 }
499
500 pub fn core_register(&self, index: usize) -> &CoreRegister {
506 self.core_registers().nth(index).unwrap()
507 }
508
509 pub fn get_core_register(&self, index: usize) -> Option<&CoreRegister> {
511 self.core_registers().nth(index)
512 }
513
514 pub fn argument_register(&self, index: usize) -> &CoreRegister {
520 self.get_argument_register(index).unwrap()
521 }
522
523 pub fn get_argument_register(&self, index: usize) -> Option<&CoreRegister> {
525 self.0
526 .iter()
527 .filter(|r| {
528 r.roles
529 .iter()
530 .any(|role| matches!(role, RegisterRole::Argument(_)))
531 })
532 .cloned()
533 .nth(index)
534 }
535
536 pub fn result_register(&self, index: usize) -> &CoreRegister {
542 self.get_result_register(index).unwrap()
543 }
544
545 pub fn get_result_register(&self, index: usize) -> Option<&CoreRegister> {
547 self.0
548 .iter()
549 .filter(|r| {
550 r.roles
551 .iter()
552 .any(|role| matches!(role, RegisterRole::Return(_)))
553 })
554 .cloned()
555 .nth(index)
556 }
557
558 pub fn pc(&self) -> Option<&CoreRegister> {
560 self.0
561 .iter()
562 .find(|r| r.register_has_role(RegisterRole::ProgramCounter))
563 .cloned()
564 }
565
566 pub fn msp(&self) -> Option<&CoreRegister> {
568 self.0
569 .iter()
570 .find(|r| r.register_has_role(RegisterRole::MainStackPointer))
571 .cloned()
572 }
573
574 pub fn psp(&self) -> Option<&CoreRegister> {
576 self.0
577 .iter()
578 .find(|r| r.register_has_role(RegisterRole::ProcessStackPointer))
579 .cloned()
580 }
581
582 pub fn psr(&self) -> Option<&CoreRegister> {
584 self.0
585 .iter()
586 .find(|r| r.register_has_role(RegisterRole::ProcessorStatus))
587 .cloned()
588 }
589
590 pub fn other_by_name(&self, name: &str) -> Option<&CoreRegister> {
592 self.0
593 .iter()
594 .find(|r| {
595 r.roles
596 .iter()
597 .any(|role| matches!(role, RegisterRole::Other(n) if *n == name))
598 })
599 .cloned()
600 }
601
602 pub fn fpsr(&self) -> Option<&CoreRegister> {
604 self.0
605 .iter()
606 .find(|r| r.register_has_role(RegisterRole::FloatingPointStatus))
607 .cloned()
608 }
609
610 pub fn fpu_registers(&self) -> Option<impl Iterator<Item = &CoreRegister>> {
612 let mut fpu_registers = self
613 .0
614 .iter()
615 .filter(|r| r.register_has_role(RegisterRole::FloatingPoint))
616 .peekable();
617 if fpu_registers.peek().is_some() {
618 Some(fpu_registers.cloned())
619 } else {
620 None
621 }
622 }
623
624 pub fn fpu_register(&self, index: usize) -> &CoreRegister {
630 self.get_fpu_register(index).unwrap()
631 }
632
633 pub fn get_fpu_register(&self, index: usize) -> Option<&CoreRegister> {
635 self.0
636 .iter()
637 .filter(|r| r.register_has_role(RegisterRole::FloatingPoint))
638 .cloned()
639 .nth(index)
640 }
641}