fcsr.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //! Floating-point control and status register
  2. use bit_field::BitField;
  3. /// Floating-point control and status register
  4. #[derive(Clone, Copy, Debug)]
  5. pub struct FCSR {
  6. bits: u32,
  7. }
  8. /// Accrued Exception Flags
  9. #[derive(Clone, Copy, Debug)]
  10. pub struct Flags(u32);
  11. /// Accrued Exception Flag
  12. #[derive(Clone, Copy, Debug)]
  13. pub enum Flag {
  14. /// Inexact
  15. NX = 0b00001,
  16. /// Underflow
  17. UF = 0b00010,
  18. /// Overflow
  19. OF = 0b00100,
  20. /// Divide by Zero
  21. DZ = 0b01000,
  22. /// Invalid Operation
  23. NV = 0b10000,
  24. }
  25. impl Flags {
  26. /// Inexact
  27. #[inline]
  28. pub fn nx(&self) -> bool {
  29. self.0.get_bit(0)
  30. }
  31. /// Underflow
  32. #[inline]
  33. pub fn uf(&self) -> bool {
  34. self.0.get_bit(1)
  35. }
  36. /// Overflow
  37. #[inline]
  38. pub fn of(&self) -> bool {
  39. self.0.get_bit(2)
  40. }
  41. /// Divide by Zero
  42. #[inline]
  43. pub fn dz(&self) -> bool {
  44. self.0.get_bit(3)
  45. }
  46. /// Invalid Operation
  47. #[inline]
  48. pub fn nv(&self) -> bool {
  49. self.0.get_bit(4)
  50. }
  51. }
  52. /// Rounding Mode
  53. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  54. pub enum RoundingMode {
  55. RoundToNearestEven = 0b000,
  56. RoundTowardsZero = 0b001,
  57. RoundDown = 0b010,
  58. RoundUp = 0b011,
  59. RoundToNearestMaxMagnitude = 0b100,
  60. Invalid = 0b111,
  61. }
  62. impl FCSR {
  63. /// Returns the contents of the register as raw bits
  64. #[inline]
  65. pub fn bits(&self) -> u32 {
  66. self.bits
  67. }
  68. /// Accrued Exception Flags
  69. #[inline]
  70. pub fn fflags(&self) -> Flags {
  71. Flags(self.bits.get_bits(0..5))
  72. }
  73. /// Rounding Mode
  74. #[inline]
  75. pub fn frm(&self) -> RoundingMode {
  76. match self.bits.get_bits(5..8) {
  77. 0b000 => RoundingMode::RoundToNearestEven,
  78. 0b001 => RoundingMode::RoundTowardsZero,
  79. 0b010 => RoundingMode::RoundDown,
  80. 0b011 => RoundingMode::RoundUp,
  81. 0b100 => RoundingMode::RoundToNearestMaxMagnitude,
  82. _ => RoundingMode::Invalid,
  83. }
  84. }
  85. }
  86. read_csr!(0x003);
  87. write_csr!(0x003);
  88. clear!(0x003);
  89. /// Reads the CSR
  90. #[inline]
  91. pub fn read() -> FCSR {
  92. FCSR {
  93. bits: unsafe { _read() as u32 },
  94. }
  95. }
  96. /// Writes the CSR
  97. #[inline]
  98. pub unsafe fn set_rounding_mode(frm: RoundingMode) {
  99. let old = read();
  100. let bits = ((frm as u32) << 5) | old.fflags().0;
  101. _write(bits as usize);
  102. }
  103. /// Resets `fflags` field bits
  104. #[inline]
  105. pub unsafe fn clear_flags() {
  106. let mask = 0b11111;
  107. _clear(mask);
  108. }
  109. /// Resets `fflags` field bit
  110. #[inline]
  111. pub unsafe fn clear_flag(flag: Flag) {
  112. _clear(flag as usize);
  113. }