Deleted Added
sdiff udiff text old ( 7388:293878a9d220 ) new ( 7396:53454ef35b46 )
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

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

105 VfpRoundZero = 3
106};
107
108template <class fpType>
109static inline void
110vfpFlushToZero(uint32_t &_fpscr, fpType &op)
111{
112 FPSCR fpscr = _fpscr;
113 if (fpscr.fz == 1 && (std::fpclassify(op) == FP_SUBNORMAL)) {
114 fpscr.idc = 1;
115 op = 0;
116 }
117 _fpscr = fpscr;
118}
119
120template <class fpType>
121static inline void
122vfpFlushToZero(uint32_t &fpscr, fpType &op1, fpType &op2)
123{
124 vfpFlushToZero(fpscr, op1);
125 vfpFlushToZero(fpscr, op2);
126}
127
128static inline uint32_t
129fpToBits(float fp)
130{
131 union
132 {
133 float fp;
134 uint32_t bits;
135 } val;

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

168 {
169 double fp;
170 uint64_t bits;
171 } val;
172 val.bits = bits;
173 return val.fp;
174}
175
176template <class fpType>
177static inline fpType
178fixDest(FPSCR fpscr, fpType val, fpType op1)
179{
180 int fpClass = std::fpclassify(val);
181 fpType junk = 0.0;
182 if (fpClass == FP_NAN) {
183 const bool single = (sizeof(val) == sizeof(float));
184 const uint64_t qnan = single ? 0x7fc00000 : ULL(0x7ff8000000000000);
185 const bool nan = std::isnan(op1);
186 if (!nan || (fpscr.dn == 1)) {
187 val = bitsToFp(qnan, junk);
188 } else if (nan) {
189 val = bitsToFp(fpToBits(op1) | qnan, junk);
190 }
191 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
192 // Turn val into a zero with the correct sign;
193 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
194 val = bitsToFp(fpToBits(val) & bitMask, junk);
195 feraiseexcept(FeUnderflow);
196 }
197 return val;
198}
199
200template <class fpType>
201static inline fpType
202fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)

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

220 val = op1;
221 } else if (nan2) {
222 val = op2;
223 }
224 } else if (fpClass == FP_SUBNORMAL && fpscr.fz == 1) {
225 // Turn val into a zero with the correct sign;
226 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
227 val = bitsToFp(fpToBits(val) & bitMask, junk);
228 feraiseexcept(FeUnderflow);
229 }
230 return val;
231}
232
233template <class fpType>
234static inline fpType
235fixMultDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
236{
237 fpType mid = fixDest(fpscr, val, op1, op2);
238 const bool single = (sizeof(fpType) == sizeof(float));
239 const fpType junk = 0.0;
240 if ((single && (val == bitsToFp(0x00800000, junk) ||
241 val == bitsToFp(0x80800000, junk))) ||
242 (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) ||
243 val == bitsToFp(ULL(0x8010000000000000), junk)))
244 ) {
245 __asm__ __volatile__("" : "=m" (op1) : "m" (op1));
246 fesetround(FeRoundZero);
247 fpType temp = 0.0;
248 __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
249 temp = op1 * op2;
250 if (!std::isnormal(temp)) {
251 feraiseexcept(FeUnderflow);
252 }
253 __asm__ __volatile__("" :: "m" (temp));
254 }
255 return mid;
256}
257
258template <class fpType>
259static inline fpType
260fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2)
261{
262 fpType mid = fixDest(fpscr, val, op1, op2);
263 const bool single = (sizeof(fpType) == sizeof(float));
264 const fpType junk = 0.0;
265 if ((single && (val == bitsToFp(0x00800000, junk) ||
266 val == bitsToFp(0x80800000, junk))) ||
267 (!single && (val == bitsToFp(ULL(0x0010000000000000), junk) ||
268 val == bitsToFp(ULL(0x8010000000000000), junk)))
269 ) {
270 __asm__ __volatile__("" : "=m" (op1) : "m" (op1));
271 fesetround(FeRoundZero);
272 fpType temp = 0.0;
273 __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
274 temp = op1 / op2;
275 if (!std::isnormal(temp)) {
276 feraiseexcept(FeUnderflow);
277 }
278 __asm__ __volatile__("" :: "m" (temp));
279 }
280 return mid;
281}
282
283static inline float
284fixFpDFpSDest(FPSCR fpscr, double val)
285{
286 const float junk = 0.0;
287 float op1 = 0.0;
288 if (std::isnan(val)) {
289 uint64_t valBits = fpToBits(val);
290 uint32_t op1Bits = bits(valBits, 50, 29) |
291 (mask(9) << 22) |
292 (bits(valBits, 63) << 31);
293 op1 = bitsToFp(op1Bits, junk);
294 }
295 float mid = fixDest(fpscr, (float)val, op1);
296 if (mid == bitsToFp(0x00800000, junk) ||
297 mid == bitsToFp(0x80800000, junk)) {
298 __asm__ __volatile__("" : "=m" (val) : "m" (val));
299 fesetround(FeRoundZero);
300 float temp = 0.0;
301 __asm__ __volatile__("" : "=m" (temp) : "m" (temp));
302 temp = val;
303 if (!std::isnormal(temp)) {
304 feraiseexcept(FeUnderflow);
305 }
306 __asm__ __volatile__("" :: "m" (temp));
307 }
308 return mid;
309}
310
311static inline uint64_t
312vfpFpSToFixed(float val, bool isSigned, bool half,
313 uint8_t imm, bool rzero = true)
314{
315 int rmode = fegetround();
316 fesetround(FeRoundNearest);
317 val = val * powf(2.0, imm);
318 __asm__ __volatile__("" : "=m" (val) : "m" (val));
319 if (rzero)
320 fesetround(FeRoundZero);
321 else
322 fesetround(rmode);
323 feclearexcept(FeAllExceptions);
324 __asm__ __volatile__("" : "=m" (val) : "m" (val));
325 float origVal = val;
326 val = rintf(val);
327 int fpType = std::fpclassify(val);
328 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
329 if (fpType == FP_NAN) {
330 feraiseexcept(FeInvalid);
331 }
332 val = 0.0;
333 } else if (origVal != val) {
334 feraiseexcept(FeInexact);
335 }
336
337 if (isSigned) {
338 if (half) {
339 if ((double)val < (int16_t)(1 << 15)) {
340 feraiseexcept(FeInvalid);
341 feclearexcept(FeInexact);

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

414 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
415 return fixDivDest(fpscr, val / scale, (float)val, scale);
416}
417
418static inline uint64_t
419vfpFpDToFixed(double val, bool isSigned, bool half,
420 uint8_t imm, bool rzero = true)
421{
422 int rmode = fegetround();
423 fesetround(FeRoundNearest);
424 val = val * pow(2.0, imm);
425 __asm__ __volatile__("" : "=m" (val) : "m" (val));
426 if (rzero)
427 fesetround(FeRoundZero);
428 else
429 fesetround(rmode);
430 feclearexcept(FeAllExceptions);
431 __asm__ __volatile__("" : "=m" (val) : "m" (val));
432 double origVal = val;
433 val = rint(val);
434 int fpType = std::fpclassify(val);
435 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
436 if (fpType == FP_NAN) {
437 feraiseexcept(FeInvalid);
438 }
439 val = 0.0;
440 } else if (origVal != val) {
441 feraiseexcept(FeInexact);
442 }
443 if (isSigned) {
444 if (half) {
445 if (val < (int16_t)(1 << 15)) {
446 feraiseexcept(FeInvalid);
447 feclearexcept(FeInexact);
448 return (int16_t)(1 << 15);

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

516 val = sext<16>(val & mask(16));
517 double scale = pow(2.0, imm);
518 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
519 feclearexcept(FeAllExceptions);
520 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
521 return fixDivDest(fpscr, val / scale, (double)val, scale);
522}
523
524typedef int VfpSavedState;
525
526static inline VfpSavedState
527prepVfpFpscr(FPSCR fpscr)
528{
529 int roundingMode = fegetround();
530 feclearexcept(FeAllExceptions);
531 switch (fpscr.rMode) {
532 case VfpRoundNearest:
533 fesetround(FeRoundNearest);
534 break;
535 case VfpRoundUpward:
536 fesetround(FeRoundUpward);
537 break;
538 case VfpRoundDown:
539 fesetround(FeRoundDown);
540 break;
541 case VfpRoundZero:
542 fesetround(FeRoundZero);
543 break;
544 }
545 return roundingMode;
546}
547
548static inline FPSCR
549setVfpFpscr(FPSCR fpscr, VfpSavedState state)
550{
551 int exceptions = fetestexcept(FeAllExceptions);
552 if (exceptions & FeInvalid) {
553 fpscr.ioc = 1;
554 }
555 if (exceptions & FeDivByZero) {
556 fpscr.dzc = 1;
557 }
558 if (exceptions & FeOverflow) {
559 fpscr.ofc = 1;
560 }
561 if (exceptions & FeUnderflow) {
562 fpscr.ufc = 1;
563 }
564 if (exceptions & FeInexact) {
565 fpscr.ixc = 1;
566 }
567 fesetround(state);
568 return fpscr;
569}
570
571class VfpMacroOp : public PredMacroOp
572{
573 public:
574 static bool
575 inScalarBank(IntRegIndex idx)
576 {
577 return (idx % 32) < 8;
578 }

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

625 nextIdxs(IntRegIndex &dest)
626 {
627 unsigned stride = (machInst.fpscrStride == 0) ? 1 : 2;
628 assert(!inScalarBank(dest));
629 dest = addStride(dest, stride);
630 }
631};
632
633class VfpRegRegOp : public RegRegOp
634{
635 protected:
636 VfpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
637 IntRegIndex _dest, IntRegIndex _op1,
638 VfpMicroMode mode = VfpNotAMicroop) :
639 RegRegOp(mnem, _machInst, __opClass, _dest, _op1)
640 {
641 setVfpMicroFlags(mode, flags);
642 }
643};
644
645class VfpRegImmOp : public RegImmOp
646{
647 protected:
648 VfpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
649 IntRegIndex _dest, uint64_t _imm,
650 VfpMicroMode mode = VfpNotAMicroop) :
651 RegImmOp(mnem, _machInst, __opClass, _dest, _imm)
652 {
653 setVfpMicroFlags(mode, flags);
654 }
655};
656
657class VfpRegRegImmOp : public RegRegImmOp
658{
659 protected:
660 VfpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
661 IntRegIndex _dest, IntRegIndex _op1,
662 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
663 RegRegImmOp(mnem, _machInst, __opClass, _dest, _op1, _imm)
664 {
665 setVfpMicroFlags(mode, flags);
666 }
667};
668
669class VfpRegRegRegOp : public RegRegRegOp
670{
671 protected:
672 VfpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
673 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
674 VfpMicroMode mode = VfpNotAMicroop) :
675 RegRegRegOp(mnem, _machInst, __opClass, _dest, _op1, _op2)
676 {
677 setVfpMicroFlags(mode, flags);
678 }
679};
680
681}
682
683#endif //__ARCH_ARM_INSTS_VFP_HH__