Deleted Added
sdiff udiff text old ( 7434:dd5a09b86b14 ) new ( 7639:8c09b7ff5b57 )
full compact
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
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
120finishVfp(FPSCR &fpscr, VfpSavedState state)
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 }
137 if ((exceptions & FeInexact) && !(underflow && fpscr.fz)) {
138 fpscr.ixc = 1;
139 }
140 fesetround(state);
141}
142
143template <class fpType>
144fpType
145fixDest(FPSCR fpscr, 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);
153 if (!nan || (fpscr.dn == 1)) {
154 val = bitsToFp(qnan, junk);
155 } else if (nan) {
156 val = bitsToFp(fpToBits(op1) | qnan, junk);
157 }
158 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 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
169float fixDest<float>(FPSCR fpscr, float val, float op1);
170template
171double fixDest<double>(FPSCR fpscr, double val, double op1);
172
173template <class fpType>
174fpType
175fixDest(FPSCR fpscr, 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);
186 if ((!nan1 && !nan2) || (fpscr.dn == 1)) {
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 }
197 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
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
208float fixDest<float>(FPSCR fpscr, float val, float op1, float op2);
209template
210double fixDest<double>(FPSCR fpscr, double val, double op1, double op2);
211
212template <class fpType>
213fpType
214fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
215{
216 fpType mid = fixDest(fpscr, 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);
231 if (fpscr.fz) {
232 feclearexcept(FeInexact);
233 mid = temp;
234 }
235 }
236 __asm__ __volatile__("" :: "m" (temp));
237 }
238 return mid;
239}
240
241template
242float fixDivDest<float>(FPSCR fpscr, float val, float op1, float op2);
243template
244double fixDivDest<double>(FPSCR fpscr, 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 }
258 float mid = fixDest(fpscr, (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 }
294 double mid = fixDest(fpscr, (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
314float
315vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top)
316{
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 }
334 if (fpscr.ahp) {
335 mantissa = 0;
336 exponent = 0;
337 fpscr.ioc = 1;
338 } else if (fpscr.dn) {
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;
349 if (fpscr.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 assert(fpscr.fz == 0);
368
369 // Check for underflow
370 if (inexact || fpscr.ufe)
371 fpscr.ufc = 1;
372
373 // Handle rounding.
374 unsigned mode = fpscr.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.
419 unsigned mode = fpscr.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
435 if (fpscr.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);
471 if (top)
472 replaceBits(destBits, 31, 16, result);
473 else
474 replaceBits(destBits, 15, 0, result);
475 return bitsToFp(destBits, junk);
476}
477
478float
479vcvtFpHFpS(FPSCR &fpscr, float op, bool top)
480{
481 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.
489 bool neg = bits(opBits, 15);
490 uint32_t exponent = bits(opBits, 14, 10);
491 uint32_t mantissa = bits(opBits, 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);
503 } else if (exponent == 0x1f && !fpscr.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 }
514 if (fpscr.dn) {
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
627vfpUFixedToFpS(FPSCR fpscr, 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 return fixDivDest(fpscr, val / scale, (float)val, scale);
637}
638
639float
640vfpSFixedToFpS(FPSCR fpscr, 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));
649 return fixDivDest(fpscr, 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
746vfpUFixedToFpD(FPSCR fpscr, 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));
755 return fixDivDest(fpscr, val / scale, (double)val, scale);
756}
757
758double
759vfpSFixedToFpD(FPSCR fpscr, 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));
768 return fixDivDest(fpscr, val / scale, (double)val, scale);
769}
770
771template <class fpType>
772fpType
773FpOp::binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
774 fpType (*func)(fpType, fpType),
775 bool flush, 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);
798 if ((!nan1 && !nan2) || (fpscr.dn == 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 }
831 finishVfp(fpscr, state);
832 return dest;
833}
834
835template
836float FpOp::binaryOp(FPSCR &fpscr, float op1, float op2,
837 float (*func)(float, float),
838 bool flush, uint32_t rMode) const;
839template
840double FpOp::binaryOp(FPSCR &fpscr, double op1, double op2,
841 double (*func)(double, double),
842 bool flush, 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 }
893 finishVfp(fpscr, state);
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 ---