vfp.hh (8737:770ccf3af571) vfp.hh (8865:508635b3e666)
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#ifndef __ARCH_ARM_INSTS_VFP_HH__
41#define __ARCH_ARM_INSTS_VFP_HH__
42
43#include <fenv.h>
44
45#include <cmath>
46
47#include "arch/arm/insts/misc.hh"
48#include "arch/arm/miscregs.hh"
49
50namespace ArmISA
51{
52
53enum VfpMicroMode {
54 VfpNotAMicroop,
55 VfpMicroop,
56 VfpFirstMicroop,
57 VfpLastMicroop
58};
59
60template<class T>
61static inline void
62setVfpMicroFlags(VfpMicroMode mode, T &flags)
63{
64 switch (mode) {
65 case VfpMicroop:
66 flags[StaticInst::IsMicroop] = true;
67 break;
68 case VfpFirstMicroop:
69 flags[StaticInst::IsMicroop] =
70 flags[StaticInst::IsFirstMicroop] = true;
71 break;
72 case VfpLastMicroop:
73 flags[StaticInst::IsMicroop] =
74 flags[StaticInst::IsLastMicroop] = true;
75 break;
76 case VfpNotAMicroop:
77 break;
78 }
79 if (mode == VfpMicroop || mode == VfpFirstMicroop) {
80 flags[StaticInst::IsDelayedCommit] = true;
81 }
82}
83
84enum FeExceptionBit
85{
86 FeDivByZero = FE_DIVBYZERO,
87 FeInexact = FE_INEXACT,
88 FeInvalid = FE_INVALID,
89 FeOverflow = FE_OVERFLOW,
90 FeUnderflow = FE_UNDERFLOW,
91 FeAllExceptions = FE_ALL_EXCEPT
92};
93
94enum FeRoundingMode
95{
96 FeRoundDown = FE_DOWNWARD,
97 FeRoundNearest = FE_TONEAREST,
98 FeRoundZero = FE_TOWARDZERO,
99 FeRoundUpward = FE_UPWARD
100};
101
102enum VfpRoundingMode
103{
104 VfpRoundNearest = 0,
105 VfpRoundUpward = 1,
106 VfpRoundDown = 2,
107 VfpRoundZero = 3
108};
109
110static inline float bitsToFp(uint64_t, float);
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#ifndef __ARCH_ARM_INSTS_VFP_HH__
41#define __ARCH_ARM_INSTS_VFP_HH__
42
43#include <fenv.h>
44
45#include <cmath>
46
47#include "arch/arm/insts/misc.hh"
48#include "arch/arm/miscregs.hh"
49
50namespace ArmISA
51{
52
53enum VfpMicroMode {
54 VfpNotAMicroop,
55 VfpMicroop,
56 VfpFirstMicroop,
57 VfpLastMicroop
58};
59
60template<class T>
61static inline void
62setVfpMicroFlags(VfpMicroMode mode, T &flags)
63{
64 switch (mode) {
65 case VfpMicroop:
66 flags[StaticInst::IsMicroop] = true;
67 break;
68 case VfpFirstMicroop:
69 flags[StaticInst::IsMicroop] =
70 flags[StaticInst::IsFirstMicroop] = true;
71 break;
72 case VfpLastMicroop:
73 flags[StaticInst::IsMicroop] =
74 flags[StaticInst::IsLastMicroop] = true;
75 break;
76 case VfpNotAMicroop:
77 break;
78 }
79 if (mode == VfpMicroop || mode == VfpFirstMicroop) {
80 flags[StaticInst::IsDelayedCommit] = true;
81 }
82}
83
84enum FeExceptionBit
85{
86 FeDivByZero = FE_DIVBYZERO,
87 FeInexact = FE_INEXACT,
88 FeInvalid = FE_INVALID,
89 FeOverflow = FE_OVERFLOW,
90 FeUnderflow = FE_UNDERFLOW,
91 FeAllExceptions = FE_ALL_EXCEPT
92};
93
94enum FeRoundingMode
95{
96 FeRoundDown = FE_DOWNWARD,
97 FeRoundNearest = FE_TONEAREST,
98 FeRoundZero = FE_TOWARDZERO,
99 FeRoundUpward = FE_UPWARD
100};
101
102enum VfpRoundingMode
103{
104 VfpRoundNearest = 0,
105 VfpRoundUpward = 1,
106 VfpRoundDown = 2,
107 VfpRoundZero = 3
108};
109
110static inline float bitsToFp(uint64_t, float);
111static inline double bitsToFp(uint64_t, double);
111static inline uint32_t fpToBits(float);
112static inline uint32_t fpToBits(float);
113static inline uint64_t fpToBits(double);
112
113template <class fpType>
114static inline bool
115flushToZero(fpType &op)
116{
117 fpType junk = 0.0;
118 if (std::fpclassify(op) == FP_SUBNORMAL) {
119 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
120 op = bitsToFp(fpToBits(op) & bitMask, junk);
121 return true;
122 }
123 return false;
124}
125
126template <class fpType>
127static inline bool
128flushToZero(fpType &op1, fpType &op2)
129{
130 bool flush1 = flushToZero(op1);
131 bool flush2 = flushToZero(op2);
132 return flush1 || flush2;
133}
134
135template <class fpType>
136static inline void
137vfpFlushToZero(FPSCR &fpscr, fpType &op)
138{
139 if (fpscr.fz == 1 && flushToZero(op)) {
140 fpscr.idc = 1;
141 }
142}
143
144template <class fpType>
145static inline void
146vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2)
147{
148 vfpFlushToZero(fpscr, op1);
149 vfpFlushToZero(fpscr, op2);
150}
151
152static inline uint32_t
153fpToBits(float fp)
154{
155 union
156 {
157 float fp;
158 uint32_t bits;
159 } val;
160 val.fp = fp;
161 return val.bits;
162}
163
164static inline uint64_t
165fpToBits(double fp)
166{
167 union
168 {
169 double fp;
170 uint64_t bits;
171 } val;
172 val.fp = fp;
173 return val.bits;
174}
175
176static inline float
177bitsToFp(uint64_t bits, float junk)
178{
179 union
180 {
181 float fp;
182 uint32_t bits;
183 } val;
184 val.bits = bits;
185 return val.fp;
186}
187
188static inline double
189bitsToFp(uint64_t bits, double junk)
190{
191 union
192 {
193 double fp;
194 uint64_t bits;
195 } val;
196 val.bits = bits;
197 return val.fp;
198}
199
200template <class fpType>
201static bool
202isSnan(fpType val)
203{
204 const bool single = (sizeof(fpType) == sizeof(float));
205 const uint64_t qnan =
206 single ? 0x7fc00000 : ULL(0x7ff8000000000000);
207 return std::isnan(val) && ((fpToBits(val) & qnan) != qnan);
208}
209
210typedef int VfpSavedState;
211
212VfpSavedState prepFpState(uint32_t rMode);
213void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush);
214
215template <class fpType>
216fpType fixDest(FPSCR fpscr, fpType val, fpType op1);
217
218template <class fpType>
219fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
220
221template <class fpType>
222fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
223
224float fixFpDFpSDest(FPSCR fpscr, double val);
225double fixFpSFpDDest(FPSCR fpscr, float val);
226
227uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan,
228 uint32_t rMode, bool ahp, float op);
229float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op);
230
231static inline double
232makeDouble(uint32_t low, uint32_t high)
233{
234 double junk = 0.0;
235 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
236}
237
238static inline uint32_t
239lowFromDouble(double val)
240{
241 return fpToBits(val);
242}
243
244static inline uint32_t
245highFromDouble(double val)
246{
247 return fpToBits(val) >> 32;
248}
249
250uint64_t vfpFpSToFixed(float val, bool isSigned, bool half,
251 uint8_t imm, bool rzero = true);
252float vfpUFixedToFpS(bool flush, bool defaultNan,
253 uint32_t val, bool half, uint8_t imm);
254float vfpSFixedToFpS(bool flush, bool defaultNan,
255 int32_t val, bool half, uint8_t imm);
256
257uint64_t vfpFpDToFixed(double val, bool isSigned, bool half,
258 uint8_t imm, bool rzero = true);
259double vfpUFixedToFpD(bool flush, bool defaultNan,
260 uint32_t val, bool half, uint8_t imm);
261double vfpSFixedToFpD(bool flush, bool defaultNan,
262 int32_t val, bool half, uint8_t imm);
263
264float fprSqrtEstimate(FPSCR &fpscr, float op);
265uint32_t unsignedRSqrtEstimate(uint32_t op);
266
267float fpRecipEstimate(FPSCR &fpscr, float op);
268uint32_t unsignedRecipEstimate(uint32_t op);
269
270class VfpMacroOp : public PredMacroOp
271{
272 public:
273 static bool
274 inScalarBank(IntRegIndex idx)
275 {
276 return (idx % 32) < 8;
277 }
278
279 protected:
280 bool wide;
281
282 VfpMacroOp(const char *mnem, ExtMachInst _machInst,
283 OpClass __opClass, bool _wide) :
284 PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
285 {}
286
287 IntRegIndex addStride(IntRegIndex idx, unsigned stride);
288 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2);
289 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1);
290 void nextIdxs(IntRegIndex &dest);
291};
292
293static inline float
294fpAddS(float a, float b)
295{
296 return a + b;
297}
298
299static inline double
300fpAddD(double a, double b)
301{
302 return a + b;
303}
304
305static inline float
306fpSubS(float a, float b)
307{
308 return a - b;
309}
310
311static inline double
312fpSubD(double a, double b)
313{
314 return a - b;
315}
316
317static inline float
318fpDivS(float a, float b)
319{
320 return a / b;
321}
322
323static inline double
324fpDivD(double a, double b)
325{
326 return a / b;
327}
328
329static inline float
330fpMulS(float a, float b)
331{
332 return a * b;
333}
334
335static inline double
336fpMulD(double a, double b)
337{
338 return a * b;
339}
340
341static inline float
342fpMaxS(float a, float b)
343{
344 // Handle comparisons of +0 and -0.
345 if (!std::signbit(a) && std::signbit(b))
346 return a;
347 return fmaxf(a, b);
348}
349
350static inline float
351fpMinS(float a, float b)
352{
353 // Handle comparisons of +0 and -0.
354 if (std::signbit(a) && !std::signbit(b))
355 return a;
356 return fminf(a, b);
357}
358
359static inline float
360fpRSqrtsS(float a, float b)
361{
362 int fpClassA = std::fpclassify(a);
363 int fpClassB = std::fpclassify(b);
364 float aXb;
365 int fpClassAxB;
366
367 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
368 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
369 return 1.5;
370 }
371 aXb = a*b;
372 fpClassAxB = std::fpclassify(aXb);
373 if(fpClassAxB == FP_SUBNORMAL) {
374 feraiseexcept(FeUnderflow);
375 return 1.5;
376 }
377 return (3.0 - (a * b)) / 2.0;
378}
379
380static inline float
381fpRecpsS(float a, float b)
382{
383 int fpClassA = std::fpclassify(a);
384 int fpClassB = std::fpclassify(b);
385 float aXb;
386 int fpClassAxB;
387
388 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
389 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
390 return 2.0;
391 }
392 aXb = a*b;
393 fpClassAxB = std::fpclassify(aXb);
394 if(fpClassAxB == FP_SUBNORMAL) {
395 feraiseexcept(FeUnderflow);
396 return 2.0;
397 }
398 return 2.0 - (a * b);
399}
400
401class FpOp : public PredOp
402{
403 protected:
404 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
405 PredOp(mnem, _machInst, __opClass)
406 {}
407
408 virtual float
409 doOp(float op1, float op2) const
410 {
411 panic("Unimplemented version of doOp called.\n");
412 }
413
414 virtual float
415 doOp(float op1) const
416 {
417 panic("Unimplemented version of doOp called.\n");
418 }
419
420 virtual double
421 doOp(double op1, double op2) const
422 {
423 panic("Unimplemented version of doOp called.\n");
424 }
425
426 virtual double
427 doOp(double op1) const
428 {
429 panic("Unimplemented version of doOp called.\n");
430 }
431
432 double
433 dbl(uint32_t low, uint32_t high) const
434 {
435 double junk = 0.0;
436 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
437 }
438
439 uint32_t
440 dblLow(double val) const
441 {
442 return fpToBits(val);
443 }
444
445 uint32_t
446 dblHi(double val) const
447 {
448 return fpToBits(val) >> 32;
449 }
450
451 template <class fpType>
452 fpType
453 processNans(FPSCR &fpscr, bool &done, bool defaultNan,
454 fpType op1, fpType op2) const;
455
456 template <class fpType>
457 fpType
458 binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
459 fpType (*func)(fpType, fpType),
460 bool flush, bool defaultNan, uint32_t rMode) const;
461
462 template <class fpType>
463 fpType
464 unaryOp(FPSCR &fpscr, fpType op1,
465 fpType (*func)(fpType),
466 bool flush, uint32_t rMode) const;
467
468 void
469 advancePC(PCState &pcState) const
470 {
471 if (flags[IsLastMicroop]) {
472 pcState.uEnd();
473 } else if (flags[IsMicroop]) {
474 pcState.uAdvance();
475 } else {
476 pcState.advance();
477 }
478 }
479};
480
481class FpRegRegOp : public FpOp
482{
483 protected:
484 IntRegIndex dest;
485 IntRegIndex op1;
486
487 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
488 IntRegIndex _dest, IntRegIndex _op1,
489 VfpMicroMode mode = VfpNotAMicroop) :
490 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
491 {
492 setVfpMicroFlags(mode, flags);
493 }
494
495 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
496};
497
498class FpRegImmOp : public FpOp
499{
500 protected:
501 IntRegIndex dest;
502 uint64_t imm;
503
504 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
505 IntRegIndex _dest, uint64_t _imm,
506 VfpMicroMode mode = VfpNotAMicroop) :
507 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
508 {
509 setVfpMicroFlags(mode, flags);
510 }
511
512 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
513};
514
515class FpRegRegImmOp : public FpOp
516{
517 protected:
518 IntRegIndex dest;
519 IntRegIndex op1;
520 uint64_t imm;
521
522 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
523 IntRegIndex _dest, IntRegIndex _op1,
524 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
525 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
526 {
527 setVfpMicroFlags(mode, flags);
528 }
529
530 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
531};
532
533class FpRegRegRegOp : public FpOp
534{
535 protected:
536 IntRegIndex dest;
537 IntRegIndex op1;
538 IntRegIndex op2;
539
540 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
541 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
542 VfpMicroMode mode = VfpNotAMicroop) :
543 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
544 {
545 setVfpMicroFlags(mode, flags);
546 }
547
548 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
549};
550
551class FpRegRegRegImmOp : public FpOp
552{
553 protected:
554 IntRegIndex dest;
555 IntRegIndex op1;
556 IntRegIndex op2;
557 uint64_t imm;
558
559 FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst,
560 OpClass __opClass, IntRegIndex _dest,
561 IntRegIndex _op1, IntRegIndex _op2,
562 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
563 FpOp(mnem, _machInst, __opClass),
564 dest(_dest), op1(_op1), op2(_op2), imm(_imm)
565 {
566 setVfpMicroFlags(mode, flags);
567 }
568
569 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
570};
571
572}
573
574#endif //__ARCH_ARM_INSTS_VFP_HH__
114
115template <class fpType>
116static inline bool
117flushToZero(fpType &op)
118{
119 fpType junk = 0.0;
120 if (std::fpclassify(op) == FP_SUBNORMAL) {
121 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
122 op = bitsToFp(fpToBits(op) & bitMask, junk);
123 return true;
124 }
125 return false;
126}
127
128template <class fpType>
129static inline bool
130flushToZero(fpType &op1, fpType &op2)
131{
132 bool flush1 = flushToZero(op1);
133 bool flush2 = flushToZero(op2);
134 return flush1 || flush2;
135}
136
137template <class fpType>
138static inline void
139vfpFlushToZero(FPSCR &fpscr, fpType &op)
140{
141 if (fpscr.fz == 1 && flushToZero(op)) {
142 fpscr.idc = 1;
143 }
144}
145
146template <class fpType>
147static inline void
148vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2)
149{
150 vfpFlushToZero(fpscr, op1);
151 vfpFlushToZero(fpscr, op2);
152}
153
154static inline uint32_t
155fpToBits(float fp)
156{
157 union
158 {
159 float fp;
160 uint32_t bits;
161 } val;
162 val.fp = fp;
163 return val.bits;
164}
165
166static inline uint64_t
167fpToBits(double fp)
168{
169 union
170 {
171 double fp;
172 uint64_t bits;
173 } val;
174 val.fp = fp;
175 return val.bits;
176}
177
178static inline float
179bitsToFp(uint64_t bits, float junk)
180{
181 union
182 {
183 float fp;
184 uint32_t bits;
185 } val;
186 val.bits = bits;
187 return val.fp;
188}
189
190static inline double
191bitsToFp(uint64_t bits, double junk)
192{
193 union
194 {
195 double fp;
196 uint64_t bits;
197 } val;
198 val.bits = bits;
199 return val.fp;
200}
201
202template <class fpType>
203static bool
204isSnan(fpType val)
205{
206 const bool single = (sizeof(fpType) == sizeof(float));
207 const uint64_t qnan =
208 single ? 0x7fc00000 : ULL(0x7ff8000000000000);
209 return std::isnan(val) && ((fpToBits(val) & qnan) != qnan);
210}
211
212typedef int VfpSavedState;
213
214VfpSavedState prepFpState(uint32_t rMode);
215void finishVfp(FPSCR &fpscr, VfpSavedState state, bool flush);
216
217template <class fpType>
218fpType fixDest(FPSCR fpscr, fpType val, fpType op1);
219
220template <class fpType>
221fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
222
223template <class fpType>
224fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
225
226float fixFpDFpSDest(FPSCR fpscr, double val);
227double fixFpSFpDDest(FPSCR fpscr, float val);
228
229uint16_t vcvtFpSFpH(FPSCR &fpscr, bool flush, bool defaultNan,
230 uint32_t rMode, bool ahp, float op);
231float vcvtFpHFpS(FPSCR &fpscr, bool defaultNan, bool ahp, uint16_t op);
232
233static inline double
234makeDouble(uint32_t low, uint32_t high)
235{
236 double junk = 0.0;
237 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
238}
239
240static inline uint32_t
241lowFromDouble(double val)
242{
243 return fpToBits(val);
244}
245
246static inline uint32_t
247highFromDouble(double val)
248{
249 return fpToBits(val) >> 32;
250}
251
252uint64_t vfpFpSToFixed(float val, bool isSigned, bool half,
253 uint8_t imm, bool rzero = true);
254float vfpUFixedToFpS(bool flush, bool defaultNan,
255 uint32_t val, bool half, uint8_t imm);
256float vfpSFixedToFpS(bool flush, bool defaultNan,
257 int32_t val, bool half, uint8_t imm);
258
259uint64_t vfpFpDToFixed(double val, bool isSigned, bool half,
260 uint8_t imm, bool rzero = true);
261double vfpUFixedToFpD(bool flush, bool defaultNan,
262 uint32_t val, bool half, uint8_t imm);
263double vfpSFixedToFpD(bool flush, bool defaultNan,
264 int32_t val, bool half, uint8_t imm);
265
266float fprSqrtEstimate(FPSCR &fpscr, float op);
267uint32_t unsignedRSqrtEstimate(uint32_t op);
268
269float fpRecipEstimate(FPSCR &fpscr, float op);
270uint32_t unsignedRecipEstimate(uint32_t op);
271
272class VfpMacroOp : public PredMacroOp
273{
274 public:
275 static bool
276 inScalarBank(IntRegIndex idx)
277 {
278 return (idx % 32) < 8;
279 }
280
281 protected:
282 bool wide;
283
284 VfpMacroOp(const char *mnem, ExtMachInst _machInst,
285 OpClass __opClass, bool _wide) :
286 PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
287 {}
288
289 IntRegIndex addStride(IntRegIndex idx, unsigned stride);
290 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2);
291 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1);
292 void nextIdxs(IntRegIndex &dest);
293};
294
295static inline float
296fpAddS(float a, float b)
297{
298 return a + b;
299}
300
301static inline double
302fpAddD(double a, double b)
303{
304 return a + b;
305}
306
307static inline float
308fpSubS(float a, float b)
309{
310 return a - b;
311}
312
313static inline double
314fpSubD(double a, double b)
315{
316 return a - b;
317}
318
319static inline float
320fpDivS(float a, float b)
321{
322 return a / b;
323}
324
325static inline double
326fpDivD(double a, double b)
327{
328 return a / b;
329}
330
331static inline float
332fpMulS(float a, float b)
333{
334 return a * b;
335}
336
337static inline double
338fpMulD(double a, double b)
339{
340 return a * b;
341}
342
343static inline float
344fpMaxS(float a, float b)
345{
346 // Handle comparisons of +0 and -0.
347 if (!std::signbit(a) && std::signbit(b))
348 return a;
349 return fmaxf(a, b);
350}
351
352static inline float
353fpMinS(float a, float b)
354{
355 // Handle comparisons of +0 and -0.
356 if (std::signbit(a) && !std::signbit(b))
357 return a;
358 return fminf(a, b);
359}
360
361static inline float
362fpRSqrtsS(float a, float b)
363{
364 int fpClassA = std::fpclassify(a);
365 int fpClassB = std::fpclassify(b);
366 float aXb;
367 int fpClassAxB;
368
369 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
370 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
371 return 1.5;
372 }
373 aXb = a*b;
374 fpClassAxB = std::fpclassify(aXb);
375 if(fpClassAxB == FP_SUBNORMAL) {
376 feraiseexcept(FeUnderflow);
377 return 1.5;
378 }
379 return (3.0 - (a * b)) / 2.0;
380}
381
382static inline float
383fpRecpsS(float a, float b)
384{
385 int fpClassA = std::fpclassify(a);
386 int fpClassB = std::fpclassify(b);
387 float aXb;
388 int fpClassAxB;
389
390 if ((fpClassA == FP_ZERO && fpClassB == FP_INFINITE) ||
391 (fpClassA == FP_INFINITE && fpClassB == FP_ZERO)) {
392 return 2.0;
393 }
394 aXb = a*b;
395 fpClassAxB = std::fpclassify(aXb);
396 if(fpClassAxB == FP_SUBNORMAL) {
397 feraiseexcept(FeUnderflow);
398 return 2.0;
399 }
400 return 2.0 - (a * b);
401}
402
403class FpOp : public PredOp
404{
405 protected:
406 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
407 PredOp(mnem, _machInst, __opClass)
408 {}
409
410 virtual float
411 doOp(float op1, float op2) const
412 {
413 panic("Unimplemented version of doOp called.\n");
414 }
415
416 virtual float
417 doOp(float op1) const
418 {
419 panic("Unimplemented version of doOp called.\n");
420 }
421
422 virtual double
423 doOp(double op1, double op2) const
424 {
425 panic("Unimplemented version of doOp called.\n");
426 }
427
428 virtual double
429 doOp(double op1) const
430 {
431 panic("Unimplemented version of doOp called.\n");
432 }
433
434 double
435 dbl(uint32_t low, uint32_t high) const
436 {
437 double junk = 0.0;
438 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
439 }
440
441 uint32_t
442 dblLow(double val) const
443 {
444 return fpToBits(val);
445 }
446
447 uint32_t
448 dblHi(double val) const
449 {
450 return fpToBits(val) >> 32;
451 }
452
453 template <class fpType>
454 fpType
455 processNans(FPSCR &fpscr, bool &done, bool defaultNan,
456 fpType op1, fpType op2) const;
457
458 template <class fpType>
459 fpType
460 binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
461 fpType (*func)(fpType, fpType),
462 bool flush, bool defaultNan, uint32_t rMode) const;
463
464 template <class fpType>
465 fpType
466 unaryOp(FPSCR &fpscr, fpType op1,
467 fpType (*func)(fpType),
468 bool flush, uint32_t rMode) const;
469
470 void
471 advancePC(PCState &pcState) const
472 {
473 if (flags[IsLastMicroop]) {
474 pcState.uEnd();
475 } else if (flags[IsMicroop]) {
476 pcState.uAdvance();
477 } else {
478 pcState.advance();
479 }
480 }
481};
482
483class FpRegRegOp : public FpOp
484{
485 protected:
486 IntRegIndex dest;
487 IntRegIndex op1;
488
489 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
490 IntRegIndex _dest, IntRegIndex _op1,
491 VfpMicroMode mode = VfpNotAMicroop) :
492 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
493 {
494 setVfpMicroFlags(mode, flags);
495 }
496
497 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
498};
499
500class FpRegImmOp : public FpOp
501{
502 protected:
503 IntRegIndex dest;
504 uint64_t imm;
505
506 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
507 IntRegIndex _dest, uint64_t _imm,
508 VfpMicroMode mode = VfpNotAMicroop) :
509 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
510 {
511 setVfpMicroFlags(mode, flags);
512 }
513
514 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
515};
516
517class FpRegRegImmOp : public FpOp
518{
519 protected:
520 IntRegIndex dest;
521 IntRegIndex op1;
522 uint64_t imm;
523
524 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
525 IntRegIndex _dest, IntRegIndex _op1,
526 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
527 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
528 {
529 setVfpMicroFlags(mode, flags);
530 }
531
532 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
533};
534
535class FpRegRegRegOp : public FpOp
536{
537 protected:
538 IntRegIndex dest;
539 IntRegIndex op1;
540 IntRegIndex op2;
541
542 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
543 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
544 VfpMicroMode mode = VfpNotAMicroop) :
545 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
546 {
547 setVfpMicroFlags(mode, flags);
548 }
549
550 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
551};
552
553class FpRegRegRegImmOp : public FpOp
554{
555 protected:
556 IntRegIndex dest;
557 IntRegIndex op1;
558 IntRegIndex op2;
559 uint64_t imm;
560
561 FpRegRegRegImmOp(const char *mnem, ExtMachInst _machInst,
562 OpClass __opClass, IntRegIndex _dest,
563 IntRegIndex _op1, IntRegIndex _op2,
564 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
565 FpOp(mnem, _machInst, __opClass),
566 dest(_dest), op1(_op1), op2(_op2), imm(_imm)
567 {
568 setVfpMicroFlags(mode, flags);
569 }
570
571 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
572};
573
574}
575
576#endif //__ARCH_ARM_INSTS_VFP_HH__