Deleted Added
sdiff udiff text old ( 8737:770ccf3af571 ) new ( 8865:508635b3e666 )
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
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 uint32_t fpToBits(float);
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__