vfp.cc (7434:dd5a09b86b14) vfp.cc (7639:8c09b7ff5b57)
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

--- 77 unchanged lines hidden (view full) ---

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

--- 77 unchanged lines hidden (view full) ---

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);

--- 10 unchanged lines hidden (view full) ---

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);

--- 10 unchanged lines hidden (view full) ---

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);

--- 19 unchanged lines hidden (view full) ---

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);

--- 19 unchanged lines hidden (view full) ---

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

--- 28 unchanged lines hidden (view full) ---

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

--- 28 unchanged lines hidden (view full) ---

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 {

--- 19 unchanged lines hidden (view full) ---

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 {

--- 19 unchanged lines hidden (view full) ---

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 }

--- 96 unchanged lines hidden (view full) ---

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 }

--- 96 unchanged lines hidden (view full) ---

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);

--- 80 unchanged lines hidden (view full) ---

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);

--- 80 unchanged lines hidden (view full) ---

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)

--- 6 unchanged lines hidden (view full) ---

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)

--- 6 unchanged lines hidden (view full) ---

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) {

--- 16 unchanged lines hidden (view full) ---

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) {

--- 16 unchanged lines hidden (view full) ---

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;

--- 34 unchanged lines hidden (view full) ---

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;

--- 34 unchanged lines hidden (view full) ---

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),

--- 47 unchanged lines hidden ---
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),

--- 47 unchanged lines hidden ---