2 * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "qemu/osdep.h"
19 #include "fpu/softfloat.h"
27 #define SF_MANTBITS 23
28 #define float32_nan make_float32(0xffffffff)
31 * These three tables are used by the cabacdecbin instruction
33 const uint8_t rLPS_table_64x4
[64][4] = {
100 const uint8_t AC_next_state_MPS_64
[64] = {
101 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
102 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
103 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
104 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
105 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
106 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
111 const uint8_t AC_next_state_LPS_64
[64] = {
112 0, 0, 1, 2, 2, 4, 4, 5, 6, 7,
113 8, 9, 9, 11, 11, 12, 13, 13, 15, 15,
114 16, 16, 18, 18, 19, 19, 21, 21, 22, 22,
115 23, 24, 24, 25, 26, 26, 27, 27, 28, 29,
116 29, 30, 30, 30, 31, 32, 32, 33, 33, 33,
117 34, 34, 35, 35, 35, 36, 36, 36, 37, 37,
121 #define BITS_MASK_8 0x5555555555555555ULL
122 #define PAIR_MASK_8 0x3333333333333333ULL
123 #define NYBL_MASK_8 0x0f0f0f0f0f0f0f0fULL
124 #define BYTE_MASK_8 0x00ff00ff00ff00ffULL
125 #define HALF_MASK_8 0x0000ffff0000ffffULL
126 #define WORD_MASK_8 0x00000000ffffffffULL
128 uint64_t interleave(uint32_t odd
, uint32_t even
)
130 /* Convert to long long */
131 uint64_t myodd
= odd
;
132 uint64_t myeven
= even
;
133 /* First, spread bits out */
134 myodd
= (myodd
| (myodd
<< 16)) & HALF_MASK_8
;
135 myeven
= (myeven
| (myeven
<< 16)) & HALF_MASK_8
;
136 myodd
= (myodd
| (myodd
<< 8)) & BYTE_MASK_8
;
137 myeven
= (myeven
| (myeven
<< 8)) & BYTE_MASK_8
;
138 myodd
= (myodd
| (myodd
<< 4)) & NYBL_MASK_8
;
139 myeven
= (myeven
| (myeven
<< 4)) & NYBL_MASK_8
;
140 myodd
= (myodd
| (myodd
<< 2)) & PAIR_MASK_8
;
141 myeven
= (myeven
| (myeven
<< 2)) & PAIR_MASK_8
;
142 myodd
= (myodd
| (myodd
<< 1)) & BITS_MASK_8
;
143 myeven
= (myeven
| (myeven
<< 1)) & BITS_MASK_8
;
144 /* Now OR together */
145 return myeven
| (myodd
<< 1);
148 uint64_t deinterleave(uint64_t src
)
150 /* Get odd and even bits */
151 uint64_t myodd
= ((src
>> 1) & BITS_MASK_8
);
152 uint64_t myeven
= (src
& BITS_MASK_8
);
155 myeven
= (myeven
| (myeven
>> 1)) & PAIR_MASK_8
;
156 myodd
= (myodd
| (myodd
>> 1)) & PAIR_MASK_8
;
157 myeven
= (myeven
| (myeven
>> 2)) & NYBL_MASK_8
;
158 myodd
= (myodd
| (myodd
>> 2)) & NYBL_MASK_8
;
159 myeven
= (myeven
| (myeven
>> 4)) & BYTE_MASK_8
;
160 myodd
= (myodd
| (myodd
>> 4)) & BYTE_MASK_8
;
161 myeven
= (myeven
| (myeven
>> 8)) & HALF_MASK_8
;
162 myodd
= (myodd
| (myodd
>> 8)) & HALF_MASK_8
;
163 myeven
= (myeven
| (myeven
>> 16)) & WORD_MASK_8
;
164 myodd
= (myodd
| (myodd
>> 16)) & WORD_MASK_8
;
166 /* Return odd bits in upper half */
167 return myeven
| (myodd
<< 32);
170 int32_t conv_round(int32_t a
, int n
)
176 } else if ((a
& ((1 << (n
- 1)) - 1)) == 0) { /* N-1..0 all zero? */
177 /* Add LSB from int part */
178 val
= ((fSE32_64(a
)) + (int64_t) (((uint32_t) ((1 << n
) & a
)) >> 1));
180 val
= ((fSE32_64(a
)) + (1 << (n
- 1)));
187 /* Floating Point Stuff */
189 static const FloatRoundMode softfloat_roundingmodes
[] = {
190 float_round_nearest_even
,
196 void arch_fpop_start(CPUHexagonState
*env
)
198 set_float_exception_flags(0, &env
->fp_status
);
199 set_float_rounding_mode(
200 softfloat_roundingmodes
[fREAD_REG_FIELD(USR
, USR_FPRND
)],
204 #ifdef CONFIG_USER_ONLY
206 * Hexagon Linux kernel only sets the relevant bits in USR (user status
207 * register). The exception isn't raised to user mode, so we don't
208 * model it in qemu user mode.
210 #define RAISE_FP_EXCEPTION do {} while (0)
213 #define SOFTFLOAT_TEST_FLAG(FLAG, MYF, MYE) \
215 if (flags & FLAG) { \
216 if (GET_USR_FIELD(USR_##MYF) == 0) { \
217 SET_USR_FIELD(USR_##MYF, 1); \
218 if (GET_USR_FIELD(USR_##MYE)) { \
219 RAISE_FP_EXCEPTION; \
225 void arch_fpop_end(CPUHexagonState
*env
)
227 int flags
= get_float_exception_flags(&env
->fp_status
);
229 SOFTFLOAT_TEST_FLAG(float_flag_inexact
, FPINPF
, FPINPE
);
230 SOFTFLOAT_TEST_FLAG(float_flag_divbyzero
, FPDBZF
, FPDBZE
);
231 SOFTFLOAT_TEST_FLAG(float_flag_invalid
, FPINVF
, FPINVE
);
232 SOFTFLOAT_TEST_FLAG(float_flag_overflow
, FPOVFF
, FPOVFE
);
233 SOFTFLOAT_TEST_FLAG(float_flag_underflow
, FPUNFF
, FPUNFE
);
237 int arch_sf_recip_common(float32
*Rs
, float32
*Rt
, float32
*Rd
, int *adjust
,
238 float_status
*fp_status
)
243 float32 RsV
, RtV
, RdV
;
247 if (float32_is_any_nan(RsV
) && float32_is_any_nan(RtV
)) {
248 if (extract32(RsV
& RtV
, 22, 1) == 0) {
249 float_raise(float_flag_invalid
, fp_status
);
251 RdV
= RsV
= RtV
= float32_nan
;
252 } else if (float32_is_any_nan(RsV
)) {
253 if (extract32(RsV
, 22, 1) == 0) {
254 float_raise(float_flag_invalid
, fp_status
);
256 RdV
= RsV
= RtV
= float32_nan
;
257 } else if (float32_is_any_nan(RtV
)) {
258 /* or put NaN in num/den fixup? */
259 if (extract32(RtV
, 22, 1) == 0) {
260 float_raise(float_flag_invalid
, fp_status
);
262 RdV
= RsV
= RtV
= float32_nan
;
263 } else if (float32_is_infinity(RsV
) && float32_is_infinity(RtV
)) {
264 /* or put Inf in num fixup? */
265 RdV
= RsV
= RtV
= float32_nan
;
266 float_raise(float_flag_invalid
, fp_status
);
267 } else if (float32_is_zero(RsV
) && float32_is_zero(RtV
)) {
268 /* or put zero in num fixup? */
269 RdV
= RsV
= RtV
= float32_nan
;
270 float_raise(float_flag_invalid
, fp_status
);
271 } else if (float32_is_zero(RtV
)) {
272 /* or put Inf in num fixup? */
273 uint8_t RsV_sign
= float32_is_neg(RsV
);
274 uint8_t RtV_sign
= float32_is_neg(RtV
);
275 /* Check that RsV is NOT infinite before we overwrite it */
276 if (!float32_is_infinity(RsV
)) {
277 float_raise(float_flag_divbyzero
, fp_status
);
279 RsV
= infinite_float32(RsV_sign
^ RtV_sign
);
282 } else if (float32_is_infinity(RtV
)) {
283 RsV
= make_float32(0x80000000 & (RsV
^ RtV
));
286 } else if (float32_is_zero(RsV
)) {
287 /* Does this just work itself out? */
288 /* No, 0/Inf causes problems. */
289 RsV
= make_float32(0x80000000 & (RsV
^ RtV
));
292 } else if (float32_is_infinity(RsV
)) {
293 uint8_t RsV_sign
= float32_is_neg(RsV
);
294 uint8_t RtV_sign
= float32_is_neg(RtV
);
295 RsV
= infinite_float32(RsV_sign
^ RtV_sign
);
300 /* Basic checks passed */
301 n_exp
= float32_getexp(RsV
);
302 d_exp
= float32_getexp(RtV
);
303 if ((n_exp
- d_exp
+ SF_BIAS
) <= SF_MANTBITS
) {
304 /* Near quotient underflow / inexact Q */
306 RtV
= float32_scalbn(RtV
, -64, fp_status
);
307 RsV
= float32_scalbn(RsV
, 64, fp_status
);
308 } else if ((n_exp
- d_exp
+ SF_BIAS
) > (SF_MAXEXP
- 24)) {
309 /* Near quotient overflow */
311 RtV
= float32_scalbn(RtV
, 32, fp_status
);
312 RsV
= float32_scalbn(RsV
, -32, fp_status
);
313 } else if (n_exp
<= SF_MANTBITS
+ 2) {
314 RtV
= float32_scalbn(RtV
, 64, fp_status
);
315 RsV
= float32_scalbn(RsV
, 64, fp_status
);
316 } else if (d_exp
<= 1) {
317 RtV
= float32_scalbn(RtV
, 32, fp_status
);
318 RsV
= float32_scalbn(RsV
, 32, fp_status
);
319 } else if (d_exp
> 252) {
320 RtV
= float32_scalbn(RtV
, -32, fp_status
);
321 RsV
= float32_scalbn(RsV
, -32, fp_status
);
333 int arch_sf_invsqrt_common(float32
*Rs
, float32
*Rd
, int *adjust
,
334 float_status
*fp_status
)
341 if (float32_is_any_nan(RsV
)) {
342 if (extract32(RsV
, 22, 1) == 0) {
343 float_raise(float_flag_invalid
, fp_status
);
345 RdV
= RsV
= float32_nan
;
346 } else if (float32_lt(RsV
, float32_zero
, fp_status
)) {
347 /* Negative nonzero values are NaN */
348 float_raise(float_flag_invalid
, fp_status
);
351 } else if (float32_is_infinity(RsV
)) {
352 /* or put Inf in num fixup? */
353 RsV
= infinite_float32(1);
354 RdV
= infinite_float32(1);
355 } else if (float32_is_zero(RsV
)) {
356 /* or put zero in num fixup? */
360 /* Basic checks passed */
361 r_exp
= float32_getexp(RsV
);
363 RsV
= float32_scalbn(RsV
, 64, fp_status
);
375 const uint8_t recip_lookup_table
[128] = {
376 0x0fe, 0x0fa, 0x0f6, 0x0f2, 0x0ef, 0x0eb, 0x0e7, 0x0e4,
377 0x0e0, 0x0dd, 0x0d9, 0x0d6, 0x0d2, 0x0cf, 0x0cc, 0x0c9,
378 0x0c6, 0x0c2, 0x0bf, 0x0bc, 0x0b9, 0x0b6, 0x0b3, 0x0b1,
379 0x0ae, 0x0ab, 0x0a8, 0x0a5, 0x0a3, 0x0a0, 0x09d, 0x09b,
380 0x098, 0x096, 0x093, 0x091, 0x08e, 0x08c, 0x08a, 0x087,
381 0x085, 0x083, 0x080, 0x07e, 0x07c, 0x07a, 0x078, 0x075,
382 0x073, 0x071, 0x06f, 0x06d, 0x06b, 0x069, 0x067, 0x065,
383 0x063, 0x061, 0x05f, 0x05e, 0x05c, 0x05a, 0x058, 0x056,
384 0x054, 0x053, 0x051, 0x04f, 0x04e, 0x04c, 0x04a, 0x049,
385 0x047, 0x045, 0x044, 0x042, 0x040, 0x03f, 0x03d, 0x03c,
386 0x03a, 0x039, 0x037, 0x036, 0x034, 0x033, 0x032, 0x030,
387 0x02f, 0x02d, 0x02c, 0x02b, 0x029, 0x028, 0x027, 0x025,
388 0x024, 0x023, 0x021, 0x020, 0x01f, 0x01e, 0x01c, 0x01b,
389 0x01a, 0x019, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012,
390 0x011, 0x00f, 0x00e, 0x00d, 0x00c, 0x00b, 0x00a, 0x009,
391 0x008, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x000,
394 const uint8_t invsqrt_lookup_table
[128] = {
395 0x069, 0x066, 0x063, 0x061, 0x05e, 0x05b, 0x059, 0x057,
396 0x054, 0x052, 0x050, 0x04d, 0x04b, 0x049, 0x047, 0x045,
397 0x043, 0x041, 0x03f, 0x03d, 0x03b, 0x039, 0x037, 0x036,
398 0x034, 0x032, 0x030, 0x02f, 0x02d, 0x02c, 0x02a, 0x028,
399 0x027, 0x025, 0x024, 0x022, 0x021, 0x01f, 0x01e, 0x01d,
400 0x01b, 0x01a, 0x019, 0x017, 0x016, 0x015, 0x014, 0x012,
401 0x011, 0x010, 0x00f, 0x00d, 0x00c, 0x00b, 0x00a, 0x009,
402 0x008, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001,
403 0x0fe, 0x0fa, 0x0f6, 0x0f3, 0x0ef, 0x0eb, 0x0e8, 0x0e4,
404 0x0e1, 0x0de, 0x0db, 0x0d7, 0x0d4, 0x0d1, 0x0ce, 0x0cb,
405 0x0c9, 0x0c6, 0x0c3, 0x0c0, 0x0be, 0x0bb, 0x0b8, 0x0b6,
406 0x0b3, 0x0b1, 0x0af, 0x0ac, 0x0aa, 0x0a8, 0x0a5, 0x0a3,
407 0x0a1, 0x09f, 0x09d, 0x09b, 0x099, 0x097, 0x095, 0x093,
408 0x091, 0x08f, 0x08d, 0x08b, 0x089, 0x087, 0x086, 0x084,
409 0x082, 0x080, 0x07f, 0x07d, 0x07b, 0x07a, 0x078, 0x077,
410 0x075, 0x074, 0x072, 0x071, 0x06f, 0x06e, 0x06c, 0x06b,