1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Gabe Black 38 */ 39 40#include "arch/arm/insts/vfp.hh" 41 42/* 43 * The asm statements below are to keep gcc from reordering code. Otherwise 44 * the rounding mode might be set after the operation it was intended for, the 45 * exception bits read before it, etc. 46 */ 47 48std::string 49FpRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 50{ 51 std::stringstream ss; 52 printMnemonic(ss); 53 printReg(ss, dest + FP_Base_DepTag); 54 ss << ", "; 55 printReg(ss, op1 + FP_Base_DepTag); 56 return ss.str(); 57} 58 59std::string 60FpRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 61{ 62 std::stringstream ss; 63 printMnemonic(ss); 64 printReg(ss, dest + FP_Base_DepTag); 65 ccprintf(ss, ", #%d", imm); 66 return ss.str(); 67} 68 69std::string 70FpRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 71{ 72 std::stringstream ss; 73 printMnemonic(ss); 74 printReg(ss, dest + FP_Base_DepTag); 75 ss << ", "; 76 printReg(ss, op1 + FP_Base_DepTag); 77 ccprintf(ss, ", #%d", imm); 78 return ss.str(); 79} 80 81std::string 82FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 83{ 84 std::stringstream ss; 85 printMnemonic(ss); 86 printReg(ss, dest + FP_Base_DepTag); 87 ss << ", "; 88 printReg(ss, op1 + FP_Base_DepTag); 89 ss << ", "; 90 printReg(ss, op2 + FP_Base_DepTag); 91 return ss.str(); 92} 93
| 1/* 2 * Copyright (c) 2010 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Gabe Black 38 */ 39 40#include "arch/arm/insts/vfp.hh" 41 42/* 43 * The asm statements below are to keep gcc from reordering code. Otherwise 44 * the rounding mode might be set after the operation it was intended for, the 45 * exception bits read before it, etc. 46 */ 47 48std::string 49FpRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 50{ 51 std::stringstream ss; 52 printMnemonic(ss); 53 printReg(ss, dest + FP_Base_DepTag); 54 ss << ", "; 55 printReg(ss, op1 + FP_Base_DepTag); 56 return ss.str(); 57} 58 59std::string 60FpRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 61{ 62 std::stringstream ss; 63 printMnemonic(ss); 64 printReg(ss, dest + FP_Base_DepTag); 65 ccprintf(ss, ", #%d", imm); 66 return ss.str(); 67} 68 69std::string 70FpRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 71{ 72 std::stringstream ss; 73 printMnemonic(ss); 74 printReg(ss, dest + FP_Base_DepTag); 75 ss << ", "; 76 printReg(ss, op1 + FP_Base_DepTag); 77 ccprintf(ss, ", #%d", imm); 78 return ss.str(); 79} 80 81std::string 82FpRegRegRegOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 83{ 84 std::stringstream ss; 85 printMnemonic(ss); 86 printReg(ss, dest + FP_Base_DepTag); 87 ss << ", "; 88 printReg(ss, op1 + FP_Base_DepTag); 89 ss << ", "; 90 printReg(ss, op2 + FP_Base_DepTag); 91 return ss.str(); 92} 93
|
| 94std::string 95FpRegRegRegImmOp::generateDisassembly(Addr pc, const SymbolTable *symtab) const 96{ 97 std::stringstream ss; 98 printMnemonic(ss); 99 printReg(ss, dest + FP_Base_DepTag); 100 ss << ", "; 101 printReg(ss, op1 + FP_Base_DepTag); 102 ss << ", "; 103 printReg(ss, op2 + FP_Base_DepTag); 104 ccprintf(ss, ", #%d", imm); 105 return ss.str(); 106} 107
|
94namespace ArmISA 95{ 96 97VfpSavedState 98prepFpState(uint32_t rMode) 99{ 100 int roundingMode = fegetround(); 101 feclearexcept(FeAllExceptions); 102 switch (rMode) { 103 case VfpRoundNearest: 104 fesetround(FeRoundNearest); 105 break; 106 case VfpRoundUpward: 107 fesetround(FeRoundUpward); 108 break; 109 case VfpRoundDown: 110 fesetround(FeRoundDown); 111 break; 112 case VfpRoundZero: 113 fesetround(FeRoundZero); 114 break; 115 } 116 return roundingMode; 117} 118 119void
| 108namespace ArmISA 109{ 110 111VfpSavedState 112prepFpState(uint32_t rMode) 113{ 114 int roundingMode = fegetround(); 115 feclearexcept(FeAllExceptions); 116 switch (rMode) { 117 case VfpRoundNearest: 118 fesetround(FeRoundNearest); 119 break; 120 case VfpRoundUpward: 121 fesetround(FeRoundUpward); 122 break; 123 case VfpRoundDown: 124 fesetround(FeRoundDown); 125 break; 126 case VfpRoundZero: 127 fesetround(FeRoundZero); 128 break; 129 } 130 return roundingMode; 131} 132 133void
|
120finishVfp(FPSCR &fpscr, VfpSavedState state)
| 134finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush)
|
121{ 122 int exceptions = fetestexcept(FeAllExceptions); 123 bool underflow = false; 124 if (exceptions & FeInvalid) { 125 fpscr.ioc = 1; 126 } 127 if (exceptions & FeDivByZero) { 128 fpscr.dzc = 1; 129 } 130 if (exceptions & FeOverflow) { 131 fpscr.ofc = 1; 132 } 133 if (exceptions & FeUnderflow) { 134 underflow = true; 135 fpscr.ufc = 1; 136 }
| 135{ 136 int exceptions = fetestexcept(FeAllExceptions); 137 bool underflow = false; 138 if (exceptions & FeInvalid) { 139 fpscr.ioc = 1; 140 } 141 if (exceptions & FeDivByZero) { 142 fpscr.dzc = 1; 143 } 144 if (exceptions & FeOverflow) { 145 fpscr.ofc = 1; 146 } 147 if (exceptions & FeUnderflow) { 148 underflow = true; 149 fpscr.ufc = 1; 150 }
|
137 if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) {
| 151 if ((exceptions & FeInexact) && !(underflow && flush)) {
|
138 fpscr.ixc = 1; 139 } 140 fesetround(state); 141} 142 143template <class fpType> 144fpType
| 152 fpscr.ixc = 1; 153 } 154 fesetround(state); 155} 156 157template <class fpType> 158fpType
|
145fixDest(FPSCR fpscr, fpType val, fpType op1)
| 159fixDest(bool flush, bool defaultNan, fpType val, fpType op1)
|
146{ 147 int fpClass = std::fpclassify(val); 148 fpType junk = 0.0; 149 if (fpClass == FP_NAN) { 150 const bool single = (sizeof(val) == sizeof(float)); 151 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 152 const bool nan = std::isnan(op1);
| 160{ 161 int fpClass = std::fpclassify(val); 162 fpType junk = 0.0; 163 if (fpClass == FP_NAN) { 164 const bool single = (sizeof(val) == sizeof(float)); 165 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 166 const bool nan = std::isnan(op1);
|
153 if (!nan || (fpscr.dn == 1)) {
| 167 if (!nan || defaultNan) {
|
154 val = bitsToFp(qnan, junk); 155 } else if (nan) { 156 val = bitsToFp(fpToBits(op1) | qnan, junk); 157 }
| 168 val = bitsToFp(qnan, junk); 169 } else if (nan) { 170 val = bitsToFp(fpToBits(op1) | qnan, junk); 171 }
|
158 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
| 172 } else if (fpClass == FP_SUBNORMAL && flush == 1) {
|
159 // Turn val into a zero with the correct sign; 160 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 161 val = bitsToFp(fpToBits(val) & bitMask, junk); 162 feclearexcept(FeInexact); 163 feraiseexcept(FeUnderflow); 164 } 165 return val; 166} 167 168template
| 173 // Turn val into a zero with the correct sign; 174 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 175 val = bitsToFp(fpToBits(val) & bitMask, junk); 176 feclearexcept(FeInexact); 177 feraiseexcept(FeUnderflow); 178 } 179 return val; 180} 181 182template
|
169float fixDest<float>(FPSCR fpscr, float val, float op1);
| 183float fixDest<float>(bool flush, bool defaultNan, float val, float op1);
|
170template
| 184template
|
171double fixDest<double>(FPSCR fpscr, double val, double op1);
| 185double fixDest<double>(bool flush, bool defaultNan, double val, double op1);
|
172 173template <class fpType> 174fpType
| 186 187template <class fpType> 188fpType
|
175fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
| 189fixDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
|
176{ 177 int fpClass = std::fpclassify(val); 178 fpType junk = 0.0; 179 if (fpClass == FP_NAN) { 180 const bool single = (sizeof(val) == sizeof(float)); 181 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 182 const bool nan1 = std::isnan(op1); 183 const bool nan2 = std::isnan(op2); 184 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 185 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
| 190{ 191 int fpClass = std::fpclassify(val); 192 fpType junk = 0.0; 193 if (fpClass == FP_NAN) { 194 const bool single = (sizeof(val) == sizeof(float)); 195 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000); 196 const bool nan1 = std::isnan(op1); 197 const bool nan2 = std::isnan(op2); 198 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 199 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
|
186 if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
| 200 if ((!nan1 && !nan2) || defaultNan) {
|
187 val = bitsToFp(qnan, junk); 188 } else if (signal1) { 189 val = bitsToFp(fpToBits(op1) | qnan, junk); 190 } else if (signal2) { 191 val = bitsToFp(fpToBits(op2) | qnan, junk); 192 } else if (nan1) { 193 val = op1; 194 } else if (nan2) { 195 val = op2; 196 }
| 201 val = bitsToFp(qnan, junk); 202 } else if (signal1) { 203 val = bitsToFp(fpToBits(op1) | qnan, junk); 204 } else if (signal2) { 205 val = bitsToFp(fpToBits(op2) | qnan, junk); 206 } else if (nan1) { 207 val = op1; 208 } else if (nan2) { 209 val = op2; 210 }
|
197 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
| 211 } else if (fpClass == FP_SUBNORMAL && flush) {
|
198 // Turn val into a zero with the correct sign; 199 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 200 val = bitsToFp(fpToBits(val) & bitMask, junk); 201 feclearexcept(FeInexact); 202 feraiseexcept(FeUnderflow); 203 } 204 return val; 205} 206 207template
| 212 // Turn val into a zero with the correct sign; 213 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1); 214 val = bitsToFp(fpToBits(val) & bitMask, junk); 215 feclearexcept(FeInexact); 216 feraiseexcept(FeUnderflow); 217 } 218 return val; 219} 220 221template
|
208float fixDest<float>(FPSCR fpscr, float val, float op1, float op2);
| 222float fixDest<float>(bool flush, bool defaultNan, 223 float val, float op1, float op2);
|
209template
| 224template
|
210double fixDest<double>(FPSCR fpscr, double val, double op1, double op2);
| 225double fixDest<double>(bool flush, bool defaultNan, 226 double val, double op1, double op2);
|
211 212template <class fpType> 213fpType
| 227 228template <class fpType> 229fpType
|
214fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
| 230fixDivDest(bool flush, bool defaultNan, fpType val, fpType op1, fpType op2)
|
215{
| 231{
|
216 fpType mid = fixDest(fpscr, val, op1, op2);
| 232 fpType mid = fixDest(flush, defaultNan, val, op1, op2);
|
217 const bool single = (sizeof(fpType) == sizeof(float)); 218 const fpType junk = 0.0; 219 if ((single && (val == bitsToFp(0x00800000, junk) || 220 val == bitsToFp(0x80800000, junk))) || 221 (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 222 val == bitsToFp(ULL(0x8010000000000000), junk))) 223 ) { 224 __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 225 fesetround(FeRoundZero); 226 fpType temp = 0.0; 227 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 228 temp = op1 / op2; 229 if (flushToZero(temp)) { 230 feraiseexcept(FeUnderflow);
| 233 const bool single = (sizeof(fpType) == sizeof(float)); 234 const fpType junk = 0.0; 235 if ((single && (val == bitsToFp(0x00800000, junk) || 236 val == bitsToFp(0x80800000, junk))) || 237 (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) || 238 val == bitsToFp(ULL(0x8010000000000000), junk))) 239 ) { 240 __asm__ __volatile__("" : "=m" (op1) : "m" (op1)); 241 fesetround(FeRoundZero); 242 fpType temp = 0.0; 243 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 244 temp = op1 / op2; 245 if (flushToZero(temp)) { 246 feraiseexcept(FeUnderflow);
|
231 if (fpscr.fz) {
| 247 if (flush) {
|
232 feclearexcept(FeInexact); 233 mid = temp; 234 } 235 } 236 __asm__ __volatile__("" :: "m" (temp)); 237 } 238 return mid; 239} 240 241template
| 248 feclearexcept(FeInexact); 249 mid = temp; 250 } 251 } 252 __asm__ __volatile__("" :: "m" (temp)); 253 } 254 return mid; 255} 256 257template
|
242float fixDivDest<float>(FPSCR fpscr, float val, float op1, float op2);
| 258float fixDivDest<float>(bool flush, bool defaultNan, 259 float val, float op1, float op2);
|
243template
| 260template
|
244double fixDivDest<double>(FPSCR fpscr, double val, double op1, double op2);
| 261double fixDivDest<double>(bool flush, bool defaultNan, 262 double val, double op1, double op2);
|
245 246float 247fixFpDFpSDest(FPSCR fpscr, double val) 248{ 249 const float junk = 0.0; 250 float op1 = 0.0; 251 if (std::isnan(val)) { 252 uint64_t valBits = fpToBits(val); 253 uint32_t op1Bits = bits(valBits, 50, 29) | 254 (mask(9) << 22) | 255 (bits(valBits, 63) << 31); 256 op1 = bitsToFp(op1Bits, junk); 257 }
| 263 264float 265fixFpDFpSDest(FPSCR fpscr, double val) 266{ 267 const float junk = 0.0; 268 float op1 = 0.0; 269 if (std::isnan(val)) { 270 uint64_t valBits = fpToBits(val); 271 uint32_t op1Bits = bits(valBits, 50, 29) | 272 (mask(9) << 22) | 273 (bits(valBits, 63) << 31); 274 op1 = bitsToFp(op1Bits, junk); 275 }
|
258 float mid = fixDest(fpscr, (float)val, op1);
| 276 float mid = fixDest(fpscr.fz, fpscr.dn, (float)val, op1);
|
259 if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 260 (FeUnderflow | FeInexact)) { 261 feclearexcept(FeInexact); 262 } 263 if (mid == bitsToFp(0x00800000, junk) || 264 mid == bitsToFp(0x80800000, junk)) { 265 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 266 fesetround(FeRoundZero); 267 float temp = 0.0; 268 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 269 temp = val; 270 if (flushToZero(temp)) { 271 feraiseexcept(FeUnderflow); 272 if (fpscr.fz) { 273 feclearexcept(FeInexact); 274 mid = temp; 275 } 276 } 277 __asm__ __volatile__("" :: "m" (temp)); 278 } 279 return mid; 280} 281 282double 283fixFpSFpDDest(FPSCR fpscr, float val) 284{ 285 const double junk = 0.0; 286 double op1 = 0.0; 287 if (std::isnan(val)) { 288 uint32_t valBits = fpToBits(val); 289 uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 290 (mask(12) << 51) | 291 ((uint64_t)bits(valBits, 31) << 63); 292 op1 = bitsToFp(op1Bits, junk); 293 }
| 277 if (fpscr.fz && fetestexcept(FeUnderflow | FeInexact) == 278 (FeUnderflow | FeInexact)) { 279 feclearexcept(FeInexact); 280 } 281 if (mid == bitsToFp(0x00800000, junk) || 282 mid == bitsToFp(0x80800000, junk)) { 283 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 284 fesetround(FeRoundZero); 285 float temp = 0.0; 286 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 287 temp = val; 288 if (flushToZero(temp)) { 289 feraiseexcept(FeUnderflow); 290 if (fpscr.fz) { 291 feclearexcept(FeInexact); 292 mid = temp; 293 } 294 } 295 __asm__ __volatile__("" :: "m" (temp)); 296 } 297 return mid; 298} 299 300double 301fixFpSFpDDest(FPSCR fpscr, float val) 302{ 303 const double junk = 0.0; 304 double op1 = 0.0; 305 if (std::isnan(val)) { 306 uint32_t valBits = fpToBits(val); 307 uint64_t op1Bits = ((uint64_t)bits(valBits, 21, 0) << 29) | 308 (mask(12) << 51) | 309 ((uint64_t)bits(valBits, 31) << 63); 310 op1 = bitsToFp(op1Bits, junk); 311 }
|
294 double mid = fixDest(fpscr, (double)val, op1);
| 312 double mid = fixDest(fpscr.fz, fpscr.dn, (double)val, op1);
|
295 if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 296 mid == bitsToFp(ULL(0x8010000000000000), junk)) { 297 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 298 fesetround(FeRoundZero); 299 double temp = 0.0; 300 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 301 temp = val; 302 if (flushToZero(temp)) { 303 feraiseexcept(FeUnderflow); 304 if (fpscr.fz) { 305 feclearexcept(FeInexact); 306 mid = temp; 307 } 308 } 309 __asm__ __volatile__("" :: "m" (temp)); 310 } 311 return mid; 312} 313
| 313 if (mid == bitsToFp(ULL(0x0010000000000000), junk) || 314 mid == bitsToFp(ULL(0x8010000000000000), junk)) { 315 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 316 fesetround(FeRoundZero); 317 double temp = 0.0; 318 __asm__ __volatile__("" : "=m" (temp) : "m" (temp)); 319 temp = val; 320 if (flushToZero(temp)) { 321 feraiseexcept(FeUnderflow); 322 if (fpscr.fz) { 323 feclearexcept(FeInexact); 324 mid = temp; 325 } 326 } 327 __asm__ __volatile__("" :: "m" (temp)); 328 } 329 return mid; 330} 331
|
314float 315vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top)
| 332uint16_t 333vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan, 334 uint32_t rMode, bool ahp, float op)
|
316{
| 335{
|
317 float junk = 0.0; 318 uint32_t destBits = fpToBits(dest);
| |
319 uint32_t opBits = fpToBits(op); 320 // Extract the operand. 321 bool neg = bits(opBits, 31); 322 uint32_t exponent = bits(opBits, 30, 23); 323 uint32_t oldMantissa = bits(opBits, 22, 0); 324 uint32_t mantissa = oldMantissa >> (23 - 10); 325 // Do the conversion. 326 uint32_t extra = oldMantissa & mask(23 - 10); 327 if (exponent == 0xff) { 328 if (oldMantissa != 0) { 329 // Nans. 330 if (bits(mantissa, 9) == 0) { 331 // Signalling nan. 332 fpscr.ioc = 1; 333 }
| 336 uint32_t opBits = fpToBits(op); 337 // Extract the operand. 338 bool neg = bits(opBits, 31); 339 uint32_t exponent = bits(opBits, 30, 23); 340 uint32_t oldMantissa = bits(opBits, 22, 0); 341 uint32_t mantissa = oldMantissa >> (23 - 10); 342 // Do the conversion. 343 uint32_t extra = oldMantissa & mask(23 - 10); 344 if (exponent == 0xff) { 345 if (oldMantissa != 0) { 346 // Nans. 347 if (bits(mantissa, 9) == 0) { 348 // Signalling nan. 349 fpscr.ioc = 1; 350 }
|
334 if (fpscr.ahp) {
| 351 if (ahp) {
|
335 mantissa = 0; 336 exponent = 0; 337 fpscr.ioc = 1;
| 352 mantissa = 0; 353 exponent = 0; 354 fpscr.ioc = 1;
|
338 } else if (fpscr.dn) {
| 355 } else if (defaultNan) {
|
339 mantissa = (1 << 9); 340 exponent = 0x1f; 341 neg = false; 342 } else { 343 exponent = 0x1f; 344 mantissa |= (1 << 9); 345 } 346 } else { 347 // Infinities. 348 exponent = 0x1F;
| 356 mantissa = (1 << 9); 357 exponent = 0x1f; 358 neg = false; 359 } else { 360 exponent = 0x1f; 361 mantissa |= (1 << 9); 362 } 363 } else { 364 // Infinities. 365 exponent = 0x1F;
|
349 if (fpscr.ahp) {
| 366 if (ahp) {
|
350 fpscr.ioc = 1; 351 mantissa = 0x3ff; 352 } else { 353 mantissa = 0; 354 } 355 } 356 } else if (exponent == 0 && oldMantissa == 0) { 357 // Zero, don't need to do anything. 358 } else { 359 // Normalized or denormalized numbers. 360 361 bool inexact = (extra != 0); 362 363 if (exponent == 0) { 364 // Denormalized. 365 366 // If flush to zero is on, this shouldn't happen.
| 367 fpscr.ioc = 1; 368 mantissa = 0x3ff; 369 } else { 370 mantissa = 0; 371 } 372 } 373 } else if (exponent == 0 && oldMantissa == 0) { 374 // Zero, don't need to do anything. 375 } else { 376 // Normalized or denormalized numbers. 377 378 bool inexact = (extra != 0); 379 380 if (exponent == 0) { 381 // Denormalized. 382 383 // If flush to zero is on, this shouldn't happen.
|
367 assert(fpscr.fz == 0);
| 384 assert(!flush);
|
368 369 // Check for underflow 370 if (inexact || fpscr.ufe) 371 fpscr.ufc = 1; 372 373 // Handle rounding.
| 385 386 // Check for underflow 387 if (inexact || fpscr.ufe) 388 fpscr.ufc = 1; 389 390 // Handle rounding.
|
374 unsigned mode = fpscr.rMode;
| 391 unsigned mode = rMode;
|
375 if ((mode == VfpRoundUpward && !neg && extra) || 376 (mode == VfpRoundDown && neg && extra) || 377 (mode == VfpRoundNearest && 378 (extra > (1 << 9) || 379 (extra == (1 << 9) && bits(mantissa, 0))))) { 380 mantissa++; 381 } 382 383 // See if the number became normalized after rounding. 384 if (mantissa == (1 << 10)) { 385 mantissa = 0; 386 exponent = 1; 387 } 388 } else { 389 // Normalized. 390 391 // We need to track the dropped bits differently since 392 // more can be dropped by denormalizing. 393 bool topOne = bits(extra, 12); 394 bool restZeros = bits(extra, 11, 0) == 0; 395 396 if (exponent <= (127 - 15)) { 397 // The result is too small. Denormalize. 398 mantissa |= (1 << 10); 399 while (mantissa && exponent <= (127 - 15)) { 400 restZeros = restZeros && !topOne; 401 topOne = bits(mantissa, 0); 402 mantissa = mantissa >> 1; 403 exponent++; 404 } 405 if (topOne || !restZeros) 406 inexact = true; 407 exponent = 0; 408 } else { 409 // Change bias. 410 exponent -= (127 - 15); 411 } 412 413 if (exponent == 0 && (inexact || fpscr.ufe)) { 414 // Underflow 415 fpscr.ufc = 1; 416 } 417 418 // Handle rounding.
| 392 if ((mode == VfpRoundUpward && !neg && extra) || 393 (mode == VfpRoundDown && neg && extra) || 394 (mode == VfpRoundNearest && 395 (extra > (1 << 9) || 396 (extra == (1 << 9) && bits(mantissa, 0))))) { 397 mantissa++; 398 } 399 400 // See if the number became normalized after rounding. 401 if (mantissa == (1 << 10)) { 402 mantissa = 0; 403 exponent = 1; 404 } 405 } else { 406 // Normalized. 407 408 // We need to track the dropped bits differently since 409 // more can be dropped by denormalizing. 410 bool topOne = bits(extra, 12); 411 bool restZeros = bits(extra, 11, 0) == 0; 412 413 if (exponent <= (127 - 15)) { 414 // The result is too small. Denormalize. 415 mantissa |= (1 << 10); 416 while (mantissa && exponent <= (127 - 15)) { 417 restZeros = restZeros && !topOne; 418 topOne = bits(mantissa, 0); 419 mantissa = mantissa >> 1; 420 exponent++; 421 } 422 if (topOne || !restZeros) 423 inexact = true; 424 exponent = 0; 425 } else { 426 // Change bias. 427 exponent -= (127 - 15); 428 } 429 430 if (exponent == 0 && (inexact || fpscr.ufe)) { 431 // Underflow 432 fpscr.ufc = 1; 433 } 434 435 // Handle rounding.
|
419 unsigned mode = fpscr.rMode;
| 436 unsigned mode = rMode;
|
420 bool nonZero = topOne || !restZeros; 421 if ((mode == VfpRoundUpward && !neg && nonZero) || 422 (mode == VfpRoundDown && neg && nonZero) || 423 (mode == VfpRoundNearest && topOne && 424 (!restZeros || bits(mantissa, 0)))) { 425 mantissa++; 426 } 427 428 // See if we rounded up and need to bump the exponent. 429 if (mantissa == (1 << 10)) { 430 mantissa = 0; 431 exponent++; 432 } 433 434 // Deal with overflow
| 437 bool nonZero = topOne || !restZeros; 438 if ((mode == VfpRoundUpward && !neg && nonZero) || 439 (mode == VfpRoundDown && neg && nonZero) || 440 (mode == VfpRoundNearest && topOne && 441 (!restZeros || bits(mantissa, 0)))) { 442 mantissa++; 443 } 444 445 // See if we rounded up and need to bump the exponent. 446 if (mantissa == (1 << 10)) { 447 mantissa = 0; 448 exponent++; 449 } 450 451 // Deal with overflow
|
435 if (fpscr.ahp) {
| 452 if (ahp) {
|
436 if (exponent >= 0x20) { 437 exponent = 0x1f; 438 mantissa = 0x3ff; 439 fpscr.ioc = 1; 440 // Supress inexact exception. 441 inexact = false; 442 } 443 } else { 444 if (exponent >= 0x1f) { 445 if ((mode == VfpRoundNearest) || 446 (mode == VfpRoundUpward && !neg) || 447 (mode == VfpRoundDown && neg)) { 448 // Overflow to infinity. 449 exponent = 0x1f; 450 mantissa = 0; 451 } else { 452 // Overflow to max normal. 453 exponent = 0x1e; 454 mantissa = 0x3ff; 455 } 456 fpscr.ofc = 1; 457 inexact = true; 458 } 459 } 460 } 461 462 if (inexact) { 463 fpscr.ixc = 1; 464 } 465 } 466 // Reassemble and install the result. 467 uint32_t result = bits(mantissa, 9, 0); 468 replaceBits(result, 14, 10, exponent); 469 if (neg) 470 result |= (1 << 15);
| 453 if (exponent >= 0x20) { 454 exponent = 0x1f; 455 mantissa = 0x3ff; 456 fpscr.ioc = 1; 457 // Supress inexact exception. 458 inexact = false; 459 } 460 } else { 461 if (exponent >= 0x1f) { 462 if ((mode == VfpRoundNearest) || 463 (mode == VfpRoundUpward && !neg) || 464 (mode == VfpRoundDown && neg)) { 465 // Overflow to infinity. 466 exponent = 0x1f; 467 mantissa = 0; 468 } else { 469 // Overflow to max normal. 470 exponent = 0x1e; 471 mantissa = 0x3ff; 472 } 473 fpscr.ofc = 1; 474 inexact = true; 475 } 476 } 477 } 478 479 if (inexact) { 480 fpscr.ixc = 1; 481 } 482 } 483 // Reassemble and install the result. 484 uint32_t result = bits(mantissa, 9, 0); 485 replaceBits(result, 14, 10, exponent); 486 if (neg) 487 result |= (1 << 15);
|
471 if (top) 472 replaceBits(destBits, 31, 16, result); 473 else 474 replaceBits(destBits, 15, 0, result); 475 return bitsToFp(destBits, junk);
| 488 return result;
|
476} 477 478float
| 489} 490 491float
|
479vcvtFpHFpS(FPSCR &fpscr, float op, bool top)
| 492vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op)
|
480{ 481 float junk = 0.0;
| 493{ 494 float junk = 0.0;
|
482 uint32_t opBits = fpToBits(op); 483 // Extract the operand. 484 if (top) 485 opBits = bits(opBits, 31, 16); 486 else 487 opBits = bits(opBits, 15, 0);
| |
488 // Extract the bitfields.
| 495 // Extract the bitfields.
|
489 bool neg = bits(opBits, 15); 490 uint32_t exponent = bits(opBits, 14, 10); 491 uint32_t mantissa = bits(opBits, 9, 0);
| 496 bool neg = bits(op, 15); 497 uint32_t exponent = bits(op, 14, 10); 498 uint32_t mantissa = bits(op, 9, 0);
|
492 // Do the conversion. 493 if (exponent == 0) { 494 if (mantissa != 0) { 495 // Normalize the value. 496 exponent = exponent + (127 - 15) + 1; 497 while (mantissa < (1 << 10)) { 498 mantissa = mantissa << 1; 499 exponent--; 500 } 501 } 502 mantissa = mantissa << (23 - 10);
| 499 // Do the conversion. 500 if (exponent == 0) { 501 if (mantissa != 0) { 502 // Normalize the value. 503 exponent = exponent + (127 - 15) + 1; 504 while (mantissa < (1 << 10)) { 505 mantissa = mantissa << 1; 506 exponent--; 507 } 508 } 509 mantissa = mantissa << (23 - 10);
|
503 } else if (exponent == 0x1f && !fpscr.ahp) {
| 510 } else if (exponent == 0x1f && !ahp) {
|
504 // Infinities and nans. 505 exponent = 0xff; 506 if (mantissa != 0) { 507 // Nans. 508 mantissa = mantissa << (23 - 10); 509 if (bits(mantissa, 22) == 0) { 510 // Signalling nan. 511 fpscr.ioc = 1; 512 mantissa |= (1 << 22); 513 }
| 511 // Infinities and nans. 512 exponent = 0xff; 513 if (mantissa != 0) { 514 // Nans. 515 mantissa = mantissa << (23 - 10); 516 if (bits(mantissa, 22) == 0) { 517 // Signalling nan. 518 fpscr.ioc = 1; 519 mantissa |= (1 << 22); 520 }
|
514 if (fpscr.dn) {
| 521 if (defaultNan) {
|
515 mantissa &= ~mask(22); 516 neg = false; 517 } 518 } 519 } else { 520 exponent = exponent + (127 - 15); 521 mantissa = mantissa << (23 - 10); 522 } 523 // Reassemble the result. 524 uint32_t result = bits(mantissa, 22, 0); 525 replaceBits(result, 30, 23, exponent); 526 if (neg) 527 result |= (1 << 31); 528 return bitsToFp(result, junk); 529} 530 531uint64_t 532vfpFpSToFixed(float val, bool isSigned, bool half, 533 uint8_t imm, bool rzero) 534{ 535 int rmode = rzero ? FeRoundZero : fegetround(); 536 __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); 537 fesetround(FeRoundNearest); 538 val = val * powf(2.0, imm); 539 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 540 fesetround(rmode); 541 feclearexcept(FeAllExceptions); 542 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 543 float origVal = val; 544 val = rintf(val); 545 int fpType = std::fpclassify(val); 546 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 547 if (fpType == FP_NAN) { 548 feraiseexcept(FeInvalid); 549 } 550 val = 0.0; 551 } else if (origVal != val) { 552 switch (rmode) { 553 case FeRoundNearest: 554 if (origVal - val > 0.5) 555 val += 1.0; 556 else if (val - origVal > 0.5) 557 val -= 1.0; 558 break; 559 case FeRoundDown: 560 if (origVal < val) 561 val -= 1.0; 562 break; 563 case FeRoundUpward: 564 if (origVal > val) 565 val += 1.0; 566 break; 567 } 568 feraiseexcept(FeInexact); 569 } 570 571 if (isSigned) { 572 if (half) { 573 if ((double)val < (int16_t)(1 << 15)) { 574 feraiseexcept(FeInvalid); 575 feclearexcept(FeInexact); 576 return (int16_t)(1 << 15); 577 } 578 if ((double)val > (int16_t)mask(15)) { 579 feraiseexcept(FeInvalid); 580 feclearexcept(FeInexact); 581 return (int16_t)mask(15); 582 } 583 return (int16_t)val; 584 } else { 585 if ((double)val < (int32_t)(1 << 31)) { 586 feraiseexcept(FeInvalid); 587 feclearexcept(FeInexact); 588 return (int32_t)(1 << 31); 589 } 590 if ((double)val > (int32_t)mask(31)) { 591 feraiseexcept(FeInvalid); 592 feclearexcept(FeInexact); 593 return (int32_t)mask(31); 594 } 595 return (int32_t)val; 596 } 597 } else { 598 if (half) { 599 if ((double)val < 0) { 600 feraiseexcept(FeInvalid); 601 feclearexcept(FeInexact); 602 return 0; 603 } 604 if ((double)val > (mask(16))) { 605 feraiseexcept(FeInvalid); 606 feclearexcept(FeInexact); 607 return mask(16); 608 } 609 return (uint16_t)val; 610 } else { 611 if ((double)val < 0) { 612 feraiseexcept(FeInvalid); 613 feclearexcept(FeInexact); 614 return 0; 615 } 616 if ((double)val > (mask(32))) { 617 feraiseexcept(FeInvalid); 618 feclearexcept(FeInexact); 619 return mask(32); 620 } 621 return (uint32_t)val; 622 } 623 } 624} 625 626float
| 522 mantissa &= ~mask(22); 523 neg = false; 524 } 525 } 526 } else { 527 exponent = exponent + (127 - 15); 528 mantissa = mantissa << (23 - 10); 529 } 530 // Reassemble the result. 531 uint32_t result = bits(mantissa, 22, 0); 532 replaceBits(result, 30, 23, exponent); 533 if (neg) 534 result |= (1 << 31); 535 return bitsToFp(result, junk); 536} 537 538uint64_t 539vfpFpSToFixed(float val, bool isSigned, bool half, 540 uint8_t imm, bool rzero) 541{ 542 int rmode = rzero ? FeRoundZero : fegetround(); 543 __asm__ __volatile__("" : "=m" (rmode) : "m" (rmode)); 544 fesetround(FeRoundNearest); 545 val = val * powf(2.0, imm); 546 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 547 fesetround(rmode); 548 feclearexcept(FeAllExceptions); 549 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 550 float origVal = val; 551 val = rintf(val); 552 int fpType = std::fpclassify(val); 553 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 554 if (fpType == FP_NAN) { 555 feraiseexcept(FeInvalid); 556 } 557 val = 0.0; 558 } else if (origVal != val) { 559 switch (rmode) { 560 case FeRoundNearest: 561 if (origVal - val > 0.5) 562 val += 1.0; 563 else if (val - origVal > 0.5) 564 val -= 1.0; 565 break; 566 case FeRoundDown: 567 if (origVal < val) 568 val -= 1.0; 569 break; 570 case FeRoundUpward: 571 if (origVal > val) 572 val += 1.0; 573 break; 574 } 575 feraiseexcept(FeInexact); 576 } 577 578 if (isSigned) { 579 if (half) { 580 if ((double)val < (int16_t)(1 << 15)) { 581 feraiseexcept(FeInvalid); 582 feclearexcept(FeInexact); 583 return (int16_t)(1 << 15); 584 } 585 if ((double)val > (int16_t)mask(15)) { 586 feraiseexcept(FeInvalid); 587 feclearexcept(FeInexact); 588 return (int16_t)mask(15); 589 } 590 return (int16_t)val; 591 } else { 592 if ((double)val < (int32_t)(1 << 31)) { 593 feraiseexcept(FeInvalid); 594 feclearexcept(FeInexact); 595 return (int32_t)(1 << 31); 596 } 597 if ((double)val > (int32_t)mask(31)) { 598 feraiseexcept(FeInvalid); 599 feclearexcept(FeInexact); 600 return (int32_t)mask(31); 601 } 602 return (int32_t)val; 603 } 604 } else { 605 if (half) { 606 if ((double)val < 0) { 607 feraiseexcept(FeInvalid); 608 feclearexcept(FeInexact); 609 return 0; 610 } 611 if ((double)val > (mask(16))) { 612 feraiseexcept(FeInvalid); 613 feclearexcept(FeInexact); 614 return mask(16); 615 } 616 return (uint16_t)val; 617 } else { 618 if ((double)val < 0) { 619 feraiseexcept(FeInvalid); 620 feclearexcept(FeInexact); 621 return 0; 622 } 623 if ((double)val > (mask(32))) { 624 feraiseexcept(FeInvalid); 625 feclearexcept(FeInexact); 626 return mask(32); 627 } 628 return (uint32_t)val; 629 } 630 } 631} 632 633float
|
627vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm)
| 634vfpUFixedToFpS(bool flush, bool defaultNan, 635 uint32_t val, bool half, uint8_t imm)
|
628{ 629 fesetround(FeRoundNearest); 630 if (half) 631 val = (uint16_t)val; 632 float scale = powf(2.0, imm); 633 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 634 feclearexcept(FeAllExceptions); 635 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
| 636{ 637 fesetround(FeRoundNearest); 638 if (half) 639 val = (uint16_t)val; 640 float scale = powf(2.0, imm); 641 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 642 feclearexcept(FeAllExceptions); 643 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
|
636 return fixDivDest(fpscr, val / scale, (float)val, scale);
| 644 return fixDivDest(flush, defaultNan, val / scale, (float)val, scale);
|
637} 638 639float
| 645} 646 647float
|
640vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm)
| 648vfpSFixedToFpS(bool flush, bool defaultNan, 649 int32_t val, bool half, uint8_t imm)
|
641{ 642 fesetround(FeRoundNearest); 643 if (half) 644 val = sext<16>(val & mask(16)); 645 float scale = powf(2.0, imm); 646 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 647 feclearexcept(FeAllExceptions); 648 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
| 650{ 651 fesetround(FeRoundNearest); 652 if (half) 653 val = sext<16>(val & mask(16)); 654 float scale = powf(2.0, imm); 655 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 656 feclearexcept(FeAllExceptions); 657 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
|
649 return fixDivDest(fpscr, val / scale, (float)val, scale);
| 658 return fixDivDest(flush, defaultNan, val / scale, (float)val, scale);
|
650} 651 652uint64_t 653vfpFpDToFixed(double val, bool isSigned, bool half, 654 uint8_t imm, bool rzero) 655{ 656 int rmode = rzero ? FeRoundZero : fegetround(); 657 fesetround(FeRoundNearest); 658 val = val * pow(2.0, imm); 659 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 660 fesetround(rmode); 661 feclearexcept(FeAllExceptions); 662 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 663 double origVal = val; 664 val = rint(val); 665 int fpType = std::fpclassify(val); 666 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 667 if (fpType == FP_NAN) { 668 feraiseexcept(FeInvalid); 669 } 670 val = 0.0; 671 } else if (origVal != val) { 672 switch (rmode) { 673 case FeRoundNearest: 674 if (origVal - val > 0.5) 675 val += 1.0; 676 else if (val - origVal > 0.5) 677 val -= 1.0; 678 break; 679 case FeRoundDown: 680 if (origVal < val) 681 val -= 1.0; 682 break; 683 case FeRoundUpward: 684 if (origVal > val) 685 val += 1.0; 686 break; 687 } 688 feraiseexcept(FeInexact); 689 } 690 if (isSigned) { 691 if (half) { 692 if (val < (int16_t)(1 << 15)) { 693 feraiseexcept(FeInvalid); 694 feclearexcept(FeInexact); 695 return (int16_t)(1 << 15); 696 } 697 if (val > (int16_t)mask(15)) { 698 feraiseexcept(FeInvalid); 699 feclearexcept(FeInexact); 700 return (int16_t)mask(15); 701 } 702 return (int16_t)val; 703 } else { 704 if (val < (int32_t)(1 << 31)) { 705 feraiseexcept(FeInvalid); 706 feclearexcept(FeInexact); 707 return (int32_t)(1 << 31); 708 } 709 if (val > (int32_t)mask(31)) { 710 feraiseexcept(FeInvalid); 711 feclearexcept(FeInexact); 712 return (int32_t)mask(31); 713 } 714 return (int32_t)val; 715 } 716 } else { 717 if (half) { 718 if (val < 0) { 719 feraiseexcept(FeInvalid); 720 feclearexcept(FeInexact); 721 return 0; 722 } 723 if (val > mask(16)) { 724 feraiseexcept(FeInvalid); 725 feclearexcept(FeInexact); 726 return mask(16); 727 } 728 return (uint16_t)val; 729 } else { 730 if (val < 0) { 731 feraiseexcept(FeInvalid); 732 feclearexcept(FeInexact); 733 return 0; 734 } 735 if (val > mask(32)) { 736 feraiseexcept(FeInvalid); 737 feclearexcept(FeInexact); 738 return mask(32); 739 } 740 return (uint32_t)val; 741 } 742 } 743} 744 745double
| 659} 660 661uint64_t 662vfpFpDToFixed(double val, bool isSigned, bool half, 663 uint8_t imm, bool rzero) 664{ 665 int rmode = rzero ? FeRoundZero : fegetround(); 666 fesetround(FeRoundNearest); 667 val = val * pow(2.0, imm); 668 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 669 fesetround(rmode); 670 feclearexcept(FeAllExceptions); 671 __asm__ __volatile__("" : "=m" (val) : "m" (val)); 672 double origVal = val; 673 val = rint(val); 674 int fpType = std::fpclassify(val); 675 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) { 676 if (fpType == FP_NAN) { 677 feraiseexcept(FeInvalid); 678 } 679 val = 0.0; 680 } else if (origVal != val) { 681 switch (rmode) { 682 case FeRoundNearest: 683 if (origVal - val > 0.5) 684 val += 1.0; 685 else if (val - origVal > 0.5) 686 val -= 1.0; 687 break; 688 case FeRoundDown: 689 if (origVal < val) 690 val -= 1.0; 691 break; 692 case FeRoundUpward: 693 if (origVal > val) 694 val += 1.0; 695 break; 696 } 697 feraiseexcept(FeInexact); 698 } 699 if (isSigned) { 700 if (half) { 701 if (val < (int16_t)(1 << 15)) { 702 feraiseexcept(FeInvalid); 703 feclearexcept(FeInexact); 704 return (int16_t)(1 << 15); 705 } 706 if (val > (int16_t)mask(15)) { 707 feraiseexcept(FeInvalid); 708 feclearexcept(FeInexact); 709 return (int16_t)mask(15); 710 } 711 return (int16_t)val; 712 } else { 713 if (val < (int32_t)(1 << 31)) { 714 feraiseexcept(FeInvalid); 715 feclearexcept(FeInexact); 716 return (int32_t)(1 << 31); 717 } 718 if (val > (int32_t)mask(31)) { 719 feraiseexcept(FeInvalid); 720 feclearexcept(FeInexact); 721 return (int32_t)mask(31); 722 } 723 return (int32_t)val; 724 } 725 } else { 726 if (half) { 727 if (val < 0) { 728 feraiseexcept(FeInvalid); 729 feclearexcept(FeInexact); 730 return 0; 731 } 732 if (val > mask(16)) { 733 feraiseexcept(FeInvalid); 734 feclearexcept(FeInexact); 735 return mask(16); 736 } 737 return (uint16_t)val; 738 } else { 739 if (val < 0) { 740 feraiseexcept(FeInvalid); 741 feclearexcept(FeInexact); 742 return 0; 743 } 744 if (val > mask(32)) { 745 feraiseexcept(FeInvalid); 746 feclearexcept(FeInexact); 747 return mask(32); 748 } 749 return (uint32_t)val; 750 } 751 } 752} 753 754double
|
746vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm)
| 755vfpUFixedToFpD(bool flush, bool defaultNan, 756 uint32_t val, bool half, uint8_t imm)
|
747{ 748 fesetround(FeRoundNearest); 749 if (half) 750 val = (uint16_t)val; 751 double scale = pow(2.0, imm); 752 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 753 feclearexcept(FeAllExceptions); 754 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
| 757{ 758 fesetround(FeRoundNearest); 759 if (half) 760 val = (uint16_t)val; 761 double scale = pow(2.0, imm); 762 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 763 feclearexcept(FeAllExceptions); 764 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
|
755 return fixDivDest(fpscr, val / scale, (double)val, scale);
| 765 return fixDivDest(flush, defaultNan, val / scale, (double)val, scale);
|
756} 757 758double
| 766} 767 768double
|
759vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm)
| 769vfpSFixedToFpD(bool flush, bool defaultNan, 770 int32_t val, bool half, uint8_t imm)
|
760{ 761 fesetround(FeRoundNearest); 762 if (half) 763 val = sext<16>(val & mask(16)); 764 double scale = pow(2.0, imm); 765 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 766 feclearexcept(FeAllExceptions); 767 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
| 771{ 772 fesetround(FeRoundNearest); 773 if (half) 774 val = sext<16>(val & mask(16)); 775 double scale = pow(2.0, imm); 776 __asm__ __volatile__("" : "=m" (scale) : "m" (scale)); 777 feclearexcept(FeAllExceptions); 778 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
|
768 return fixDivDest(fpscr, val / scale, (double)val, scale);
| 779 return fixDivDest(flush, defaultNan, val / scale, (double)val, scale);
|
769} 770
| 780} 781
|
| 782// This function implements a magic formula taken from the architecture 783// reference manual. It was originally called recip_sqrt_estimate. 784static double 785recipSqrtEstimate(double a) 786{ 787 int64_t q0, q1, s; 788 double r; 789 if (a < 0.5) { 790 q0 = (int64_t)(a * 512.0); 791 r = 1.0 / sqrt(((double)q0 + 0.5) / 512.0); 792 } else { 793 q1 = (int64_t)(a * 256.0); 794 r = 1.0 / sqrt(((double)q1 + 0.5) / 256.0); 795 } 796 s = (int64_t)(256.0 * r + 0.5); 797 return (double)s / 256.0; 798} 799 800// This function is only intended for use in Neon instructions because 801// it ignores certain bits in the FPSCR. 802float 803fprSqrtEstimate(FPSCR &fpscr, float op) 804{ 805 const uint32_t qnan = 0x7fc00000; 806 float junk = 0.0; 807 int fpClass = std::fpclassify(op); 808 if (fpClass == FP_NAN) { 809 if ((fpToBits(op) & qnan) != qnan) 810 fpscr.ioc = 1; 811 return bitsToFp(qnan, junk); 812 } else if (fpClass == FP_ZERO) { 813 fpscr.dzc = 1; 814 // Return infinity with the same sign as the operand. 815 return bitsToFp((std::signbit(op) << 31) | 816 (0xFF << 23) | (0 << 0), junk); 817 } else if (std::signbit(op)) { 818 // Set invalid op bit. 819 fpscr.ioc = 1; 820 return bitsToFp(qnan, junk); 821 } else if (fpClass == FP_INFINITE) { 822 return 0.0; 823 } else { 824 uint64_t opBits = fpToBits(op); 825 double scaled; 826 if (bits(opBits, 23)) { 827 scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | 828 (ULL(0x3fd) << 52) | (bits(opBits, 31) << 63), 829 (double)0.0); 830 } else { 831 scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | 832 (ULL(0x3fe) << 52) | (bits(opBits, 31) << 63), 833 (double)0.0); 834 } 835 uint64_t resultExp = (380 - bits(opBits, 30, 23)) / 2; 836 837 uint64_t estimate = fpToBits(recipSqrtEstimate(scaled)); 838 839 return bitsToFp((bits(estimate, 63) << 31) | 840 (bits(resultExp, 7, 0) << 23) | 841 (bits(estimate, 51, 29) << 0), junk); 842 } 843} 844 845uint32_t 846unsignedRSqrtEstimate(uint32_t op) 847{ 848 if (bits(op, 31, 30) == 0) { 849 return -1; 850 } else { 851 double dpOp; 852 if (bits(op, 31)) { 853 dpOp = bitsToFp((ULL(0) << 63) | 854 (ULL(0x3fe) << 52) | 855 (bits((uint64_t)op, 30, 0) << 21) | 856 (0 << 0), (double)0.0); 857 } else { 858 dpOp = bitsToFp((ULL(0) << 63) | 859 (ULL(0x3fd) << 52) | 860 (bits((uint64_t)op, 29, 0) << 22) | 861 (0 << 0), (double)0.0); 862 } 863 uint64_t estimate = fpToBits(recipSqrtEstimate(dpOp)); 864 return (1 << 31) | bits(estimate, 51, 21); 865 } 866} 867 868// This function implements a magic formula taken from the architecture 869// reference manual. It was originally called recip_estimate. 870 871static double 872recipEstimate(double a) 873{ 874 int64_t q, s; 875 double r; 876 q = (int64_t)(a * 512.0); 877 r = 1.0 / (((double)q + 0.5) / 512.0); 878 s = (int64_t)(256.0 * r + 0.5); 879 return (double)s / 256.0; 880} 881 882// This function is only intended for use in Neon instructions because 883// it ignores certain bits in the FPSCR. 884float 885fpRecipEstimate(FPSCR &fpscr, float op) 886{ 887 const uint32_t qnan = 0x7fc00000; 888 float junk = 0.0; 889 int fpClass = std::fpclassify(op); 890 if (fpClass == FP_NAN) { 891 if ((fpToBits(op) & qnan) != qnan) 892 fpscr.ioc = 1; 893 return bitsToFp(qnan, junk); 894 } else if (fpClass == FP_INFINITE) { 895 return bitsToFp(std::signbit(op) << 31, junk); 896 } else if (fpClass == FP_ZERO) { 897 fpscr.dzc = 1; 898 // Return infinity with the same sign as the operand. 899 return bitsToFp((std::signbit(op) << 31) | 900 (0xFF << 23) | (0 << 0), junk); 901 } else if (fabs(op) >= pow(2.0, 126)) { 902 fpscr.ufc = 1; 903 return bitsToFp(std::signbit(op) << 31, junk); 904 } else { 905 uint64_t opBits = fpToBits(op); 906 double scaled; 907 scaled = bitsToFp((0 << 0) | (bits(opBits, 22, 0) << 29) | 908 (ULL(0x3fe) << 52) | (ULL(0) << 63), 909 (double)0.0); 910 uint64_t resultExp = 253 - bits(opBits, 30, 23); 911 912 uint64_t estimate = fpToBits(recipEstimate(scaled)); 913 914 return bitsToFp((bits(opBits, 31) << 31) | 915 (bits(resultExp, 7, 0) << 23) | 916 (bits(estimate, 51, 29) << 0), junk); 917 } 918} 919 920uint32_t 921unsignedRecipEstimate(uint32_t op) 922{ 923 if (bits(op, 31) == 0) { 924 return -1; 925 } else { 926 double dpOp; 927 dpOp = bitsToFp((ULL(0) << 63) | 928 (ULL(0x3fe) << 52) | 929 (bits((uint64_t)op, 30, 0) << 21) | 930 (0 << 0), (double)0.0); 931 uint64_t estimate = fpToBits(recipEstimate(dpOp)); 932 return (1 << 31) | bits(estimate, 51, 21); 933 } 934} 935
|
771template <class fpType> 772fpType
| 936template <class fpType> 937fpType
|
| 938FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, 939 fpType op1, fpType op2) const 940{ 941 done = true; 942 fpType junk = 0.0; 943 fpType dest = 0.0; 944 const bool single = (sizeof(fpType) == sizeof(float)); 945 const uint64_t qnan = 946 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 947 const bool nan1 = std::isnan(op1); 948 const bool nan2 = std::isnan(op2); 949 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 950 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan); 951 if (nan1 || nan2) { 952 if (defaultNan) { 953 dest = bitsToFp(qnan, junk); 954 } else if (signal1) { 955 dest = bitsToFp(fpToBits(op1) | qnan, junk); 956 } else if (signal2) { 957 dest = bitsToFp(fpToBits(op2) | qnan, junk); 958 } else if (nan1) { 959 dest = op1; 960 } else if (nan2) { 961 dest = op2; 962 } 963 if (signal1 || signal2) { 964 fpscr.ioc = 1; 965 } 966 } else { 967 done = false; 968 } 969 return dest; 970} 971 972template 973float FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, 974 float op1, float op2) const; 975template 976double FpOp::processNans(FPSCR &fpscr, bool &done, bool defaultNan, 977 double op1, double op2) const; 978 979template <class fpType> 980fpType
|
773FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 774 fpType (*func)(fpType, fpType),
| 981FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2, 982 fpType (*func)(fpType, fpType),
|
775 bool flush, uint32_t rMode) const
| 983 bool flush, bool defaultNan, uint32_t rMode) const
|
776{ 777 const bool single = (sizeof(fpType) == sizeof(float)); 778 fpType junk = 0.0; 779 780 if (flush && flushToZero(op1, op2)) 781 fpscr.idc = 1; 782 VfpSavedState state = prepFpState(rMode); 783 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) 784 : "m" (op1), "m" (op2), "m" (state)); 785 fpType dest = func(op1, op2); 786 __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 787 788 int fpClass = std::fpclassify(dest); 789 // Get NAN behavior right. This varies between x86 and ARM. 790 if (fpClass == FP_NAN) { 791 const bool single = (sizeof(fpType) == sizeof(float)); 792 const uint64_t qnan = 793 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 794 const bool nan1 = std::isnan(op1); 795 const bool nan2 = std::isnan(op2); 796 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 797 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
| 984{ 985 const bool single = (sizeof(fpType) == sizeof(float)); 986 fpType junk = 0.0; 987 988 if (flush && flushToZero(op1, op2)) 989 fpscr.idc = 1; 990 VfpSavedState state = prepFpState(rMode); 991 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2), "=m" (state) 992 : "m" (op1), "m" (op2), "m" (state)); 993 fpType dest = func(op1, op2); 994 __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 995 996 int fpClass = std::fpclassify(dest); 997 // Get NAN behavior right. This varies between x86 and ARM. 998 if (fpClass == FP_NAN) { 999 const bool single = (sizeof(fpType) == sizeof(float)); 1000 const uint64_t qnan = 1001 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 1002 const bool nan1 = std::isnan(op1); 1003 const bool nan2 = std::isnan(op2); 1004 const bool signal1 = nan1 && ((fpToBits(op1) & qnan) != qnan); 1005 const bool signal2 = nan2 && ((fpToBits(op2) & qnan) != qnan);
|
798 if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
| 1006 if ((!nan1 && !nan2) || (defaultNan == 1)) {
|
799 dest = bitsToFp(qnan, junk); 800 } else if (signal1) { 801 dest = bitsToFp(fpToBits(op1) | qnan, junk); 802 } else if (signal2) { 803 dest = bitsToFp(fpToBits(op2) | qnan, junk); 804 } else if (nan1) { 805 dest = op1; 806 } else if (nan2) { 807 dest = op2; 808 } 809 } else if (flush && flushToZero(dest)) { 810 feraiseexcept(FeUnderflow); 811 } else if (( 812 (single && (dest == bitsToFp(0x00800000, junk) || 813 dest == bitsToFp(0x80800000, junk))) || 814 (!single && 815 (dest == bitsToFp(ULL(0x0010000000000000), junk) || 816 dest == bitsToFp(ULL(0x8010000000000000), junk))) 817 ) && rMode != VfpRoundZero) { 818 /* 819 * Correct for the fact that underflow is detected -before- rounding 820 * in ARM and -after- rounding in x86. 821 */ 822 fesetround(FeRoundZero); 823 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 824 : "m" (op1), "m" (op2)); 825 fpType temp = func(op1, op2); 826 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 827 if (flush && flushToZero(temp)) { 828 dest = temp; 829 } 830 }
| 1007 dest = bitsToFp(qnan, junk); 1008 } else if (signal1) { 1009 dest = bitsToFp(fpToBits(op1) | qnan, junk); 1010 } else if (signal2) { 1011 dest = bitsToFp(fpToBits(op2) | qnan, junk); 1012 } else if (nan1) { 1013 dest = op1; 1014 } else if (nan2) { 1015 dest = op2; 1016 } 1017 } else if (flush && flushToZero(dest)) { 1018 feraiseexcept(FeUnderflow); 1019 } else if (( 1020 (single && (dest == bitsToFp(0x00800000, junk) || 1021 dest == bitsToFp(0x80800000, junk))) || 1022 (!single && 1023 (dest == bitsToFp(ULL(0x0010000000000000), junk) || 1024 dest == bitsToFp(ULL(0x8010000000000000), junk))) 1025 ) && rMode != VfpRoundZero) { 1026 /* 1027 * Correct for the fact that underflow is detected -before- rounding 1028 * in ARM and -after- rounding in x86. 1029 */ 1030 fesetround(FeRoundZero); 1031 __asm__ __volatile__ ("" : "=m" (op1), "=m" (op2) 1032 : "m" (op1), "m" (op2)); 1033 fpType temp = func(op1, op2); 1034 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 1035 if (flush && flushToZero(temp)) { 1036 dest = temp; 1037 } 1038 }
|
831 finishVfp(fpscr, state);
| 1039 finishVfp(fpscr, state, flush);
|
832 return dest; 833} 834 835template 836float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, 837 float (*func)(float, float),
| 1040 return dest; 1041} 1042 1043template 1044float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2, 1045 float (*func)(float, float),
|
838 bool flush, uint32_t rMode) const;
| 1046 bool flush, bool defaultNan, uint32_t rMode) const;
|
839template 840double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, 841 double (*func)(double, double),
| 1047template 1048double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2, 1049 double (*func)(double, double),
|
842 bool flush, uint32_t rMode) const;
| 1050 bool flush, bool defaultNan, uint32_t rMode) const;
|
843 844template <class fpType> 845fpType 846FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), 847 bool flush, uint32_t rMode) const 848{ 849 const bool single = (sizeof(fpType) == sizeof(float)); 850 fpType junk = 0.0; 851 852 if (flush && flushToZero(op1)) 853 fpscr.idc = 1; 854 VfpSavedState state = prepFpState(rMode); 855 __asm__ __volatile__ ("" : "=m" (op1), "=m" (state) 856 : "m" (op1), "m" (state)); 857 fpType dest = func(op1); 858 __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 859 860 int fpClass = std::fpclassify(dest); 861 // Get NAN behavior right. This varies between x86 and ARM. 862 if (fpClass == FP_NAN) { 863 const bool single = (sizeof(fpType) == sizeof(float)); 864 const uint64_t qnan = 865 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 866 const bool nan = std::isnan(op1); 867 if (!nan || fpscr.dn == 1) { 868 dest = bitsToFp(qnan, junk); 869 } else if (nan) { 870 dest = bitsToFp(fpToBits(op1) | qnan, junk); 871 } 872 } else if (flush && flushToZero(dest)) { 873 feraiseexcept(FeUnderflow); 874 } else if (( 875 (single && (dest == bitsToFp(0x00800000, junk) || 876 dest == bitsToFp(0x80800000, junk))) || 877 (!single && 878 (dest == bitsToFp(ULL(0x0010000000000000), junk) || 879 dest == bitsToFp(ULL(0x8010000000000000), junk))) 880 ) && rMode != VfpRoundZero) { 881 /* 882 * Correct for the fact that underflow is detected -before- rounding 883 * in ARM and -after- rounding in x86. 884 */ 885 fesetround(FeRoundZero); 886 __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); 887 fpType temp = func(op1); 888 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 889 if (flush && flushToZero(temp)) { 890 dest = temp; 891 } 892 }
| 1051 1052template <class fpType> 1053fpType 1054FpOp::unaryOp(FPSCR &fpscr, fpType op1, fpType (*func)(fpType), 1055 bool flush, uint32_t rMode) const 1056{ 1057 const bool single = (sizeof(fpType) == sizeof(float)); 1058 fpType junk = 0.0; 1059 1060 if (flush && flushToZero(op1)) 1061 fpscr.idc = 1; 1062 VfpSavedState state = prepFpState(rMode); 1063 __asm__ __volatile__ ("" : "=m" (op1), "=m" (state) 1064 : "m" (op1), "m" (state)); 1065 fpType dest = func(op1); 1066 __asm__ __volatile__ ("" : "=m" (dest) : "m" (dest)); 1067 1068 int fpClass = std::fpclassify(dest); 1069 // Get NAN behavior right. This varies between x86 and ARM. 1070 if (fpClass == FP_NAN) { 1071 const bool single = (sizeof(fpType) == sizeof(float)); 1072 const uint64_t qnan = 1073 single ? 0x7fc00000 : ULL(0x7ff8000000000000); 1074 const bool nan = std::isnan(op1); 1075 if (!nan || fpscr.dn == 1) { 1076 dest = bitsToFp(qnan, junk); 1077 } else if (nan) { 1078 dest = bitsToFp(fpToBits(op1) | qnan, junk); 1079 } 1080 } else if (flush && flushToZero(dest)) { 1081 feraiseexcept(FeUnderflow); 1082 } else if (( 1083 (single && (dest == bitsToFp(0x00800000, junk) || 1084 dest == bitsToFp(0x80800000, junk))) || 1085 (!single && 1086 (dest == bitsToFp(ULL(0x0010000000000000), junk) || 1087 dest == bitsToFp(ULL(0x8010000000000000), junk))) 1088 ) && rMode != VfpRoundZero) { 1089 /* 1090 * Correct for the fact that underflow is detected -before- rounding 1091 * in ARM and -after- rounding in x86. 1092 */ 1093 fesetround(FeRoundZero); 1094 __asm__ __volatile__ ("" : "=m" (op1) : "m" (op1)); 1095 fpType temp = func(op1); 1096 __asm__ __volatile__ ("" : "=m" (temp) : "m" (temp)); 1097 if (flush && flushToZero(temp)) { 1098 dest = temp; 1099 } 1100 }
|
893 finishVfp(fpscr, state);
| 1101 finishVfp(fpscr, state, flush);
|
894 return dest; 895} 896 897template 898float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float), 899 bool flush, uint32_t rMode) const; 900template 901double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double), 902 bool flush, uint32_t rMode) const; 903 904IntRegIndex 905VfpMacroOp::addStride(IntRegIndex idx, unsigned stride) 906{ 907 if (wide) { 908 stride *= 2; 909 } 910 unsigned offset = idx % 8; 911 idx = (IntRegIndex)(idx - offset); 912 offset += stride; 913 idx = (IntRegIndex)(idx + (offset % 8)); 914 return idx; 915} 916 917void 918VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) 919{ 920 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 921 assert(!inScalarBank(dest)); 922 dest = addStride(dest, stride); 923 op1 = addStride(op1, stride); 924 if (!inScalarBank(op2)) { 925 op2 = addStride(op2, stride); 926 } 927} 928 929void 930VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1) 931{ 932 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 933 assert(!inScalarBank(dest)); 934 dest = addStride(dest, stride); 935 if (!inScalarBank(op1)) { 936 op1 = addStride(op1, stride); 937 } 938} 939 940void 941VfpMacroOp::nextIdxs(IntRegIndex &dest) 942{ 943 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 944 assert(!inScalarBank(dest)); 945 dest = addStride(dest, stride); 946} 947 948}
| 1102 return dest; 1103} 1104 1105template 1106float FpOp::unaryOp(FPSCR &fpscr, float op1, float (*func)(float), 1107 bool flush, uint32_t rMode) const; 1108template 1109double FpOp::unaryOp(FPSCR &fpscr, double op1, double (*func)(double), 1110 bool flush, uint32_t rMode) const; 1111 1112IntRegIndex 1113VfpMacroOp::addStride(IntRegIndex idx, unsigned stride) 1114{ 1115 if (wide) { 1116 stride *= 2; 1117 } 1118 unsigned offset = idx % 8; 1119 idx = (IntRegIndex)(idx - offset); 1120 offset += stride; 1121 idx = (IntRegIndex)(idx + (offset % 8)); 1122 return idx; 1123} 1124 1125void 1126VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2) 1127{ 1128 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 1129 assert(!inScalarBank(dest)); 1130 dest = addStride(dest, stride); 1131 op1 = addStride(op1, stride); 1132 if (!inScalarBank(op2)) { 1133 op2 = addStride(op2, stride); 1134 } 1135} 1136 1137void 1138VfpMacroOp::nextIdxs(IntRegIndex &dest, IntRegIndex &op1) 1139{ 1140 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 1141 assert(!inScalarBank(dest)); 1142 dest = addStride(dest, stride); 1143 if (!inScalarBank(op1)) { 1144 op1 = addStride(op1, stride); 1145 } 1146} 1147 1148void 1149VfpMacroOp::nextIdxs(IntRegIndex &dest) 1150{ 1151 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2; 1152 assert(!inScalarBank(dest)); 1153 dest = addStride(dest, stride); 1154} 1155 1156}
|