vfp.hh (7381:bc68c91e9814) vfp.hh (7382:b3c768629a54)
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

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

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>
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

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

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>
46
47enum VfpMicroMode {
48 VfpNotAMicroop,
49 VfpMicroop,
50 VfpFirstMicroop,
51 VfpLastMicroop
52};
53

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

96enum VfpRoundingMode
97{
98 VfpRoundNearest = 0,
99 VfpRoundUpward = 1,
100 VfpRoundDown = 2,
101 VfpRoundZero = 3
102};
103
47
48enum VfpMicroMode {
49 VfpNotAMicroop,
50 VfpMicroop,
51 VfpFirstMicroop,
52 VfpLastMicroop
53};
54

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

97enum VfpRoundingMode
98{
99 VfpRoundNearest = 0,
100 VfpRoundUpward = 1,
101 VfpRoundDown = 2,
102 VfpRoundZero = 3
103};
104
105template <class fpType>
106static inline void
107vfpFlushToZero(uint32_t &_fpscr, fpType &op)
108{
109 FPSCR fpscr = _fpscr;
110 if (fpscr.fz == 1 && (std::fpclassify(op) == FP_SUBNORMAL)) {
111 fpscr.idc = 1;
112 op = 0;
113 }
114 _fpscr = fpscr;
115}
116
117template <class fpType>
118static inline void
119vfpFlushToZero(uint32_t &fpscr, fpType &op1, fpType &op2)
120{
121 vfpFlushToZero(fpscr, op1);
122 vfpFlushToZero(fpscr, op2);
123}
124
104static inline uint64_t
105vfpFpSToFixed(float val, bool isSigned, bool half, uint8_t imm)
106{
107 fesetround(FeRoundZero);
108 val = val * powf(2.0, imm);
109 __asm__ __volatile__("" : "=m" (val) : "m" (val));
110 feclearexcept(FeAllExceptions);
125static inline uint64_t
126vfpFpSToFixed(float val, bool isSigned, bool half, uint8_t imm)
127{
128 fesetround(FeRoundZero);
129 val = val * powf(2.0, imm);
130 __asm__ __volatile__("" : "=m" (val) : "m" (val));
131 feclearexcept(FeAllExceptions);
132 __asm__ __volatile__("" : "=m" (val) : "m" (val));
133 float origVal = val;
134 val = rintf(val);
135 int fpType = std::fpclassify(val);
136 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
137 if (fpType == FP_NAN) {
138 feraiseexcept(FeInvalid);
139 }
140 val = 0.0;
141 } else if (origVal != val) {
142 feraiseexcept(FeInexact);
143 }
144
111 if (isSigned) {
112 if (half) {
113 if ((double)val < (int16_t)(1 << 15)) {
114 feraiseexcept(FeInvalid);
145 if (isSigned) {
146 if (half) {
147 if ((double)val < (int16_t)(1 << 15)) {
148 feraiseexcept(FeInvalid);
149 feclearexcept(FeInexact);
115 return (int16_t)(1 << 15);
116 }
117 if ((double)val > (int16_t)mask(15)) {
118 feraiseexcept(FeInvalid);
150 return (int16_t)(1 << 15);
151 }
152 if ((double)val > (int16_t)mask(15)) {
153 feraiseexcept(FeInvalid);
154 feclearexcept(FeInexact);
119 return (int16_t)mask(15);
120 }
121 return (int16_t)val;
122 } else {
123 if ((double)val < (int32_t)(1 << 31)) {
124 feraiseexcept(FeInvalid);
155 return (int16_t)mask(15);
156 }
157 return (int16_t)val;
158 } else {
159 if ((double)val < (int32_t)(1 << 31)) {
160 feraiseexcept(FeInvalid);
161 feclearexcept(FeInexact);
125 return (int32_t)(1 << 31);
126 }
127 if ((double)val > (int32_t)mask(31)) {
128 feraiseexcept(FeInvalid);
162 return (int32_t)(1 << 31);
163 }
164 if ((double)val > (int32_t)mask(31)) {
165 feraiseexcept(FeInvalid);
166 feclearexcept(FeInexact);
129 return (int32_t)mask(31);
130 }
131 return (int32_t)val;
132 }
133 } else {
134 if (half) {
135 if ((double)val < 0) {
136 feraiseexcept(FeInvalid);
167 return (int32_t)mask(31);
168 }
169 return (int32_t)val;
170 }
171 } else {
172 if (half) {
173 if ((double)val < 0) {
174 feraiseexcept(FeInvalid);
175 feclearexcept(FeInexact);
137 return 0;
138 }
139 if ((double)val > (mask(16))) {
140 feraiseexcept(FeInvalid);
176 return 0;
177 }
178 if ((double)val > (mask(16))) {
179 feraiseexcept(FeInvalid);
180 feclearexcept(FeInexact);
141 return mask(16);
142 }
143 return (uint16_t)val;
144 } else {
145 if ((double)val < 0) {
146 feraiseexcept(FeInvalid);
181 return mask(16);
182 }
183 return (uint16_t)val;
184 } else {
185 if ((double)val < 0) {
186 feraiseexcept(FeInvalid);
187 feclearexcept(FeInexact);
147 return 0;
148 }
149 if ((double)val > (mask(32))) {
150 feraiseexcept(FeInvalid);
188 return 0;
189 }
190 if ((double)val > (mask(32))) {
191 feraiseexcept(FeInvalid);
192 feclearexcept(FeInexact);
151 return mask(32);
152 }
153 return (uint32_t)val;
154 }
155 }
156}
157
158static inline float
159vfpUFixedToFpS(uint32_t val, bool half, uint8_t imm)
160{
161 fesetround(FeRoundNearest);
162 if (half)
163 val = (uint16_t)val;
193 return mask(32);
194 }
195 return (uint32_t)val;
196 }
197 }
198}
199
200static inline float
201vfpUFixedToFpS(uint32_t val, bool half, uint8_t imm)
202{
203 fesetround(FeRoundNearest);
204 if (half)
205 val = (uint16_t)val;
164 return val / powf(2.0, imm);
206 float scale = powf(2.0, imm);
207 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
208 feclearexcept(FeAllExceptions);
209 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
210 return val / scale;
165}
166
167static inline float
168vfpSFixedToFpS(int32_t val, bool half, uint8_t imm)
169{
170 fesetround(FeRoundNearest);
171 if (half)
172 val = sext<16>(val & mask(16));
211}
212
213static inline float
214vfpSFixedToFpS(int32_t val, bool half, uint8_t imm)
215{
216 fesetround(FeRoundNearest);
217 if (half)
218 val = sext<16>(val & mask(16));
173 return val / powf(2.0, imm);
219 float scale = powf(2.0, imm);
220 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
221 feclearexcept(FeAllExceptions);
222 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
223 return val / scale;
174}
175
176static inline uint64_t
177vfpFpDToFixed(double val, bool isSigned, bool half, uint8_t imm)
178{
224}
225
226static inline uint64_t
227vfpFpDToFixed(double val, bool isSigned, bool half, uint8_t imm)
228{
179 fesetround(FeRoundZero);
229 fesetround(FeRoundNearest);
180 val = val * pow(2.0, imm);
181 __asm__ __volatile__("" : "=m" (val) : "m" (val));
230 val = val * pow(2.0, imm);
231 __asm__ __volatile__("" : "=m" (val) : "m" (val));
232 fesetround(FeRoundZero);
182 feclearexcept(FeAllExceptions);
233 feclearexcept(FeAllExceptions);
234 __asm__ __volatile__("" : "=m" (val) : "m" (val));
235 double origVal = val;
236 val = rint(val);
237 int fpType = std::fpclassify(val);
238 if (fpType == FP_SUBNORMAL || fpType == FP_NAN) {
239 if (fpType == FP_NAN) {
240 feraiseexcept(FeInvalid);
241 }
242 val = 0.0;
243 } else if (origVal != val) {
244 feraiseexcept(FeInexact);
245 }
183 if (isSigned) {
184 if (half) {
185 if (val < (int16_t)(1 << 15)) {
186 feraiseexcept(FeInvalid);
246 if (isSigned) {
247 if (half) {
248 if (val < (int16_t)(1 << 15)) {
249 feraiseexcept(FeInvalid);
250 feclearexcept(FeInexact);
187 return (int16_t)(1 << 15);
188 }
189 if (val > (int16_t)mask(15)) {
190 feraiseexcept(FeInvalid);
251 return (int16_t)(1 << 15);
252 }
253 if (val > (int16_t)mask(15)) {
254 feraiseexcept(FeInvalid);
255 feclearexcept(FeInexact);
191 return (int16_t)mask(15);
192 }
193 return (int16_t)val;
194 } else {
195 if (val < (int32_t)(1 << 31)) {
196 feraiseexcept(FeInvalid);
256 return (int16_t)mask(15);
257 }
258 return (int16_t)val;
259 } else {
260 if (val < (int32_t)(1 << 31)) {
261 feraiseexcept(FeInvalid);
262 feclearexcept(FeInexact);
197 return (int32_t)(1 << 31);
198 }
199 if (val > (int32_t)mask(31)) {
200 feraiseexcept(FeInvalid);
263 return (int32_t)(1 << 31);
264 }
265 if (val > (int32_t)mask(31)) {
266 feraiseexcept(FeInvalid);
267 feclearexcept(FeInexact);
201 return (int32_t)mask(31);
202 }
203 return (int32_t)val;
204 }
205 } else {
206 if (half) {
207 if (val < 0) {
208 feraiseexcept(FeInvalid);
268 return (int32_t)mask(31);
269 }
270 return (int32_t)val;
271 }
272 } else {
273 if (half) {
274 if (val < 0) {
275 feraiseexcept(FeInvalid);
276 feclearexcept(FeInexact);
209 return 0;
210 }
211 if (val > mask(16)) {
212 feraiseexcept(FeInvalid);
277 return 0;
278 }
279 if (val > mask(16)) {
280 feraiseexcept(FeInvalid);
281 feclearexcept(FeInexact);
213 return mask(16);
214 }
215 return (uint16_t)val;
216 } else {
217 if (val < 0) {
218 feraiseexcept(FeInvalid);
282 return mask(16);
283 }
284 return (uint16_t)val;
285 } else {
286 if (val < 0) {
287 feraiseexcept(FeInvalid);
288 feclearexcept(FeInexact);
219 return 0;
220 }
221 if (val > mask(32)) {
222 feraiseexcept(FeInvalid);
289 return 0;
290 }
291 if (val > mask(32)) {
292 feraiseexcept(FeInvalid);
293 feclearexcept(FeInexact);
223 return mask(32);
224 }
225 return (uint32_t)val;
226 }
227 }
228}
229
230static inline double
231vfpUFixedToFpD(uint32_t val, bool half, uint8_t imm)
232{
233 fesetround(FeRoundNearest);
234 if (half)
235 val = (uint16_t)val;
294 return mask(32);
295 }
296 return (uint32_t)val;
297 }
298 }
299}
300
301static inline double
302vfpUFixedToFpD(uint32_t val, bool half, uint8_t imm)
303{
304 fesetround(FeRoundNearest);
305 if (half)
306 val = (uint16_t)val;
236 return val / pow(2.0, imm);
307 double scale = pow(2.0, imm);
308 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
309 feclearexcept(FeAllExceptions);
310 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
311 return val / scale;
237}
238
239static inline double
240vfpSFixedToFpD(int32_t val, bool half, uint8_t imm)
241{
242 fesetround(FeRoundNearest);
243 if (half)
244 val = sext<16>(val & mask(16));
312}
313
314static inline double
315vfpSFixedToFpD(int32_t val, bool half, uint8_t imm)
316{
317 fesetround(FeRoundNearest);
318 if (half)
319 val = sext<16>(val & mask(16));
245 return val / pow(2.0, imm);
320 double scale = pow(2.0, imm);
321 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
322 feclearexcept(FeAllExceptions);
323 __asm__ __volatile__("" : "=m" (scale) : "m" (scale));
324 return val / scale;
246}
247
248typedef int VfpSavedState;
249
250static inline VfpSavedState
251prepVfpFpscr(FPSCR fpscr)
252{
253 int roundingMode = fegetround();

--- 152 unchanged lines hidden ---
325}
326
327typedef int VfpSavedState;
328
329static inline VfpSavedState
330prepVfpFpscr(FPSCR fpscr)
331{
332 int roundingMode = fegetround();

--- 152 unchanged lines hidden ---