scause.rs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //! scause register
  2. use bit_field::BitField;
  3. use core::mem::size_of;
  4. /// scause register
  5. #[derive(Clone, Copy)]
  6. pub struct Scause {
  7. bits: usize,
  8. }
  9. /// Trap Cause
  10. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  11. pub enum Trap {
  12. Interrupt(Interrupt),
  13. Exception(Exception),
  14. }
  15. /// Interrupt
  16. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  17. pub enum Interrupt {
  18. UserSoft,
  19. SupervisorSoft,
  20. UserTimer,
  21. SupervisorTimer,
  22. UserExternal,
  23. SupervisorExternal,
  24. Unknown,
  25. }
  26. /// Exception
  27. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  28. pub enum Exception {
  29. InstructionMisaligned,
  30. InstructionFault,
  31. IllegalInstruction,
  32. Breakpoint,
  33. LoadFault,
  34. StoreMisaligned,
  35. StoreFault,
  36. UserEnvCall,
  37. InstructionPageFault,
  38. LoadPageFault,
  39. StorePageFault,
  40. Unknown,
  41. }
  42. impl Interrupt {
  43. pub fn from(nr: usize) -> Self {
  44. match nr {
  45. 0 => Interrupt::UserSoft,
  46. 1 => Interrupt::SupervisorSoft,
  47. 4 => Interrupt::UserTimer,
  48. 5 => Interrupt::SupervisorTimer,
  49. 8 => Interrupt::UserExternal,
  50. 9 => Interrupt::SupervisorExternal,
  51. _ => Interrupt::Unknown,
  52. }
  53. }
  54. }
  55. impl Exception {
  56. pub fn from(nr: usize) -> Self {
  57. match nr {
  58. 0 => Exception::InstructionMisaligned,
  59. 1 => Exception::InstructionFault,
  60. 2 => Exception::IllegalInstruction,
  61. 3 => Exception::Breakpoint,
  62. 5 => Exception::LoadFault,
  63. 6 => Exception::StoreMisaligned,
  64. 7 => Exception::StoreFault,
  65. 8 => Exception::UserEnvCall,
  66. 12 => Exception::InstructionPageFault,
  67. 13 => Exception::LoadPageFault,
  68. 15 => Exception::StorePageFault,
  69. _ => Exception::Unknown,
  70. }
  71. }
  72. }
  73. impl Scause {
  74. /// Returns the contents of the register as raw bits
  75. #[inline]
  76. pub fn bits(&self) -> usize {
  77. self.bits
  78. }
  79. /// Returns the code field
  80. pub fn code(&self) -> usize {
  81. let bit = 1 << (size_of::<usize>() * 8 - 1);
  82. self.bits & !bit
  83. }
  84. /// Trap Cause
  85. #[inline]
  86. pub fn cause(&self) -> Trap {
  87. if self.is_interrupt() {
  88. Trap::Interrupt(Interrupt::from(self.code()))
  89. } else {
  90. Trap::Exception(Exception::from(self.code()))
  91. }
  92. }
  93. /// Is trap cause an interrupt.
  94. #[inline]
  95. pub fn is_interrupt(&self) -> bool {
  96. self.bits.get_bit(size_of::<usize>() * 8 - 1)
  97. }
  98. /// Is trap cause an exception.
  99. #[inline]
  100. pub fn is_exception(&self) -> bool {
  101. !self.is_interrupt()
  102. }
  103. }
  104. read_csr_as!(Scause, 0x142, __read_scause);
  105. write_csr!(0x142, __write_scause);
  106. /// Writes the CSR
  107. #[inline]
  108. pub unsafe fn write(bits: usize) {
  109. _write(bits)
  110. }
  111. /// Set supervisor cause register to corresponding cause.
  112. #[inline]
  113. pub unsafe fn set(cause: Trap) {
  114. let bits = match cause {
  115. Trap::Interrupt(i) => match i {
  116. Interrupt::UserSoft => 0,
  117. Interrupt::SupervisorSoft => 1,
  118. Interrupt::UserTimer => 4,
  119. Interrupt::SupervisorTimer => 5,
  120. Interrupt::UserExternal => 8,
  121. Interrupt::SupervisorExternal => 9,
  122. Interrupt::Unknown => panic!("unknown interrupt"),
  123. },
  124. Trap::Exception(e) => {
  125. (match e {
  126. Exception::InstructionMisaligned => 0,
  127. Exception::InstructionFault => 1,
  128. Exception::IllegalInstruction => 2,
  129. Exception::Breakpoint => 3,
  130. Exception::LoadFault => 5,
  131. Exception::StoreMisaligned => 6,
  132. Exception::StoreFault => 7,
  133. Exception::UserEnvCall => 8,
  134. Exception::InstructionPageFault => 12,
  135. Exception::LoadPageFault => 13,
  136. Exception::StorePageFault => 15,
  137. Exception::Unknown => panic!("unknown exception"),
  138. } | (1 << (size_of::<usize>() * 8 - 1)))
  139. }
  140. };
  141. _write(bits);
  142. }