Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / target / hexagon / arch.c
blobd053d6848715c283f6dd58723d8f01ba656dfd95
1 /*
2 * Copyright(c) 2019-2023 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"
20 #include "cpu.h"
21 #include "fma_emu.h"
22 #include "arch.h"
23 #include "macros.h"
25 #define SF_BIAS 127
26 #define SF_MAXEXP 254
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] = {
34 {128, 176, 208, 240},
35 {128, 167, 197, 227},
36 {128, 158, 187, 216},
37 {123, 150, 178, 205},
38 {116, 142, 169, 195},
39 {111, 135, 160, 185},
40 {105, 128, 152, 175},
41 {100, 122, 144, 166},
42 {95, 116, 137, 158},
43 {90, 110, 130, 150},
44 {85, 104, 123, 142},
45 {81, 99, 117, 135},
46 {77, 94, 111, 128},
47 {73, 89, 105, 122},
48 {69, 85, 100, 116},
49 {66, 80, 95, 110},
50 {62, 76, 90, 104},
51 {59, 72, 86, 99},
52 {56, 69, 81, 94},
53 {53, 65, 77, 89},
54 {51, 62, 73, 85},
55 {48, 59, 69, 80},
56 {46, 56, 66, 76},
57 {43, 53, 63, 72},
58 {41, 50, 59, 69},
59 {39, 48, 56, 65},
60 {37, 45, 54, 62},
61 {35, 43, 51, 59},
62 {33, 41, 48, 56},
63 {32, 39, 46, 53},
64 {30, 37, 43, 50},
65 {29, 35, 41, 48},
66 {27, 33, 39, 45},
67 {26, 31, 37, 43},
68 {24, 30, 35, 41},
69 {23, 28, 33, 39},
70 {22, 27, 32, 37},
71 {21, 26, 30, 35},
72 {20, 24, 29, 33},
73 {19, 23, 27, 31},
74 {18, 22, 26, 30},
75 {17, 21, 25, 28},
76 {16, 20, 23, 27},
77 {15, 19, 22, 25},
78 {14, 18, 21, 24},
79 {14, 17, 20, 23},
80 {13, 16, 19, 22},
81 {12, 15, 18, 21},
82 {12, 14, 17, 20},
83 {11, 14, 16, 19},
84 {11, 13, 15, 18},
85 {10, 12, 15, 17},
86 {10, 12, 14, 16},
87 {9, 11, 13, 15},
88 {9, 11, 12, 14},
89 {8, 10, 12, 14},
90 {8, 9, 11, 13},
91 {7, 9, 11, 12},
92 {7, 9, 10, 12},
93 {7, 8, 10, 11},
94 {6, 8, 9, 11},
95 {6, 7, 9, 10},
96 {6, 7, 8, 9},
97 {2, 2, 2, 2}
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,
107 61, 62, 62, 63
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,
118 37, 38, 38, 63
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);
154 /* Unspread bits */
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)
172 int64_t val;
174 if (n == 0) {
175 val = a;
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));
179 } else {
180 val = ((fSE32_64(a)) + (1 << (n - 1)));
183 val = val >> n;
184 return (int32_t)val;
187 /* Floating Point Stuff */
189 static const FloatRoundMode softfloat_roundingmodes[] = {
190 float_round_nearest_even,
191 float_round_to_zero,
192 float_round_down,
193 float_round_up,
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)],
201 &env->fp_status);
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)
211 #endif
213 #define SOFTFLOAT_TEST_FLAG(FLAG, MYF, MYE) \
214 do { \
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; \
223 } while (0)
225 void arch_fpop_end(CPUHexagonState *env)
227 const bool pkt_need_commit = true;
228 int flags = get_float_exception_flags(&env->fp_status);
229 if (flags != 0) {
230 SOFTFLOAT_TEST_FLAG(float_flag_inexact, FPINPF, FPINPE);
231 SOFTFLOAT_TEST_FLAG(float_flag_divbyzero, FPDBZF, FPDBZE);
232 SOFTFLOAT_TEST_FLAG(float_flag_invalid, FPINVF, FPINVE);
233 SOFTFLOAT_TEST_FLAG(float_flag_overflow, FPOVFF, FPOVFE);
234 SOFTFLOAT_TEST_FLAG(float_flag_underflow, FPUNFF, FPUNFE);
238 int arch_sf_recip_common(float32 *Rs, float32 *Rt, float32 *Rd, int *adjust,
239 float_status *fp_status)
241 int n_exp;
242 int d_exp;
243 int ret = 0;
244 float32 RsV, RtV, RdV;
245 int PeV = 0;
246 RsV = *Rs;
247 RtV = *Rt;
248 if (float32_is_any_nan(RsV) && float32_is_any_nan(RtV)) {
249 if (extract32(RsV & RtV, 22, 1) == 0) {
250 float_raise(float_flag_invalid, fp_status);
252 RdV = RsV = RtV = float32_nan;
253 } else if (float32_is_any_nan(RsV)) {
254 if (extract32(RsV, 22, 1) == 0) {
255 float_raise(float_flag_invalid, fp_status);
257 RdV = RsV = RtV = float32_nan;
258 } else if (float32_is_any_nan(RtV)) {
259 /* or put NaN in num/den fixup? */
260 if (extract32(RtV, 22, 1) == 0) {
261 float_raise(float_flag_invalid, fp_status);
263 RdV = RsV = RtV = float32_nan;
264 } else if (float32_is_infinity(RsV) && float32_is_infinity(RtV)) {
265 /* or put Inf in num fixup? */
266 RdV = RsV = RtV = float32_nan;
267 float_raise(float_flag_invalid, fp_status);
268 } else if (float32_is_zero(RsV) && float32_is_zero(RtV)) {
269 /* or put zero in num fixup? */
270 RdV = RsV = RtV = float32_nan;
271 float_raise(float_flag_invalid, fp_status);
272 } else if (float32_is_zero(RtV)) {
273 /* or put Inf in num fixup? */
274 uint8_t RsV_sign = float32_is_neg(RsV);
275 uint8_t RtV_sign = float32_is_neg(RtV);
276 /* Check that RsV is NOT infinite before we overwrite it */
277 if (!float32_is_infinity(RsV)) {
278 float_raise(float_flag_divbyzero, fp_status);
280 RsV = infinite_float32(RsV_sign ^ RtV_sign);
281 RtV = float32_one;
282 RdV = float32_one;
283 } else if (float32_is_infinity(RtV)) {
284 RsV = make_float32(0x80000000 & (RsV ^ RtV));
285 RtV = float32_one;
286 RdV = float32_one;
287 } else if (float32_is_zero(RsV)) {
288 /* Does this just work itself out? */
289 /* No, 0/Inf causes problems. */
290 RsV = make_float32(0x80000000 & (RsV ^ RtV));
291 RtV = float32_one;
292 RdV = float32_one;
293 } else if (float32_is_infinity(RsV)) {
294 uint8_t RsV_sign = float32_is_neg(RsV);
295 uint8_t RtV_sign = float32_is_neg(RtV);
296 RsV = infinite_float32(RsV_sign ^ RtV_sign);
297 RtV = float32_one;
298 RdV = float32_one;
299 } else {
300 PeV = 0x00;
301 /* Basic checks passed */
302 n_exp = float32_getexp_raw(RsV);
303 d_exp = float32_getexp_raw(RtV);
304 if ((n_exp - d_exp + SF_BIAS) <= SF_MANTBITS) {
305 /* Near quotient underflow / inexact Q */
306 PeV = 0x80;
307 RtV = float32_scalbn(RtV, -64, fp_status);
308 RsV = float32_scalbn(RsV, 64, fp_status);
309 } else if ((n_exp - d_exp + SF_BIAS) > (SF_MAXEXP - 24)) {
310 /* Near quotient overflow */
311 PeV = 0x40;
312 RtV = float32_scalbn(RtV, 32, fp_status);
313 RsV = float32_scalbn(RsV, -32, fp_status);
314 } else if (n_exp <= SF_MANTBITS + 2) {
315 RtV = float32_scalbn(RtV, 64, fp_status);
316 RsV = float32_scalbn(RsV, 64, fp_status);
317 } else if (d_exp <= 1) {
318 RtV = float32_scalbn(RtV, 32, fp_status);
319 RsV = float32_scalbn(RsV, 32, fp_status);
320 } else if (d_exp > 252) {
321 RtV = float32_scalbn(RtV, -32, fp_status);
322 RsV = float32_scalbn(RsV, -32, fp_status);
324 RdV = 0;
325 ret = 1;
327 *Rs = RsV;
328 *Rt = RtV;
329 *Rd = RdV;
330 *adjust = PeV;
331 return ret;
334 int arch_sf_invsqrt_common(float32 *Rs, float32 *Rd, int *adjust,
335 float_status *fp_status)
337 float32 RsV, RdV;
338 int PeV = 0;
339 int r_exp;
340 int ret = 0;
341 RsV = *Rs;
342 if (float32_is_any_nan(RsV)) {
343 if (extract32(RsV, 22, 1) == 0) {
344 float_raise(float_flag_invalid, fp_status);
346 RdV = RsV = float32_nan;
347 } else if (float32_lt(RsV, float32_zero, fp_status)) {
348 /* Negative nonzero values are NaN */
349 float_raise(float_flag_invalid, fp_status);
350 RsV = float32_nan;
351 RdV = float32_nan;
352 } else if (float32_is_infinity(RsV)) {
353 /* or put Inf in num fixup? */
354 RsV = infinite_float32(1);
355 RdV = infinite_float32(1);
356 } else if (float32_is_zero(RsV)) {
357 /* or put zero in num fixup? */
358 RdV = float32_one;
359 } else {
360 PeV = 0x00;
361 /* Basic checks passed */
362 r_exp = float32_getexp(RsV);
363 if (r_exp <= 24) {
364 RsV = float32_scalbn(RsV, 64, fp_status);
365 PeV = 0xe0;
367 RdV = 0;
368 ret = 1;
370 *Rs = RsV;
371 *Rd = RdV;
372 *adjust = PeV;
373 return ret;
376 const uint8_t recip_lookup_table[128] = {
377 0x0fe, 0x0fa, 0x0f6, 0x0f2, 0x0ef, 0x0eb, 0x0e7, 0x0e4,
378 0x0e0, 0x0dd, 0x0d9, 0x0d6, 0x0d2, 0x0cf, 0x0cc, 0x0c9,
379 0x0c6, 0x0c2, 0x0bf, 0x0bc, 0x0b9, 0x0b6, 0x0b3, 0x0b1,
380 0x0ae, 0x0ab, 0x0a8, 0x0a5, 0x0a3, 0x0a0, 0x09d, 0x09b,
381 0x098, 0x096, 0x093, 0x091, 0x08e, 0x08c, 0x08a, 0x087,
382 0x085, 0x083, 0x080, 0x07e, 0x07c, 0x07a, 0x078, 0x075,
383 0x073, 0x071, 0x06f, 0x06d, 0x06b, 0x069, 0x067, 0x065,
384 0x063, 0x061, 0x05f, 0x05e, 0x05c, 0x05a, 0x058, 0x056,
385 0x054, 0x053, 0x051, 0x04f, 0x04e, 0x04c, 0x04a, 0x049,
386 0x047, 0x045, 0x044, 0x042, 0x040, 0x03f, 0x03d, 0x03c,
387 0x03a, 0x039, 0x037, 0x036, 0x034, 0x033, 0x032, 0x030,
388 0x02f, 0x02d, 0x02c, 0x02b, 0x029, 0x028, 0x027, 0x025,
389 0x024, 0x023, 0x021, 0x020, 0x01f, 0x01e, 0x01c, 0x01b,
390 0x01a, 0x019, 0x017, 0x016, 0x015, 0x014, 0x013, 0x012,
391 0x011, 0x00f, 0x00e, 0x00d, 0x00c, 0x00b, 0x00a, 0x009,
392 0x008, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x000,
395 const uint8_t invsqrt_lookup_table[128] = {
396 0x069, 0x066, 0x063, 0x061, 0x05e, 0x05b, 0x059, 0x057,
397 0x054, 0x052, 0x050, 0x04d, 0x04b, 0x049, 0x047, 0x045,
398 0x043, 0x041, 0x03f, 0x03d, 0x03b, 0x039, 0x037, 0x036,
399 0x034, 0x032, 0x030, 0x02f, 0x02d, 0x02c, 0x02a, 0x028,
400 0x027, 0x025, 0x024, 0x022, 0x021, 0x01f, 0x01e, 0x01d,
401 0x01b, 0x01a, 0x019, 0x017, 0x016, 0x015, 0x014, 0x012,
402 0x011, 0x010, 0x00f, 0x00d, 0x00c, 0x00b, 0x00a, 0x009,
403 0x008, 0x007, 0x006, 0x005, 0x004, 0x003, 0x002, 0x001,
404 0x0fe, 0x0fa, 0x0f6, 0x0f3, 0x0ef, 0x0eb, 0x0e8, 0x0e4,
405 0x0e1, 0x0de, 0x0db, 0x0d7, 0x0d4, 0x0d1, 0x0ce, 0x0cb,
406 0x0c9, 0x0c6, 0x0c3, 0x0c0, 0x0be, 0x0bb, 0x0b8, 0x0b6,
407 0x0b3, 0x0b1, 0x0af, 0x0ac, 0x0aa, 0x0a8, 0x0a5, 0x0a3,
408 0x0a1, 0x09f, 0x09d, 0x09b, 0x099, 0x097, 0x095, 0x093,
409 0x091, 0x08f, 0x08d, 0x08b, 0x089, 0x087, 0x086, 0x084,
410 0x082, 0x080, 0x07f, 0x07d, 0x07b, 0x07a, 0x078, 0x077,
411 0x075, 0x074, 0x072, 0x071, 0x06f, 0x06e, 0x06c, 0x06b,