1 /*
2 * Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
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.
8 *
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.
13 *
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/>.
16 */
17
18 #include "qemu/osdep.h"
19 #include "qemu/log.h"
20 #include "accel/tcg/cpu-ldst.h"
21 #include "accel/tcg/probe.h"
22 #include "exec/helper-proto.h"
23 #include "fpu/softfloat.h"
24 #include "cpu.h"
25 #include "internal.h"
26 #include "macros.h"
27 #include "arch.h"
28 #include "hex_arch_types.h"
29 #include "fma_emu.h"
30 #include "mmvec/mmvec.h"
31 #include "mmvec/macros.h"
32 #include "op_helper.h"
33 #include "translate.h"
34
35 #define SF_BIAS 127
36 #define SF_MANTBITS 23
37
38 /* Exceptions processing helpers */
hexagon_raise_exception_err(CPUHexagonState * env,uint32_t exception,uintptr_t pc)39 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
40 uint32_t exception,
41 uintptr_t pc)
42 {
43 CPUState *cs = env_cpu(env);
44 qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
45 cs->exception_index = exception;
46 cpu_loop_exit_restore(cs, pc);
47 }
48
HELPER(raise_exception)49 G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp)
50 {
51 hexagon_raise_exception_err(env, excp, 0);
52 }
53
log_store32(CPUHexagonState * env,target_ulong addr,target_ulong val,int width,int slot)54 void log_store32(CPUHexagonState *env, target_ulong addr,
55 target_ulong val, int width, int slot)
56 {
57 env->mem_log_stores[slot].va = addr;
58 env->mem_log_stores[slot].width = width;
59 env->mem_log_stores[slot].data32 = val;
60 }
61
log_store64(CPUHexagonState * env,target_ulong addr,int64_t val,int width,int slot)62 void log_store64(CPUHexagonState *env, target_ulong addr,
63 int64_t val, int width, int slot)
64 {
65 env->mem_log_stores[slot].va = addr;
66 env->mem_log_stores[slot].width = width;
67 env->mem_log_stores[slot].data64 = val;
68 }
69
commit_store(CPUHexagonState * env,int slot_num,uintptr_t ra)70 static void commit_store(CPUHexagonState *env, int slot_num, uintptr_t ra)
71 {
72 uint8_t width = env->mem_log_stores[slot_num].width;
73 target_ulong va = env->mem_log_stores[slot_num].va;
74
75 switch (width) {
76 case 1:
77 cpu_stb_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
78 break;
79 case 2:
80 cpu_stw_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
81 break;
82 case 4:
83 cpu_stl_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
84 break;
85 case 8:
86 cpu_stq_data_ra(env, va, env->mem_log_stores[slot_num].data64, ra);
87 break;
88 default:
89 g_assert_not_reached();
90 }
91 }
92
HELPER(commit_store)93 void HELPER(commit_store)(CPUHexagonState *env, int slot_num)
94 {
95 uintptr_t ra = GETPC();
96 commit_store(env, slot_num, ra);
97 }
98
HELPER(gather_store)99 void HELPER(gather_store)(CPUHexagonState *env, uint32_t addr, int slot)
100 {
101 mem_gather_store(env, addr, slot);
102 }
103
HELPER(commit_hvx_stores)104 void HELPER(commit_hvx_stores)(CPUHexagonState *env)
105 {
106 uintptr_t ra = GETPC();
107
108 /* Normal (possibly masked) vector store */
109 for (int i = 0; i < VSTORES_MAX; i++) {
110 if (env->vstore_pending[i]) {
111 env->vstore_pending[i] = 0;
112 target_ulong va = env->vstore[i].va;
113 int size = env->vstore[i].size;
114 for (int j = 0; j < size; j++) {
115 if (test_bit(j, env->vstore[i].mask)) {
116 cpu_stb_data_ra(env, va + j, env->vstore[i].data.ub[j], ra);
117 }
118 }
119 }
120 }
121
122 /* Scatter store */
123 if (env->vtcm_pending) {
124 env->vtcm_pending = false;
125 if (env->vtcm_log.op) {
126 /* Need to perform the scatter read/modify/write at commit time */
127 if (env->vtcm_log.op_size == 2) {
128 SCATTER_OP_WRITE_TO_MEM(uint16_t);
129 } else if (env->vtcm_log.op_size == 4) {
130 /* Word Scatter += */
131 SCATTER_OP_WRITE_TO_MEM(uint32_t);
132 } else {
133 g_assert_not_reached();
134 }
135 } else {
136 for (int i = 0; i < sizeof(MMVector); i++) {
137 if (test_bit(i, env->vtcm_log.mask)) {
138 cpu_stb_data_ra(env, env->vtcm_log.va[i],
139 env->vtcm_log.data.ub[i], ra);
140 clear_bit(i, env->vtcm_log.mask);
141 env->vtcm_log.data.ub[i] = 0;
142 }
143
144 }
145 }
146 }
147 }
148
HELPER(fcircadd)149 int32_t HELPER(fcircadd)(int32_t RxV, int32_t offset, int32_t M, int32_t CS)
150 {
151 uint32_t K_const = extract32(M, 24, 4);
152 uint32_t length = extract32(M, 0, 17);
153 uint32_t new_ptr = RxV + offset;
154 uint32_t start_addr;
155 uint32_t end_addr;
156
157 if (K_const == 0 && length >= 4) {
158 start_addr = CS;
159 end_addr = start_addr + length;
160 } else {
161 /*
162 * Versions v3 and earlier used the K value to specify a power-of-2 size
163 * 2^(K+2) that is greater than the buffer length
164 */
165 int32_t mask = (1 << (K_const + 2)) - 1;
166 start_addr = RxV & (~mask);
167 end_addr = start_addr | length;
168 }
169
170 if (new_ptr >= end_addr) {
171 new_ptr -= length;
172 } else if (new_ptr < start_addr) {
173 new_ptr += length;
174 }
175
176 return new_ptr;
177 }
178
HELPER(fbrev)179 uint32_t HELPER(fbrev)(uint32_t addr)
180 {
181 /*
182 * Bit reverse the low 16 bits of the address
183 */
184 return deposit32(addr, 0, 16, revbit16(addr));
185 }
186
build_float32(uint8_t sign,uint32_t exp,uint32_t mant)187 static float32 build_float32(uint8_t sign, uint32_t exp, uint32_t mant)
188 {
189 return make_float32(
190 ((sign & 1) << 31) |
191 ((exp & 0xff) << SF_MANTBITS) |
192 (mant & ((1 << SF_MANTBITS) - 1)));
193 }
194
195 /*
196 * sfrecipa, sfinvsqrta have two 32-bit results
197 * r0,p0=sfrecipa(r1,r2)
198 * r0,p0=sfinvsqrta(r1)
199 *
200 * Since helpers can only return a single value, we pack the two results
201 * into a 64-bit value.
202 */
HELPER(sfrecipa)203 uint64_t HELPER(sfrecipa)(CPUHexagonState *env, float32 RsV, float32 RtV)
204 {
205 int32_t PeV = 0;
206 float32 RdV;
207 int idx;
208 int adjust;
209 int mant;
210 int exp;
211
212 arch_fpop_start(env);
213 if (arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status)) {
214 PeV = adjust;
215 idx = (RtV >> 16) & 0x7f;
216 mant = (recip_lookup_table[idx] << 15) | 1;
217 exp = SF_BIAS - (float32_getexp(RtV) - SF_BIAS) - 1;
218 RdV = build_float32(extract32(RtV, 31, 1), exp, mant);
219 }
220 arch_fpop_end(env);
221 return ((uint64_t)RdV << 32) | PeV;
222 }
223
HELPER(sfinvsqrta)224 uint64_t HELPER(sfinvsqrta)(CPUHexagonState *env, float32 RsV)
225 {
226 int PeV = 0;
227 float32 RdV;
228 int idx;
229 int adjust;
230 int mant;
231 int exp;
232
233 arch_fpop_start(env);
234 if (arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status)) {
235 PeV = adjust;
236 idx = (RsV >> 17) & 0x7f;
237 mant = (invsqrt_lookup_table[idx] << 15);
238 exp = SF_BIAS - ((float32_getexp(RsV) - SF_BIAS) >> 1) - 1;
239 RdV = build_float32(extract32(RsV, 31, 1), exp, mant);
240 }
241 arch_fpop_end(env);
242 return ((uint64_t)RdV << 32) | PeV;
243 }
244
HELPER(vacsh_val)245 int64_t HELPER(vacsh_val)(CPUHexagonState *env,
246 int64_t RxxV, int64_t RssV, int64_t RttV,
247 uint32_t pkt_need_commit)
248 {
249 for (int i = 0; i < 4; i++) {
250 int xv = sextract64(RxxV, i * 16, 16);
251 int sv = sextract64(RssV, i * 16, 16);
252 int tv = sextract64(RttV, i * 16, 16);
253 int max;
254 xv = xv + tv;
255 sv = sv - tv;
256 max = xv > sv ? xv : sv;
257 /* Note that fSATH can set the OVF bit in usr */
258 RxxV = deposit64(RxxV, i * 16, 16, fSATH(max));
259 }
260 return RxxV;
261 }
262
HELPER(vacsh_pred)263 int32_t HELPER(vacsh_pred)(CPUHexagonState *env,
264 int64_t RxxV, int64_t RssV, int64_t RttV)
265 {
266 int32_t PeV = 0;
267 for (int i = 0; i < 4; i++) {
268 int xv = sextract64(RxxV, i * 16, 16);
269 int sv = sextract64(RssV, i * 16, 16);
270 int tv = sextract64(RttV, i * 16, 16);
271 xv = xv + tv;
272 sv = sv - tv;
273 PeV = deposit32(PeV, i * 2, 1, (xv > sv));
274 PeV = deposit32(PeV, i * 2 + 1, 1, (xv > sv));
275 }
276 return PeV;
277 }
278
HELPER(cabacdecbin_val)279 int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV)
280 {
281 int64_t RddV = 0;
282 size4u_t state;
283 size4u_t valMPS;
284 size4u_t bitpos;
285 size4u_t range;
286 size4u_t offset;
287 size4u_t rLPS;
288 size4u_t rMPS;
289
290 state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0);
291 valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8);
292 bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0);
293 range = fGETWORD(0, RssV);
294 offset = fGETWORD(1, RssV);
295
296 /* calculate rLPS */
297 range <<= bitpos;
298 offset <<= bitpos;
299 rLPS = rLPS_table_64x4[state][(range >> 29) & 3];
300 rLPS = rLPS << 23; /* left aligned */
301
302 /* calculate rMPS */
303 rMPS = (range & 0xff800000) - rLPS;
304
305 /* most probable region */
306 if (offset < rMPS) {
307 RddV = AC_next_state_MPS_64[state];
308 fINSERT_RANGE(RddV, 8, 8, valMPS);
309 fINSERT_RANGE(RddV, 31, 23, (rMPS >> 23));
310 fSETWORD(1, RddV, offset);
311 }
312 /* least probable region */
313 else {
314 RddV = AC_next_state_LPS_64[state];
315 fINSERT_RANGE(RddV, 8, 8, ((!state) ? (1 - valMPS) : (valMPS)));
316 fINSERT_RANGE(RddV, 31, 23, (rLPS >> 23));
317 fSETWORD(1, RddV, (offset - rMPS));
318 }
319 return RddV;
320 }
321
HELPER(cabacdecbin_pred)322 int32_t HELPER(cabacdecbin_pred)(int64_t RssV, int64_t RttV)
323 {
324 int32_t p0 = 0;
325 size4u_t state;
326 size4u_t valMPS;
327 size4u_t bitpos;
328 size4u_t range;
329 size4u_t offset;
330 size4u_t rLPS;
331 size4u_t rMPS;
332
333 state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0);
334 valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8);
335 bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0);
336 range = fGETWORD(0, RssV);
337 offset = fGETWORD(1, RssV);
338
339 /* calculate rLPS */
340 range <<= bitpos;
341 offset <<= bitpos;
342 rLPS = rLPS_table_64x4[state][(range >> 29) & 3];
343 rLPS = rLPS << 23; /* left aligned */
344
345 /* calculate rMPS */
346 rMPS = (range & 0xff800000) - rLPS;
347
348 /* most probable region */
349 if (offset < rMPS) {
350 p0 = valMPS;
351
352 }
353 /* least probable region */
354 else {
355 p0 = valMPS ^ 1;
356 }
357 return p0;
358 }
359
probe_store(CPUHexagonState * env,int slot,int mmu_idx,bool is_predicated,uintptr_t retaddr)360 static void probe_store(CPUHexagonState *env, int slot, int mmu_idx,
361 bool is_predicated, uintptr_t retaddr)
362 {
363 if (!is_predicated || !(env->slot_cancelled & (1 << slot))) {
364 size1u_t width = env->mem_log_stores[slot].width;
365 target_ulong va = env->mem_log_stores[slot].va;
366 probe_write(env, va, width, mmu_idx, retaddr);
367 }
368 }
369
370 /*
371 * Called from a mem_noshuf packet to make sure the load doesn't
372 * raise an exception
373 */
HELPER(probe_noshuf_load)374 void HELPER(probe_noshuf_load)(CPUHexagonState *env, target_ulong va,
375 int size, int mmu_idx)
376 {
377 uintptr_t retaddr = GETPC();
378 probe_read(env, va, size, mmu_idx, retaddr);
379 }
380
381 /* Called during packet commit when there are two scalar stores */
HELPER(probe_pkt_scalar_store_s0)382 void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int args)
383 {
384 int mmu_idx = FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX);
385 bool is_predicated =
386 FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED);
387 uintptr_t ra = GETPC();
388 probe_store(env, 0, mmu_idx, is_predicated, ra);
389 }
390
probe_hvx_stores(CPUHexagonState * env,int mmu_idx,uintptr_t retaddr)391 static void probe_hvx_stores(CPUHexagonState *env, int mmu_idx,
392 uintptr_t retaddr)
393 {
394 /* Normal (possibly masked) vector store */
395 for (int i = 0; i < VSTORES_MAX; i++) {
396 if (env->vstore_pending[i]) {
397 target_ulong va = env->vstore[i].va;
398 int size = env->vstore[i].size;
399 for (int j = 0; j < size; j++) {
400 if (test_bit(j, env->vstore[i].mask)) {
401 probe_write(env, va + j, 1, mmu_idx, retaddr);
402 }
403 }
404 }
405 }
406
407 /* Scatter store */
408 if (env->vtcm_pending) {
409 if (env->vtcm_log.op) {
410 /* Need to perform the scatter read/modify/write at commit time */
411 if (env->vtcm_log.op_size == 2) {
412 SCATTER_OP_PROBE_MEM(size2u_t, mmu_idx, retaddr);
413 } else if (env->vtcm_log.op_size == 4) {
414 /* Word Scatter += */
415 SCATTER_OP_PROBE_MEM(size4u_t, mmu_idx, retaddr);
416 } else {
417 g_assert_not_reached();
418 }
419 } else {
420 for (int i = 0; i < sizeof(MMVector); i++) {
421 if (test_bit(i, env->vtcm_log.mask)) {
422 probe_write(env, env->vtcm_log.va[i], 1, mmu_idx, retaddr);
423 }
424
425 }
426 }
427 }
428 }
429
HELPER(probe_hvx_stores)430 void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx)
431 {
432 uintptr_t retaddr = GETPC();
433 probe_hvx_stores(env, mmu_idx, retaddr);
434 }
435
HELPER(probe_pkt_scalar_hvx_stores)436 void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask)
437 {
438 bool has_st0 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0);
439 bool has_st1 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1);
440 bool has_hvx_stores =
441 FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_HVX_STORES);
442 bool s0_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED);
443 bool s1_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED);
444 int mmu_idx = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX);
445 uintptr_t ra = GETPC();
446
447 if (has_st0) {
448 probe_store(env, 0, mmu_idx, s0_is_pred, ra);
449 }
450 if (has_st1) {
451 probe_store(env, 1, mmu_idx, s1_is_pred, ra);
452 }
453 if (has_hvx_stores) {
454 probe_hvx_stores(env, mmu_idx, ra);
455 }
456 }
457
458 #ifndef CONFIG_HEXAGON_IDEF_PARSER
459 /*
460 * mem_noshuf
461 * Section 5.5 of the Hexagon V67 Programmer's Reference Manual
462 *
463 * If the load is in slot 0 and there is a store in slot1 (that
464 * wasn't cancelled), we have to do the store first.
465 */
check_noshuf(CPUHexagonState * env,bool pkt_has_store_s1,uint32_t slot,target_ulong vaddr,int size,uintptr_t ra)466 static void check_noshuf(CPUHexagonState *env, bool pkt_has_store_s1,
467 uint32_t slot, target_ulong vaddr, int size,
468 uintptr_t ra)
469 {
470 if (slot == 0 && pkt_has_store_s1 &&
471 ((env->slot_cancelled & (1 << 1)) == 0)) {
472 probe_read(env, vaddr, size, MMU_USER_IDX, ra);
473 commit_store(env, 1, ra);
474 }
475 }
476 #endif
477
478 /* Floating point */
HELPER(conv_sf2df)479 float64 HELPER(conv_sf2df)(CPUHexagonState *env, float32 RsV)
480 {
481 float64 out_f64;
482 arch_fpop_start(env);
483 out_f64 = float32_to_float64(RsV, &env->fp_status);
484 arch_fpop_end(env);
485 return out_f64;
486 }
487
HELPER(conv_df2sf)488 float32 HELPER(conv_df2sf)(CPUHexagonState *env, float64 RssV)
489 {
490 float32 out_f32;
491 arch_fpop_start(env);
492 out_f32 = float64_to_float32(RssV, &env->fp_status);
493 arch_fpop_end(env);
494 return out_f32;
495 }
496
HELPER(conv_uw2sf)497 float32 HELPER(conv_uw2sf)(CPUHexagonState *env, int32_t RsV)
498 {
499 float32 RdV;
500 arch_fpop_start(env);
501 RdV = uint32_to_float32(RsV, &env->fp_status);
502 arch_fpop_end(env);
503 return RdV;
504 }
505
HELPER(conv_uw2df)506 float64 HELPER(conv_uw2df)(CPUHexagonState *env, int32_t RsV)
507 {
508 float64 RddV;
509 arch_fpop_start(env);
510 RddV = uint32_to_float64(RsV, &env->fp_status);
511 arch_fpop_end(env);
512 return RddV;
513 }
514
HELPER(conv_w2sf)515 float32 HELPER(conv_w2sf)(CPUHexagonState *env, int32_t RsV)
516 {
517 float32 RdV;
518 arch_fpop_start(env);
519 RdV = int32_to_float32(RsV, &env->fp_status);
520 arch_fpop_end(env);
521 return RdV;
522 }
523
HELPER(conv_w2df)524 float64 HELPER(conv_w2df)(CPUHexagonState *env, int32_t RsV)
525 {
526 float64 RddV;
527 arch_fpop_start(env);
528 RddV = int32_to_float64(RsV, &env->fp_status);
529 arch_fpop_end(env);
530 return RddV;
531 }
532
HELPER(conv_ud2sf)533 float32 HELPER(conv_ud2sf)(CPUHexagonState *env, int64_t RssV)
534 {
535 float32 RdV;
536 arch_fpop_start(env);
537 RdV = uint64_to_float32(RssV, &env->fp_status);
538 arch_fpop_end(env);
539 return RdV;
540 }
541
HELPER(conv_ud2df)542 float64 HELPER(conv_ud2df)(CPUHexagonState *env, int64_t RssV)
543 {
544 float64 RddV;
545 arch_fpop_start(env);
546 RddV = uint64_to_float64(RssV, &env->fp_status);
547 arch_fpop_end(env);
548 return RddV;
549 }
550
HELPER(conv_d2sf)551 float32 HELPER(conv_d2sf)(CPUHexagonState *env, int64_t RssV)
552 {
553 float32 RdV;
554 arch_fpop_start(env);
555 RdV = int64_to_float32(RssV, &env->fp_status);
556 arch_fpop_end(env);
557 return RdV;
558 }
559
HELPER(conv_d2df)560 float64 HELPER(conv_d2df)(CPUHexagonState *env, int64_t RssV)
561 {
562 float64 RddV;
563 arch_fpop_start(env);
564 RddV = int64_to_float64(RssV, &env->fp_status);
565 arch_fpop_end(env);
566 return RddV;
567 }
568
HELPER(conv_sf2uw)569 uint32_t HELPER(conv_sf2uw)(CPUHexagonState *env, float32 RsV)
570 {
571 uint32_t RdV;
572 arch_fpop_start(env);
573 /* Hexagon checks the sign before rounding */
574 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
575 float_raise(float_flag_invalid, &env->fp_status);
576 RdV = 0;
577 } else {
578 RdV = float32_to_uint32(RsV, &env->fp_status);
579 }
580 arch_fpop_end(env);
581 return RdV;
582 }
583
HELPER(conv_sf2w)584 int32_t HELPER(conv_sf2w)(CPUHexagonState *env, float32 RsV)
585 {
586 int32_t RdV;
587 arch_fpop_start(env);
588 /* Hexagon returns -1 for NaN */
589 if (float32_is_any_nan(RsV)) {
590 float_raise(float_flag_invalid, &env->fp_status);
591 RdV = -1;
592 } else {
593 RdV = float32_to_int32(RsV, &env->fp_status);
594 }
595 arch_fpop_end(env);
596 return RdV;
597 }
598
HELPER(conv_sf2ud)599 uint64_t HELPER(conv_sf2ud)(CPUHexagonState *env, float32 RsV)
600 {
601 uint64_t RddV;
602 arch_fpop_start(env);
603 /* Hexagon checks the sign before rounding */
604 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
605 float_raise(float_flag_invalid, &env->fp_status);
606 RddV = 0;
607 } else {
608 RddV = float32_to_uint64(RsV, &env->fp_status);
609 }
610 arch_fpop_end(env);
611 return RddV;
612 }
613
HELPER(conv_sf2d)614 int64_t HELPER(conv_sf2d)(CPUHexagonState *env, float32 RsV)
615 {
616 int64_t RddV;
617 arch_fpop_start(env);
618 /* Hexagon returns -1 for NaN */
619 if (float32_is_any_nan(RsV)) {
620 float_raise(float_flag_invalid, &env->fp_status);
621 RddV = -1;
622 } else {
623 RddV = float32_to_int64(RsV, &env->fp_status);
624 }
625 arch_fpop_end(env);
626 return RddV;
627 }
628
HELPER(conv_df2uw)629 uint32_t HELPER(conv_df2uw)(CPUHexagonState *env, float64 RssV)
630 {
631 uint32_t RdV;
632 arch_fpop_start(env);
633 /* Hexagon checks the sign before rounding */
634 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
635 float_raise(float_flag_invalid, &env->fp_status);
636 RdV = 0;
637 } else {
638 RdV = float64_to_uint32(RssV, &env->fp_status);
639 }
640 arch_fpop_end(env);
641 return RdV;
642 }
643
HELPER(conv_df2w)644 int32_t HELPER(conv_df2w)(CPUHexagonState *env, float64 RssV)
645 {
646 int32_t RdV;
647 arch_fpop_start(env);
648 /* Hexagon returns -1 for NaN */
649 if (float64_is_any_nan(RssV)) {
650 float_raise(float_flag_invalid, &env->fp_status);
651 RdV = -1;
652 } else {
653 RdV = float64_to_int32(RssV, &env->fp_status);
654 }
655 arch_fpop_end(env);
656 return RdV;
657 }
658
HELPER(conv_df2ud)659 uint64_t HELPER(conv_df2ud)(CPUHexagonState *env, float64 RssV)
660 {
661 uint64_t RddV;
662 arch_fpop_start(env);
663 /* Hexagon checks the sign before rounding */
664 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
665 float_raise(float_flag_invalid, &env->fp_status);
666 RddV = 0;
667 } else {
668 RddV = float64_to_uint64(RssV, &env->fp_status);
669 }
670 arch_fpop_end(env);
671 return RddV;
672 }
673
HELPER(conv_df2d)674 int64_t HELPER(conv_df2d)(CPUHexagonState *env, float64 RssV)
675 {
676 int64_t RddV;
677 arch_fpop_start(env);
678 /* Hexagon returns -1 for NaN */
679 if (float64_is_any_nan(RssV)) {
680 float_raise(float_flag_invalid, &env->fp_status);
681 RddV = -1;
682 } else {
683 RddV = float64_to_int64(RssV, &env->fp_status);
684 }
685 arch_fpop_end(env);
686 return RddV;
687 }
688
HELPER(conv_sf2uw_chop)689 uint32_t HELPER(conv_sf2uw_chop)(CPUHexagonState *env, float32 RsV)
690 {
691 uint32_t RdV;
692 arch_fpop_start(env);
693 /* Hexagon checks the sign before rounding */
694 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
695 float_raise(float_flag_invalid, &env->fp_status);
696 RdV = 0;
697 } else {
698 RdV = float32_to_uint32_round_to_zero(RsV, &env->fp_status);
699 }
700 arch_fpop_end(env);
701 return RdV;
702 }
703
HELPER(conv_sf2w_chop)704 int32_t HELPER(conv_sf2w_chop)(CPUHexagonState *env, float32 RsV)
705 {
706 int32_t RdV;
707 arch_fpop_start(env);
708 /* Hexagon returns -1 for NaN */
709 if (float32_is_any_nan(RsV)) {
710 float_raise(float_flag_invalid, &env->fp_status);
711 RdV = -1;
712 } else {
713 RdV = float32_to_int32_round_to_zero(RsV, &env->fp_status);
714 }
715 arch_fpop_end(env);
716 return RdV;
717 }
718
HELPER(conv_sf2ud_chop)719 uint64_t HELPER(conv_sf2ud_chop)(CPUHexagonState *env, float32 RsV)
720 {
721 uint64_t RddV;
722 arch_fpop_start(env);
723 /* Hexagon checks the sign before rounding */
724 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
725 float_raise(float_flag_invalid, &env->fp_status);
726 RddV = 0;
727 } else {
728 RddV = float32_to_uint64_round_to_zero(RsV, &env->fp_status);
729 }
730 arch_fpop_end(env);
731 return RddV;
732 }
733
HELPER(conv_sf2d_chop)734 int64_t HELPER(conv_sf2d_chop)(CPUHexagonState *env, float32 RsV)
735 {
736 int64_t RddV;
737 arch_fpop_start(env);
738 /* Hexagon returns -1 for NaN */
739 if (float32_is_any_nan(RsV)) {
740 float_raise(float_flag_invalid, &env->fp_status);
741 RddV = -1;
742 } else {
743 RddV = float32_to_int64_round_to_zero(RsV, &env->fp_status);
744 }
745 arch_fpop_end(env);
746 return RddV;
747 }
748
HELPER(conv_df2uw_chop)749 uint32_t HELPER(conv_df2uw_chop)(CPUHexagonState *env, float64 RssV)
750 {
751 uint32_t RdV;
752 arch_fpop_start(env);
753 /* Hexagon checks the sign before rounding */
754 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
755 float_raise(float_flag_invalid, &env->fp_status);
756 RdV = 0;
757 } else {
758 RdV = float64_to_uint32_round_to_zero(RssV, &env->fp_status);
759 }
760 arch_fpop_end(env);
761 return RdV;
762 }
763
HELPER(conv_df2w_chop)764 int32_t HELPER(conv_df2w_chop)(CPUHexagonState *env, float64 RssV)
765 {
766 int32_t RdV;
767 arch_fpop_start(env);
768 /* Hexagon returns -1 for NaN */
769 if (float64_is_any_nan(RssV)) {
770 float_raise(float_flag_invalid, &env->fp_status);
771 RdV = -1;
772 } else {
773 RdV = float64_to_int32_round_to_zero(RssV, &env->fp_status);
774 }
775 arch_fpop_end(env);
776 return RdV;
777 }
778
HELPER(conv_df2ud_chop)779 uint64_t HELPER(conv_df2ud_chop)(CPUHexagonState *env, float64 RssV)
780 {
781 uint64_t RddV;
782 arch_fpop_start(env);
783 /* Hexagon checks the sign before rounding */
784 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
785 float_raise(float_flag_invalid, &env->fp_status);
786 RddV = 0;
787 } else {
788 RddV = float64_to_uint64_round_to_zero(RssV, &env->fp_status);
789 }
790 arch_fpop_end(env);
791 return RddV;
792 }
793
HELPER(conv_df2d_chop)794 int64_t HELPER(conv_df2d_chop)(CPUHexagonState *env, float64 RssV)
795 {
796 int64_t RddV;
797 arch_fpop_start(env);
798 /* Hexagon returns -1 for NaN */
799 if (float64_is_any_nan(RssV)) {
800 float_raise(float_flag_invalid, &env->fp_status);
801 RddV = -1;
802 } else {
803 RddV = float64_to_int64_round_to_zero(RssV, &env->fp_status);
804 }
805 arch_fpop_end(env);
806 return RddV;
807 }
808
HELPER(sfadd)809 float32 HELPER(sfadd)(CPUHexagonState *env, float32 RsV, float32 RtV)
810 {
811 float32 RdV;
812 arch_fpop_start(env);
813 RdV = float32_add(RsV, RtV, &env->fp_status);
814 arch_fpop_end(env);
815 return RdV;
816 }
817
HELPER(sfsub)818 float32 HELPER(sfsub)(CPUHexagonState *env, float32 RsV, float32 RtV)
819 {
820 float32 RdV;
821 arch_fpop_start(env);
822 RdV = float32_sub(RsV, RtV, &env->fp_status);
823 arch_fpop_end(env);
824 return RdV;
825 }
826
HELPER(sfcmpeq)827 int32_t HELPER(sfcmpeq)(CPUHexagonState *env, float32 RsV, float32 RtV)
828 {
829 int32_t PdV;
830 arch_fpop_start(env);
831 PdV = f8BITSOF(float32_eq_quiet(RsV, RtV, &env->fp_status));
832 arch_fpop_end(env);
833 return PdV;
834 }
835
HELPER(sfcmpgt)836 int32_t HELPER(sfcmpgt)(CPUHexagonState *env, float32 RsV, float32 RtV)
837 {
838 int cmp;
839 int32_t PdV;
840 arch_fpop_start(env);
841 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status);
842 PdV = f8BITSOF(cmp == float_relation_greater);
843 arch_fpop_end(env);
844 return PdV;
845 }
846
HELPER(sfcmpge)847 int32_t HELPER(sfcmpge)(CPUHexagonState *env, float32 RsV, float32 RtV)
848 {
849 int cmp;
850 int32_t PdV;
851 arch_fpop_start(env);
852 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status);
853 PdV = f8BITSOF(cmp == float_relation_greater ||
854 cmp == float_relation_equal);
855 arch_fpop_end(env);
856 return PdV;
857 }
858
HELPER(sfcmpuo)859 int32_t HELPER(sfcmpuo)(CPUHexagonState *env, float32 RsV, float32 RtV)
860 {
861 int32_t PdV;
862 arch_fpop_start(env);
863 PdV = f8BITSOF(float32_unordered_quiet(RsV, RtV, &env->fp_status));
864 arch_fpop_end(env);
865 return PdV;
866 }
867
HELPER(sfmax)868 float32 HELPER(sfmax)(CPUHexagonState *env, float32 RsV, float32 RtV)
869 {
870 float32 RdV;
871 arch_fpop_start(env);
872 RdV = float32_maximum_number(RsV, RtV, &env->fp_status);
873 arch_fpop_end(env);
874 return RdV;
875 }
876
HELPER(sfmin)877 float32 HELPER(sfmin)(CPUHexagonState *env, float32 RsV, float32 RtV)
878 {
879 float32 RdV;
880 arch_fpop_start(env);
881 RdV = float32_minimum_number(RsV, RtV, &env->fp_status);
882 arch_fpop_end(env);
883 return RdV;
884 }
885
HELPER(sfclass)886 int32_t HELPER(sfclass)(CPUHexagonState *env, float32 RsV, int32_t uiV)
887 {
888 int32_t PdV = 0;
889 arch_fpop_start(env);
890 if (fGETBIT(0, uiV) && float32_is_zero(RsV)) {
891 PdV = 0xff;
892 }
893 if (fGETBIT(1, uiV) && float32_is_normal(RsV)) {
894 PdV = 0xff;
895 }
896 if (fGETBIT(2, uiV) && float32_is_denormal(RsV)) {
897 PdV = 0xff;
898 }
899 if (fGETBIT(3, uiV) && float32_is_infinity(RsV)) {
900 PdV = 0xff;
901 }
902 if (fGETBIT(4, uiV) && float32_is_any_nan(RsV)) {
903 PdV = 0xff;
904 }
905 set_float_exception_flags(0, &env->fp_status);
906 arch_fpop_end(env);
907 return PdV;
908 }
909
HELPER(sffixupn)910 float32 HELPER(sffixupn)(CPUHexagonState *env, float32 RsV, float32 RtV)
911 {
912 float32 RdV = 0;
913 int adjust;
914 arch_fpop_start(env);
915 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status);
916 RdV = RsV;
917 arch_fpop_end(env);
918 return RdV;
919 }
920
HELPER(sffixupd)921 float32 HELPER(sffixupd)(CPUHexagonState *env, float32 RsV, float32 RtV)
922 {
923 float32 RdV = 0;
924 int adjust;
925 arch_fpop_start(env);
926 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status);
927 RdV = RtV;
928 arch_fpop_end(env);
929 return RdV;
930 }
931
HELPER(sffixupr)932 float32 HELPER(sffixupr)(CPUHexagonState *env, float32 RsV)
933 {
934 float32 RdV = 0;
935 int adjust;
936 arch_fpop_start(env);
937 arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status);
938 RdV = RsV;
939 arch_fpop_end(env);
940 return RdV;
941 }
942
HELPER(dfadd)943 float64 HELPER(dfadd)(CPUHexagonState *env, float64 RssV, float64 RttV)
944 {
945 float64 RddV;
946 arch_fpop_start(env);
947 RddV = float64_add(RssV, RttV, &env->fp_status);
948 arch_fpop_end(env);
949 return RddV;
950 }
951
HELPER(dfsub)952 float64 HELPER(dfsub)(CPUHexagonState *env, float64 RssV, float64 RttV)
953 {
954 float64 RddV;
955 arch_fpop_start(env);
956 RddV = float64_sub(RssV, RttV, &env->fp_status);
957 arch_fpop_end(env);
958 return RddV;
959 }
960
HELPER(dfmax)961 float64 HELPER(dfmax)(CPUHexagonState *env, float64 RssV, float64 RttV)
962 {
963 float64 RddV;
964 arch_fpop_start(env);
965 RddV = float64_maximum_number(RssV, RttV, &env->fp_status);
966 arch_fpop_end(env);
967 return RddV;
968 }
969
HELPER(dfmin)970 float64 HELPER(dfmin)(CPUHexagonState *env, float64 RssV, float64 RttV)
971 {
972 float64 RddV;
973 arch_fpop_start(env);
974 RddV = float64_minimum_number(RssV, RttV, &env->fp_status);
975 arch_fpop_end(env);
976 return RddV;
977 }
978
HELPER(dfcmpeq)979 int32_t HELPER(dfcmpeq)(CPUHexagonState *env, float64 RssV, float64 RttV)
980 {
981 int32_t PdV;
982 arch_fpop_start(env);
983 PdV = f8BITSOF(float64_eq_quiet(RssV, RttV, &env->fp_status));
984 arch_fpop_end(env);
985 return PdV;
986 }
987
HELPER(dfcmpgt)988 int32_t HELPER(dfcmpgt)(CPUHexagonState *env, float64 RssV, float64 RttV)
989 {
990 int cmp;
991 int32_t PdV;
992 arch_fpop_start(env);
993 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status);
994 PdV = f8BITSOF(cmp == float_relation_greater);
995 arch_fpop_end(env);
996 return PdV;
997 }
998
HELPER(dfcmpge)999 int32_t HELPER(dfcmpge)(CPUHexagonState *env, float64 RssV, float64 RttV)
1000 {
1001 int cmp;
1002 int32_t PdV;
1003 arch_fpop_start(env);
1004 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status);
1005 PdV = f8BITSOF(cmp == float_relation_greater ||
1006 cmp == float_relation_equal);
1007 arch_fpop_end(env);
1008 return PdV;
1009 }
1010
HELPER(dfcmpuo)1011 int32_t HELPER(dfcmpuo)(CPUHexagonState *env, float64 RssV, float64 RttV)
1012 {
1013 int32_t PdV;
1014 arch_fpop_start(env);
1015 PdV = f8BITSOF(float64_unordered_quiet(RssV, RttV, &env->fp_status));
1016 arch_fpop_end(env);
1017 return PdV;
1018 }
1019
HELPER(dfclass)1020 int32_t HELPER(dfclass)(CPUHexagonState *env, float64 RssV, int32_t uiV)
1021 {
1022 int32_t PdV = 0;
1023 arch_fpop_start(env);
1024 if (fGETBIT(0, uiV) && float64_is_zero(RssV)) {
1025 PdV = 0xff;
1026 }
1027 if (fGETBIT(1, uiV) && float64_is_normal(RssV)) {
1028 PdV = 0xff;
1029 }
1030 if (fGETBIT(2, uiV) && float64_is_denormal(RssV)) {
1031 PdV = 0xff;
1032 }
1033 if (fGETBIT(3, uiV) && float64_is_infinity(RssV)) {
1034 PdV = 0xff;
1035 }
1036 if (fGETBIT(4, uiV) && float64_is_any_nan(RssV)) {
1037 PdV = 0xff;
1038 }
1039 set_float_exception_flags(0, &env->fp_status);
1040 arch_fpop_end(env);
1041 return PdV;
1042 }
1043
HELPER(sfmpy)1044 float32 HELPER(sfmpy)(CPUHexagonState *env, float32 RsV, float32 RtV)
1045 {
1046 float32 RdV;
1047 arch_fpop_start(env);
1048 RdV = float32_mul(RsV, RtV, &env->fp_status);
1049 arch_fpop_end(env);
1050 return RdV;
1051 }
1052
HELPER(sffma)1053 float32 HELPER(sffma)(CPUHexagonState *env, float32 RxV,
1054 float32 RsV, float32 RtV)
1055 {
1056 arch_fpop_start(env);
1057 RxV = float32_muladd(RsV, RtV, RxV, 0, &env->fp_status);
1058 arch_fpop_end(env);
1059 return RxV;
1060 }
1061
HELPER(sffma_sc)1062 float32 HELPER(sffma_sc)(CPUHexagonState *env, float32 RxV,
1063 float32 RsV, float32 RtV, float32 PuV)
1064 {
1065 arch_fpop_start(env);
1066 RxV = float32_muladd_scalbn(RsV, RtV, RxV, fSXTN(8, 64, PuV),
1067 float_muladd_suppress_add_product_zero,
1068 &env->fp_status);
1069 arch_fpop_end(env);
1070 return RxV;
1071 }
1072
HELPER(sffms)1073 float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV,
1074 float32 RsV, float32 RtV)
1075 {
1076 arch_fpop_start(env);
1077 RxV = float32_muladd(RsV, RtV, RxV, float_muladd_negate_product,
1078 &env->fp_status);
1079 arch_fpop_end(env);
1080 return RxV;
1081 }
1082
do_sffma_lib(CPUHexagonState * env,float32 RxV,float32 RsV,float32 RtV,int negate)1083 static float32 do_sffma_lib(CPUHexagonState *env, float32 RxV,
1084 float32 RsV, float32 RtV, int negate)
1085 {
1086 int flags;
1087
1088 arch_fpop_start(env);
1089
1090 set_float_rounding_mode(float_round_nearest_even_max, &env->fp_status);
1091 RxV = float32_muladd(RsV, RtV, RxV,
1092 negate | float_muladd_suppress_add_product_zero,
1093 &env->fp_status);
1094
1095 flags = get_float_exception_flags(&env->fp_status);
1096 if (flags) {
1097 /* Flags are suppressed by this instruction. */
1098 set_float_exception_flags(0, &env->fp_status);
1099
1100 /* Return 0 for Inf - Inf. */
1101 if (flags & float_flag_invalid_isi) {
1102 RxV = 0;
1103 }
1104 }
1105
1106 arch_fpop_end(env);
1107 return RxV;
1108 }
1109
HELPER(sffma_lib)1110 float32 HELPER(sffma_lib)(CPUHexagonState *env, float32 RxV,
1111 float32 RsV, float32 RtV)
1112 {
1113 return do_sffma_lib(env, RxV, RsV, RtV, 0);
1114 }
1115
HELPER(sffms_lib)1116 float32 HELPER(sffms_lib)(CPUHexagonState *env, float32 RxV,
1117 float32 RsV, float32 RtV)
1118 {
1119 return do_sffma_lib(env, RxV, RsV, RtV, float_muladd_negate_product);
1120 }
1121
HELPER(dfmpyfix)1122 float64 HELPER(dfmpyfix)(CPUHexagonState *env, float64 RssV, float64 RttV)
1123 {
1124 int64_t RddV;
1125 arch_fpop_start(env);
1126 if (float64_is_denormal(RssV) &&
1127 (float64_getexp(RttV) >= 512) &&
1128 float64_is_normal(RttV)) {
1129 RddV = float64_mul(RssV, make_float64(0x4330000000000000),
1130 &env->fp_status);
1131 } else if (float64_is_denormal(RttV) &&
1132 (float64_getexp(RssV) >= 512) &&
1133 float64_is_normal(RssV)) {
1134 RddV = float64_mul(RssV, make_float64(0x3cb0000000000000),
1135 &env->fp_status);
1136 } else {
1137 RddV = RssV;
1138 }
1139 arch_fpop_end(env);
1140 return RddV;
1141 }
1142
HELPER(dfmpyhh)1143 float64 HELPER(dfmpyhh)(CPUHexagonState *env, float64 RxxV,
1144 float64 RssV, float64 RttV)
1145 {
1146 arch_fpop_start(env);
1147 RxxV = internal_mpyhh(RssV, RttV, RxxV, &env->fp_status);
1148 arch_fpop_end(env);
1149 return RxxV;
1150 }
1151
1152 /* Histogram instructions */
1153
HELPER(vhist)1154 void HELPER(vhist)(CPUHexagonState *env)
1155 {
1156 MMVector *input = &env->tmp_VRegs[0];
1157
1158 for (int lane = 0; lane < 8; lane++) {
1159 for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
1160 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
1161 unsigned char regno = value >> 3;
1162 unsigned char element = value & 7;
1163
1164 env->VRegs[regno].uh[(sizeof(MMVector) / 16) * lane + element]++;
1165 }
1166 }
1167 }
1168
HELPER(vhistq)1169 void HELPER(vhistq)(CPUHexagonState *env)
1170 {
1171 MMVector *input = &env->tmp_VRegs[0];
1172
1173 for (int lane = 0; lane < 8; lane++) {
1174 for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
1175 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
1176 unsigned char regno = value >> 3;
1177 unsigned char element = value & 7;
1178
1179 if (fGETQBIT(env->qtmp, sizeof(MMVector) / 8 * lane + i)) {
1180 env->VRegs[regno].uh[
1181 (sizeof(MMVector) / 16) * lane + element]++;
1182 }
1183 }
1184 }
1185 }
1186
HELPER(vwhist256)1187 void HELPER(vwhist256)(CPUHexagonState *env)
1188 {
1189 MMVector *input = &env->tmp_VRegs[0];
1190
1191 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1192 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1193 unsigned int weight = fGETUBYTE(1, input->h[i]);
1194 unsigned int vindex = (bucket >> 3) & 0x1F;
1195 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1196
1197 env->VRegs[vindex].uh[elindex] =
1198 env->VRegs[vindex].uh[elindex] + weight;
1199 }
1200 }
1201
HELPER(vwhist256q)1202 void HELPER(vwhist256q)(CPUHexagonState *env)
1203 {
1204 MMVector *input = &env->tmp_VRegs[0];
1205
1206 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1207 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1208 unsigned int weight = fGETUBYTE(1, input->h[i]);
1209 unsigned int vindex = (bucket >> 3) & 0x1F;
1210 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1211
1212 if (fGETQBIT(env->qtmp, 2 * i)) {
1213 env->VRegs[vindex].uh[elindex] =
1214 env->VRegs[vindex].uh[elindex] + weight;
1215 }
1216 }
1217 }
1218
HELPER(vwhist256_sat)1219 void HELPER(vwhist256_sat)(CPUHexagonState *env)
1220 {
1221 MMVector *input = &env->tmp_VRegs[0];
1222
1223 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1224 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1225 unsigned int weight = fGETUBYTE(1, input->h[i]);
1226 unsigned int vindex = (bucket >> 3) & 0x1F;
1227 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1228
1229 env->VRegs[vindex].uh[elindex] =
1230 fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
1231 }
1232 }
1233
HELPER(vwhist256q_sat)1234 void HELPER(vwhist256q_sat)(CPUHexagonState *env)
1235 {
1236 MMVector *input = &env->tmp_VRegs[0];
1237
1238 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1239 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1240 unsigned int weight = fGETUBYTE(1, input->h[i]);
1241 unsigned int vindex = (bucket >> 3) & 0x1F;
1242 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1243
1244 if (fGETQBIT(env->qtmp, 2 * i)) {
1245 env->VRegs[vindex].uh[elindex] =
1246 fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
1247 }
1248 }
1249 }
1250
HELPER(vwhist128)1251 void HELPER(vwhist128)(CPUHexagonState *env)
1252 {
1253 MMVector *input = &env->tmp_VRegs[0];
1254
1255 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1256 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1257 unsigned int weight = fGETUBYTE(1, input->h[i]);
1258 unsigned int vindex = (bucket >> 3) & 0x1F;
1259 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1260
1261 env->VRegs[vindex].uw[elindex] =
1262 env->VRegs[vindex].uw[elindex] + weight;
1263 }
1264 }
1265
HELPER(vwhist128q)1266 void HELPER(vwhist128q)(CPUHexagonState *env)
1267 {
1268 MMVector *input = &env->tmp_VRegs[0];
1269
1270 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1271 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1272 unsigned int weight = fGETUBYTE(1, input->h[i]);
1273 unsigned int vindex = (bucket >> 3) & 0x1F;
1274 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1275
1276 if (fGETQBIT(env->qtmp, 2 * i)) {
1277 env->VRegs[vindex].uw[elindex] =
1278 env->VRegs[vindex].uw[elindex] + weight;
1279 }
1280 }
1281 }
1282
HELPER(vwhist128m)1283 void HELPER(vwhist128m)(CPUHexagonState *env, int32_t uiV)
1284 {
1285 MMVector *input = &env->tmp_VRegs[0];
1286
1287 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1288 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1289 unsigned int weight = fGETUBYTE(1, input->h[i]);
1290 unsigned int vindex = (bucket >> 3) & 0x1F;
1291 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1292
1293 if ((bucket & 1) == uiV) {
1294 env->VRegs[vindex].uw[elindex] =
1295 env->VRegs[vindex].uw[elindex] + weight;
1296 }
1297 }
1298 }
1299
HELPER(vwhist128qm)1300 void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
1301 {
1302 MMVector *input = &env->tmp_VRegs[0];
1303
1304 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1305 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1306 unsigned int weight = fGETUBYTE(1, input->h[i]);
1307 unsigned int vindex = (bucket >> 3) & 0x1F;
1308 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1309
1310 if (((bucket & 1) == uiV) && fGETQBIT(env->qtmp, 2 * i)) {
1311 env->VRegs[vindex].uw[elindex] =
1312 env->VRegs[vindex].uw[elindex] + weight;
1313 }
1314 }
1315 }
1316
1317 /* These macros can be referenced in the generated helper functions */
1318 #define warn(...) /* Nothing */
1319 #define fatal(...) g_assert_not_reached();
1320
1321 #define BOGUS_HELPER(tag) \
1322 printf("ERROR: bogus helper: " #tag "\n")
1323
1324 #include "helper_funcs_generated.c.inc"
1325