Deleted Added
sdiff udiff text old ( 7430:db3e376f35d1 ) 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
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 "arch/arm/insts/misc.hh"
44#include "arch/arm/miscregs.hh"
45#include <fenv.h>
46#include <cmath>
47
48namespace ArmISA
49{
50
51enum VfpMicroMode {
52 VfpNotAMicroop,
53 VfpMicroop,
54 VfpFirstMicroop,
55 VfpLastMicroop
56};
57
58template<class T>
59static inline void
60setVfpMicroFlags(VfpMicroMode mode, T &flags)
61{
62 switch (mode) {
63 case VfpMicroop:
64 flags[StaticInst::IsMicroop] = true;
65 break;
66 case VfpFirstMicroop:
67 flags[StaticInst::IsMicroop] =
68 flags[StaticInst::IsFirstMicroop] = true;
69 break;
70 case VfpLastMicroop:
71 flags[StaticInst::IsMicroop] =
72 flags[StaticInst::IsLastMicroop] = true;
73 break;
74 case VfpNotAMicroop:
75 break;
76 }
77 if (mode == VfpMicroop || mode == VfpFirstMicroop) {
78 flags[StaticInst::IsDelayedCommit] = true;
79 }
80}
81
82enum FeExceptionBit
83{
84 FeDivByZero = FE_DIVBYZERO,
85 FeInexact = FE_INEXACT,
86 FeInvalid = FE_INVALID,
87 FeOverflow = FE_OVERFLOW,
88 FeUnderflow = FE_UNDERFLOW,
89 FeAllExceptions = FE_ALL_EXCEPT
90};
91
92enum FeRoundingMode
93{
94 FeRoundDown = FE_DOWNWARD,
95 FeRoundNearest = FE_TONEAREST,
96 FeRoundZero = FE_TOWARDZERO,
97 FeRoundUpward = FE_UPWARD
98};
99
100enum VfpRoundingMode
101{
102 VfpRoundNearest = 0,
103 VfpRoundUpward = 1,
104 VfpRoundDown = 2,
105 VfpRoundZero = 3
106};
107
108template <class fpType>
109static inline bool
110flushToZero(fpType &op)
111{
112 fpType junk = 0.0;
113 if (std::fpclassify(op) == FP_SUBNORMAL) {
114 uint64_t bitMask = ULL(0x1) << (sizeof(fpType) * 8 - 1);
115 op = bitsToFp(fpToBits(op) & bitMask, junk);
116 return true;
117 }
118 return false;
119}
120
121template <class fpType>
122static inline bool
123flushToZero(fpType &op1, fpType &op2)
124{
125 bool flush1 = flushToZero(op1);
126 bool flush2 = flushToZero(op2);
127 return flush1 || flush2;
128}
129
130template <class fpType>
131static inline void
132vfpFlushToZero(FPSCR &fpscr, fpType &op)
133{
134 if (fpscr.fz == 1 && flushToZero(op)) {
135 fpscr.idc = 1;
136 }
137}
138
139template <class fpType>
140static inline void
141vfpFlushToZero(FPSCR &fpscr, fpType &op1, fpType &op2)
142{
143 vfpFlushToZero(fpscr, op1);
144 vfpFlushToZero(fpscr, op2);
145}
146
147static inline uint32_t
148fpToBits(float fp)
149{
150 union
151 {
152 float fp;
153 uint32_t bits;
154 } val;
155 val.fp = fp;
156 return val.bits;
157}
158
159static inline uint64_t
160fpToBits(double fp)
161{
162 union
163 {
164 double fp;
165 uint64_t bits;
166 } val;
167 val.fp = fp;
168 return val.bits;
169}
170
171static inline float
172bitsToFp(uint64_t bits, float junk)
173{
174 union
175 {
176 float fp;
177 uint32_t bits;
178 } val;
179 val.bits = bits;
180 return val.fp;
181}
182
183static inline double
184bitsToFp(uint64_t bits, double junk)
185{
186 union
187 {
188 double fp;
189 uint64_t bits;
190 } val;
191 val.bits = bits;
192 return val.fp;
193}
194
195typedef int VfpSavedState;
196
197VfpSavedState prepFpState(uint32_t rMode);
198void finishVfp(FPSCR &fpscr, VfpSavedState state);
199
200template <class fpType>
201fpType fixDest(FPSCR fpscr, fpType val, fpType op1);
202
203template <class fpType>
204fpType fixDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
205
206template <class fpType>
207fpType fixDivDest(FPSCR fpscr, fpType val, fpType op1, fpType op2);
208
209float fixFpDFpSDest(FPSCR fpscr, double val);
210double fixFpSFpDDest(FPSCR fpscr, float val);
211
212float vcvtFpSFpH(FPSCR &fpscr, float op, float dest, bool top);
213float vcvtFpHFpS(FPSCR &fpscr, float op, bool top);
214
215static inline double
216makeDouble(uint32_t low, uint32_t high)
217{
218 double junk = 0.0;
219 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
220}
221
222static inline uint32_t
223lowFromDouble(double val)
224{
225 return fpToBits(val);
226}
227
228static inline uint32_t
229highFromDouble(double val)
230{
231 return fpToBits(val) >> 32;
232}
233
234uint64_t vfpFpSToFixed(float val, bool isSigned, bool half,
235 uint8_t imm, bool rzero = true);
236float vfpUFixedToFpS(FPSCR fpscr, uint32_t val, bool half, uint8_t imm);
237float vfpSFixedToFpS(FPSCR fpscr, int32_t val, bool half, uint8_t imm);
238
239uint64_t vfpFpDToFixed(double val, bool isSigned, bool half,
240 uint8_t imm, bool rzero = true);
241double vfpUFixedToFpD(FPSCR fpscr, uint32_t val, bool half, uint8_t imm);
242double vfpSFixedToFpD(FPSCR fpscr, int32_t val, bool half, uint8_t imm);
243
244class VfpMacroOp : public PredMacroOp
245{
246 public:
247 static bool
248 inScalarBank(IntRegIndex idx)
249 {
250 return (idx % 32) < 8;
251 }
252
253 protected:
254 bool wide;
255
256 VfpMacroOp(const char *mnem, ExtMachInst _machInst,
257 OpClass __opClass, bool _wide) :
258 PredMacroOp(mnem, _machInst, __opClass), wide(_wide)
259 {}
260
261 IntRegIndex addStride(IntRegIndex idx, unsigned stride);
262 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1, IntRegIndex &op2);
263 void nextIdxs(IntRegIndex &dest, IntRegIndex &op1);
264 void nextIdxs(IntRegIndex &dest);
265};
266
267static inline float
268fpAddS(float a, float b)
269{
270 return a + b;
271}
272
273static inline double
274fpAddD(double a, double b)
275{
276 return a + b;
277}
278
279static inline float
280fpSubS(float a, float b)
281{
282 return a - b;
283}
284
285static inline double
286fpSubD(double a, double b)
287{
288 return a - b;
289}
290
291static inline float
292fpDivS(float a, float b)
293{
294 return a / b;
295}
296
297static inline double
298fpDivD(double a, double b)
299{
300 return a / b;
301}
302
303static inline float
304fpMulS(float a, float b)
305{
306 return a * b;
307}
308
309static inline double
310fpMulD(double a, double b)
311{
312 return a * b;
313}
314
315class FpOp : public PredOp
316{
317 protected:
318 FpOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
319 PredOp(mnem, _machInst, __opClass)
320 {}
321
322 virtual float
323 doOp(float op1, float op2) const
324 {
325 panic("Unimplemented version of doOp called.\n");
326 }
327
328 virtual float
329 doOp(float op1) const
330 {
331 panic("Unimplemented version of doOp called.\n");
332 }
333
334 virtual double
335 doOp(double op1, double op2) const
336 {
337 panic("Unimplemented version of doOp called.\n");
338 }
339
340 virtual double
341 doOp(double op1) const
342 {
343 panic("Unimplemented version of doOp called.\n");
344 }
345
346 double
347 dbl(uint32_t low, uint32_t high) const
348 {
349 double junk = 0.0;
350 return bitsToFp((uint64_t)low | ((uint64_t)high << 32), junk);
351 }
352
353 uint32_t
354 dblLow(double val) const
355 {
356 return fpToBits(val);
357 }
358
359 uint32_t
360 dblHi(double val) const
361 {
362 return fpToBits(val) >> 32;
363 }
364
365 template <class fpType>
366 fpType
367 binaryOp(FPSCR &fpscr, fpType op1, fpType op2,
368 fpType (*func)(fpType, fpType),
369 bool flush, uint32_t rMode) const;
370
371 template <class fpType>
372 fpType
373 unaryOp(FPSCR &fpscr, fpType op1,
374 fpType (*func)(fpType),
375 bool flush, uint32_t rMode) const;
376};
377
378class FpRegRegOp : public FpOp
379{
380 protected:
381 IntRegIndex dest;
382 IntRegIndex op1;
383
384 FpRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
385 IntRegIndex _dest, IntRegIndex _op1,
386 VfpMicroMode mode = VfpNotAMicroop) :
387 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1)
388 {
389 setVfpMicroFlags(mode, flags);
390 }
391
392 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
393};
394
395class FpRegImmOp : public FpOp
396{
397 protected:
398 IntRegIndex dest;
399 uint64_t imm;
400
401 FpRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
402 IntRegIndex _dest, uint64_t _imm,
403 VfpMicroMode mode = VfpNotAMicroop) :
404 FpOp(mnem, _machInst, __opClass), dest(_dest), imm(_imm)
405 {
406 setVfpMicroFlags(mode, flags);
407 }
408
409 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
410};
411
412class FpRegRegImmOp : public FpOp
413{
414 protected:
415 IntRegIndex dest;
416 IntRegIndex op1;
417 uint64_t imm;
418
419 FpRegRegImmOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
420 IntRegIndex _dest, IntRegIndex _op1,
421 uint64_t _imm, VfpMicroMode mode = VfpNotAMicroop) :
422 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), imm(_imm)
423 {
424 setVfpMicroFlags(mode, flags);
425 }
426
427 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
428};
429
430class FpRegRegRegOp : public FpOp
431{
432 protected:
433 IntRegIndex dest;
434 IntRegIndex op1;
435 IntRegIndex op2;
436
437 FpRegRegRegOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
438 IntRegIndex _dest, IntRegIndex _op1, IntRegIndex _op2,
439 VfpMicroMode mode = VfpNotAMicroop) :
440 FpOp(mnem, _machInst, __opClass), dest(_dest), op1(_op1), op2(_op2)
441 {
442 setVfpMicroFlags(mode, flags);
443 }
444
445 std::string generateDisassembly(Addr pc, const SymbolTable *symtab) const;
446};
447
448}
449
450#endif //__ARCH_ARM_INSTS_VFP_HH__