1 /* This file is part of the dynarmic project. 2 * Copyright (c) 2016 MerryMage 3 * SPDX-License-Identifier: 0BSD 4 */ 5 6 #pragma once 7 8 #include <optional> 9 10 #include "common/bit_util.h" 11 #include "common/common_types.h" 12 #include "common/fp/rounding_mode.h" 13 14 namespace Dynarmic::A32 { 15 16 /** 17 * Representation of the Floating-Point Status and Control Register. 18 */ 19 class FPSCR final 20 { 21 public: 22 FPSCR() = default; 23 FPSCR(const FPSCR&) = default; 24 FPSCR(FPSCR&&) = default; FPSCR(u32 data)25 explicit FPSCR(u32 data) : value{data & mask} {} 26 27 FPSCR& operator=(const FPSCR&) = default; 28 FPSCR& operator=(FPSCR&&) = default; 29 FPSCR& operator=(u32 data) { 30 value = data & mask; 31 return *this; 32 } 33 34 /// Negative condition flag. N()35 bool N() const { 36 return Common::Bit<31>(value); 37 } 38 39 /// Zero condition flag. Z()40 bool Z() const { 41 return Common::Bit<30>(value); 42 } 43 44 /// Carry condition flag. C()45 bool C() const { 46 return Common::Bit<29>(value); 47 } 48 49 /// Overflow condition flag. V()50 bool V() const { 51 return Common::Bit<28>(value); 52 } 53 54 /// Cumulative saturation flag. QC()55 bool QC() const { 56 return Common::Bit<27>(value); 57 } 58 59 /// Alternate half-precision control flag. AHP()60 bool AHP() const { 61 return Common::Bit<26>(value); 62 } 63 64 /// Default NaN mode control bit. DN()65 bool DN() const { 66 return Common::Bit<25>(value); 67 } 68 69 /// Flush-to-zero mode control bit. FTZ()70 bool FTZ() const { 71 return Common::Bit<24>(value); 72 } 73 74 /// Rounding mode control field. RMode()75 FP::RoundingMode RMode() const { 76 return static_cast<FP::RoundingMode>(Common::Bits<22, 23>(value)); 77 } 78 79 /// Indicates the stride of a vector. Stride()80 std::optional<size_t> Stride() const { 81 switch (Common::Bits<20, 21>(value)) { 82 case 0b00: 83 return 1; 84 case 0b11: 85 return 2; 86 default: 87 return std::nullopt; 88 } 89 } 90 91 /// Indicates the length of a vector. Len()92 size_t Len() const { 93 return Common::Bits<16, 18>(value) + 1; 94 } 95 96 /// Input denormal exception trap enable flag. IDE()97 bool IDE() const { 98 return Common::Bit<15>(value); 99 } 100 101 /// Inexact exception trap enable flag. IXE()102 bool IXE() const { 103 return Common::Bit<12>(value); 104 } 105 106 /// Underflow exception trap enable flag. UFE()107 bool UFE() const { 108 return Common::Bit<11>(value); 109 } 110 111 /// Overflow exception trap enable flag. OFE()112 bool OFE() const { 113 return Common::Bit<10>(value); 114 } 115 116 /// Division by zero exception trap enable flag. DZE()117 bool DZE() const { 118 return Common::Bit<9>(value); 119 } 120 121 /// Invalid operation exception trap enable flag. IOE()122 bool IOE() const { 123 return Common::Bit<8>(value); 124 } 125 126 /// Input denormal cumulative exception bit. IDC()127 bool IDC() const { 128 return Common::Bit<7>(value); 129 } 130 131 /// Inexact cumulative exception bit. IXC()132 bool IXC() const { 133 return Common::Bit<4>(value); 134 } 135 136 /// Underflow cumulative exception bit. UFC()137 bool UFC() const { 138 return Common::Bit<3>(value); 139 } 140 141 /// Overflow cumulative exception bit. OFC()142 bool OFC() const { 143 return Common::Bit<2>(value); 144 } 145 146 /// Division by zero cumulative exception bit. DZC()147 bool DZC() const { 148 return Common::Bit<1>(value); 149 } 150 151 /// Invalid operation cumulative exception bit. IOC()152 bool IOC() const { 153 return Common::Bit<0>(value); 154 } 155 156 /** 157 * Whether or not the FPSCR indicates RunFast mode. 158 * 159 * RunFast mode is enabled when: 160 * - Flush-to-zero is enabled 161 * - Default NaNs are enabled. 162 * - All exception enable bits are cleared. 163 */ InRunFastMode()164 bool InRunFastMode() const { 165 constexpr u32 runfast_mask = 0x03001F00; 166 constexpr u32 expected = 0x03000000; 167 168 return (value & runfast_mask) == expected; 169 } 170 171 /// Gets the underlying raw value within the FPSCR. Value()172 u32 Value() const { 173 return value; 174 } 175 176 private: 177 // Bits 5-6, 13-14, and 19 are reserved. 178 static constexpr u32 mask = 0xFFF79F9F; 179 u32 value = 0; 180 }; 181 182 inline bool operator==(FPSCR lhs, FPSCR rhs) { 183 return lhs.Value() == rhs.Value(); 184 } 185 186 inline bool operator!=(FPSCR lhs, FPSCR rhs) { 187 return !operator==(lhs, rhs); 188 } 189 190 } // namespace Dynarmic::A32 191