1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "qemu/osdep.h"
19#include "qemu/log.h"
20#include "exec/exec-all.h"
21#include "exec/cpu_ldst.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
33#define SF_BIAS 127
34#define SF_MANTBITS 23
35
36
37static G_NORETURN
38void do_raise_exception_err(CPUHexagonState *env,
39 uint32_t exception,
40 uintptr_t pc)
41{
42 CPUState *cs = env_cpu(env);
43 qemu_log_mask(CPU_LOG_INT, "%s: %d\n", __func__, exception);
44 cs->exception_index = exception;
45 cpu_loop_exit_restore(cs, pc);
46}
47
48G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp)
49{
50 do_raise_exception_err(env, excp, 0);
51}
52
53static void log_reg_write(CPUHexagonState *env, int rnum,
54 target_ulong val, uint32_t slot)
55{
56 HEX_DEBUG_LOG("log_reg_write[%d] = " TARGET_FMT_ld " (0x" TARGET_FMT_lx ")",
57 rnum, val, val);
58 if (val == env->gpr[rnum]) {
59 HEX_DEBUG_LOG(" NO CHANGE");
60 }
61 HEX_DEBUG_LOG("\n");
62
63 env->new_value[rnum] = val;
64 if (HEX_DEBUG) {
65
66 env->reg_written[rnum] = 1;
67 }
68}
69
70static void log_pred_write(CPUHexagonState *env, int pnum, target_ulong val)
71{
72 HEX_DEBUG_LOG("log_pred_write[%d] = " TARGET_FMT_ld
73 " (0x" TARGET_FMT_lx ")\n",
74 pnum, val, val);
75
76
77 if (env->pred_written & (1 << pnum)) {
78 env->new_pred_value[pnum] &= val & 0xff;
79 } else {
80 env->new_pred_value[pnum] = val & 0xff;
81 env->pred_written |= 1 << pnum;
82 }
83}
84
85static void log_store32(CPUHexagonState *env, target_ulong addr,
86 target_ulong val, int width, int slot)
87{
88 HEX_DEBUG_LOG("log_store%d(0x" TARGET_FMT_lx
89 ", %" PRId32 " [0x08%" PRIx32 "])\n",
90 width, addr, val, val);
91 env->mem_log_stores[slot].va = addr;
92 env->mem_log_stores[slot].width = width;
93 env->mem_log_stores[slot].data32 = val;
94}
95
96static void log_store64(CPUHexagonState *env, target_ulong addr,
97 int64_t val, int width, int slot)
98{
99 HEX_DEBUG_LOG("log_store%d(0x" TARGET_FMT_lx
100 ", %" PRId64 " [0x016%" PRIx64 "])\n",
101 width, addr, val, val);
102 env->mem_log_stores[slot].va = addr;
103 env->mem_log_stores[slot].width = width;
104 env->mem_log_stores[slot].data64 = val;
105}
106
107static void write_new_pc(CPUHexagonState *env, target_ulong addr)
108{
109 HEX_DEBUG_LOG("write_new_pc(0x" TARGET_FMT_lx ")\n", addr);
110
111
112
113
114
115 if (env->branch_taken) {
116 HEX_DEBUG_LOG("INFO: multiple branches taken in same packet, "
117 "ignoring the second one\n");
118 } else {
119 fCHECK_PCALIGN(addr);
120 env->branch_taken = 1;
121 env->next_PC = addr;
122 }
123}
124
125
126void HELPER(debug_start_packet)(CPUHexagonState *env)
127{
128 HEX_DEBUG_LOG("Start packet: pc = 0x" TARGET_FMT_lx "\n",
129 env->gpr[HEX_REG_PC]);
130
131 for (int i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
132 env->reg_written[i] = 0;
133 }
134}
135
136
137void HELPER(debug_check_store_width)(CPUHexagonState *env, int slot, int check)
138{
139 if (env->mem_log_stores[slot].width != check) {
140 HEX_DEBUG_LOG("ERROR: %d != %d\n",
141 env->mem_log_stores[slot].width, check);
142 g_assert_not_reached();
143 }
144}
145
146void HELPER(commit_store)(CPUHexagonState *env, int slot_num)
147{
148 uintptr_t ra = GETPC();
149 uint8_t width = env->mem_log_stores[slot_num].width;
150 target_ulong va = env->mem_log_stores[slot_num].va;
151
152 switch (width) {
153 case 1:
154 cpu_stb_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
155 break;
156 case 2:
157 cpu_stw_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
158 break;
159 case 4:
160 cpu_stl_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
161 break;
162 case 8:
163 cpu_stq_data_ra(env, va, env->mem_log_stores[slot_num].data64, ra);
164 break;
165 default:
166 g_assert_not_reached();
167 }
168}
169
170void HELPER(gather_store)(CPUHexagonState *env, uint32_t addr, int slot)
171{
172 mem_gather_store(env, addr, slot);
173}
174
175void HELPER(commit_hvx_stores)(CPUHexagonState *env)
176{
177 uintptr_t ra = GETPC();
178 int i;
179
180
181 for (i = 0; i < VSTORES_MAX; i++) {
182 if (env->vstore_pending[i]) {
183 env->vstore_pending[i] = 0;
184 target_ulong va = env->vstore[i].va;
185 int size = env->vstore[i].size;
186 for (int j = 0; j < size; j++) {
187 if (test_bit(j, env->vstore[i].mask)) {
188 cpu_stb_data_ra(env, va + j, env->vstore[i].data.ub[j], ra);
189 }
190 }
191 }
192 }
193
194
195 if (env->vtcm_pending) {
196 env->vtcm_pending = false;
197 if (env->vtcm_log.op) {
198
199 if (env->vtcm_log.op_size == 2) {
200 SCATTER_OP_WRITE_TO_MEM(uint16_t);
201 } else if (env->vtcm_log.op_size == 4) {
202
203 SCATTER_OP_WRITE_TO_MEM(uint32_t);
204 } else {
205 g_assert_not_reached();
206 }
207 } else {
208 for (i = 0; i < sizeof(MMVector); i++) {
209 if (test_bit(i, env->vtcm_log.mask)) {
210 cpu_stb_data_ra(env, env->vtcm_log.va[i],
211 env->vtcm_log.data.ub[i], ra);
212 clear_bit(i, env->vtcm_log.mask);
213 env->vtcm_log.data.ub[i] = 0;
214 }
215
216 }
217 }
218 }
219}
220
221static void print_store(CPUHexagonState *env, int slot)
222{
223 if (!(env->slot_cancelled & (1 << slot))) {
224 uint8_t width = env->mem_log_stores[slot].width;
225 if (width == 1) {
226 uint32_t data = env->mem_log_stores[slot].data32 & 0xff;
227 HEX_DEBUG_LOG("\tmemb[0x" TARGET_FMT_lx "] = %" PRId32
228 " (0x%02" PRIx32 ")\n",
229 env->mem_log_stores[slot].va, data, data);
230 } else if (width == 2) {
231 uint32_t data = env->mem_log_stores[slot].data32 & 0xffff;
232 HEX_DEBUG_LOG("\tmemh[0x" TARGET_FMT_lx "] = %" PRId32
233 " (0x%04" PRIx32 ")\n",
234 env->mem_log_stores[slot].va, data, data);
235 } else if (width == 4) {
236 uint32_t data = env->mem_log_stores[slot].data32;
237 HEX_DEBUG_LOG("\tmemw[0x" TARGET_FMT_lx "] = %" PRId32
238 " (0x%08" PRIx32 ")\n",
239 env->mem_log_stores[slot].va, data, data);
240 } else if (width == 8) {
241 HEX_DEBUG_LOG("\tmemd[0x" TARGET_FMT_lx "] = %" PRId64
242 " (0x%016" PRIx64 ")\n",
243 env->mem_log_stores[slot].va,
244 env->mem_log_stores[slot].data64,
245 env->mem_log_stores[slot].data64);
246 } else {
247 HEX_DEBUG_LOG("\tBad store width %d\n", width);
248 g_assert_not_reached();
249 }
250 }
251}
252
253
254void HELPER(debug_commit_end)(CPUHexagonState *env, int has_st0, int has_st1)
255{
256 bool reg_printed = false;
257 bool pred_printed = false;
258 int i;
259
260 HEX_DEBUG_LOG("Packet committed: pc = 0x" TARGET_FMT_lx "\n",
261 env->this_PC);
262 HEX_DEBUG_LOG("slot_cancelled = %d\n", env->slot_cancelled);
263
264 for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
265 if (env->reg_written[i]) {
266 if (!reg_printed) {
267 HEX_DEBUG_LOG("Regs written\n");
268 reg_printed = true;
269 }
270 HEX_DEBUG_LOG("\tr%d = " TARGET_FMT_ld " (0x" TARGET_FMT_lx ")\n",
271 i, env->new_value[i], env->new_value[i]);
272 }
273 }
274
275 for (i = 0; i < NUM_PREGS; i++) {
276 if (env->pred_written & (1 << i)) {
277 if (!pred_printed) {
278 HEX_DEBUG_LOG("Predicates written\n");
279 pred_printed = true;
280 }
281 HEX_DEBUG_LOG("\tp%d = 0x" TARGET_FMT_lx "\n",
282 i, env->new_pred_value[i]);
283 }
284 }
285
286 if (has_st0 || has_st1) {
287 HEX_DEBUG_LOG("Stores\n");
288 if (has_st0) {
289 print_store(env, 0);
290 }
291 if (has_st1) {
292 print_store(env, 1);
293 }
294 }
295
296 HEX_DEBUG_LOG("Next PC = " TARGET_FMT_lx "\n", env->next_PC);
297 HEX_DEBUG_LOG("Exec counters: pkt = " TARGET_FMT_lx
298 ", insn = " TARGET_FMT_lx
299 ", hvx = " TARGET_FMT_lx "\n",
300 env->gpr[HEX_REG_QEMU_PKT_CNT],
301 env->gpr[HEX_REG_QEMU_INSN_CNT],
302 env->gpr[HEX_REG_QEMU_HVX_CNT]);
303
304}
305
306int32_t HELPER(fcircadd)(int32_t RxV, int32_t offset, int32_t M, int32_t CS)
307{
308 uint32_t K_const = extract32(M, 24, 4);
309 uint32_t length = extract32(M, 0, 17);
310 uint32_t new_ptr = RxV + offset;
311 uint32_t start_addr;
312 uint32_t end_addr;
313
314 if (K_const == 0 && length >= 4) {
315 start_addr = CS;
316 end_addr = start_addr + length;
317 } else {
318
319
320
321
322 int32_t mask = (1 << (K_const + 2)) - 1;
323 start_addr = RxV & (~mask);
324 end_addr = start_addr | length;
325 }
326
327 if (new_ptr >= end_addr) {
328 new_ptr -= length;
329 } else if (new_ptr < start_addr) {
330 new_ptr += length;
331 }
332
333 return new_ptr;
334}
335
336uint32_t HELPER(fbrev)(uint32_t addr)
337{
338
339
340
341 return deposit32(addr, 0, 16, revbit16(addr));
342}
343
344static float32 build_float32(uint8_t sign, uint32_t exp, uint32_t mant)
345{
346 return make_float32(
347 ((sign & 1) << 31) |
348 ((exp & 0xff) << SF_MANTBITS) |
349 (mant & ((1 << SF_MANTBITS) - 1)));
350}
351
352
353
354
355
356
357
358
359
360uint64_t HELPER(sfrecipa)(CPUHexagonState *env, float32 RsV, float32 RtV)
361{
362 int32_t PeV = 0;
363 float32 RdV;
364 int idx;
365 int adjust;
366 int mant;
367 int exp;
368
369 arch_fpop_start(env);
370 if (arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status)) {
371 PeV = adjust;
372 idx = (RtV >> 16) & 0x7f;
373 mant = (recip_lookup_table[idx] << 15) | 1;
374 exp = SF_BIAS - (float32_getexp(RtV) - SF_BIAS) - 1;
375 RdV = build_float32(extract32(RtV, 31, 1), exp, mant);
376 }
377 arch_fpop_end(env);
378 return ((uint64_t)RdV << 32) | PeV;
379}
380
381uint64_t HELPER(sfinvsqrta)(CPUHexagonState *env, float32 RsV)
382{
383 int PeV = 0;
384 float32 RdV;
385 int idx;
386 int adjust;
387 int mant;
388 int exp;
389
390 arch_fpop_start(env);
391 if (arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status)) {
392 PeV = adjust;
393 idx = (RsV >> 17) & 0x7f;
394 mant = (invsqrt_lookup_table[idx] << 15);
395 exp = SF_BIAS - ((float32_getexp(RsV) - SF_BIAS) >> 1) - 1;
396 RdV = build_float32(extract32(RsV, 31, 1), exp, mant);
397 }
398 arch_fpop_end(env);
399 return ((uint64_t)RdV << 32) | PeV;
400}
401
402int64_t HELPER(vacsh_val)(CPUHexagonState *env,
403 int64_t RxxV, int64_t RssV, int64_t RttV)
404{
405 for (int i = 0; i < 4; i++) {
406 int xv = sextract64(RxxV, i * 16, 16);
407 int sv = sextract64(RssV, i * 16, 16);
408 int tv = sextract64(RttV, i * 16, 16);
409 int max;
410 xv = xv + tv;
411 sv = sv - tv;
412 max = xv > sv ? xv : sv;
413
414 RxxV = deposit64(RxxV, i * 16, 16, fSATH(max));
415 }
416 return RxxV;
417}
418
419int32_t HELPER(vacsh_pred)(CPUHexagonState *env,
420 int64_t RxxV, int64_t RssV, int64_t RttV)
421{
422 int32_t PeV = 0;
423 for (int i = 0; i < 4; i++) {
424 int xv = sextract64(RxxV, i * 16, 16);
425 int sv = sextract64(RssV, i * 16, 16);
426 int tv = sextract64(RttV, i * 16, 16);
427 xv = xv + tv;
428 sv = sv - tv;
429 PeV = deposit32(PeV, i * 2, 1, (xv > sv));
430 PeV = deposit32(PeV, i * 2 + 1, 1, (xv > sv));
431 }
432 return PeV;
433}
434
435static void probe_store(CPUHexagonState *env, int slot, int mmu_idx)
436{
437 if (!(env->slot_cancelled & (1 << slot))) {
438 size1u_t width = env->mem_log_stores[slot].width;
439 target_ulong va = env->mem_log_stores[slot].va;
440 uintptr_t ra = GETPC();
441 probe_write(env, va, width, mmu_idx, ra);
442 }
443}
444
445
446
447
448
449void HELPER(probe_noshuf_load)(CPUHexagonState *env, target_ulong va,
450 int size, int mmu_idx)
451{
452 uintptr_t retaddr = GETPC();
453 probe_read(env, va, size, mmu_idx, retaddr);
454}
455
456
457void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int mmu_idx)
458{
459 probe_store(env, 0, mmu_idx);
460}
461
462void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx)
463{
464 uintptr_t retaddr = GETPC();
465 int i;
466
467
468 for (i = 0; i < VSTORES_MAX; i++) {
469 if (env->vstore_pending[i]) {
470 target_ulong va = env->vstore[i].va;
471 int size = env->vstore[i].size;
472 for (int j = 0; j < size; j++) {
473 if (test_bit(j, env->vstore[i].mask)) {
474 probe_write(env, va + j, 1, mmu_idx, retaddr);
475 }
476 }
477 }
478 }
479
480
481 if (env->vtcm_pending) {
482 if (env->vtcm_log.op) {
483
484 if (env->vtcm_log.op_size == 2) {
485 SCATTER_OP_PROBE_MEM(size2u_t, mmu_idx, retaddr);
486 } else if (env->vtcm_log.op_size == 4) {
487
488 SCATTER_OP_PROBE_MEM(size4u_t, mmu_idx, retaddr);
489 } else {
490 g_assert_not_reached();
491 }
492 } else {
493 for (int i = 0; i < sizeof(MMVector); i++) {
494 if (test_bit(i, env->vtcm_log.mask)) {
495 probe_write(env, env->vtcm_log.va[i], 1, mmu_idx, retaddr);
496 }
497
498 }
499 }
500 }
501}
502
503void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask,
504 int mmu_idx)
505{
506 bool has_st0 = (mask >> 0) & 1;
507 bool has_st1 = (mask >> 1) & 1;
508 bool has_hvx_stores = (mask >> 2) & 1;
509
510 if (has_st0) {
511 probe_store(env, 0, mmu_idx);
512 }
513 if (has_st1) {
514 probe_store(env, 1, mmu_idx);
515 }
516 if (has_hvx_stores) {
517 HELPER(probe_hvx_stores)(env, mmu_idx);
518 }
519}
520
521
522
523
524
525
526
527
528static void check_noshuf(CPUHexagonState *env, uint32_t slot,
529 target_ulong vaddr, int size)
530{
531 if (slot == 0 && env->pkt_has_store_s1 &&
532 ((env->slot_cancelled & (1 << 1)) == 0)) {
533 HELPER(probe_noshuf_load)(env, vaddr, size, MMU_USER_IDX);
534 HELPER(commit_store)(env, 1);
535 }
536}
537
538static uint8_t mem_load1(CPUHexagonState *env, uint32_t slot,
539 target_ulong vaddr)
540{
541 uintptr_t ra = GETPC();
542 check_noshuf(env, slot, vaddr, 1);
543 return cpu_ldub_data_ra(env, vaddr, ra);
544}
545
546static uint16_t mem_load2(CPUHexagonState *env, uint32_t slot,
547 target_ulong vaddr)
548{
549 uintptr_t ra = GETPC();
550 check_noshuf(env, slot, vaddr, 2);
551 return cpu_lduw_data_ra(env, vaddr, ra);
552}
553
554static uint32_t mem_load4(CPUHexagonState *env, uint32_t slot,
555 target_ulong vaddr)
556{
557 uintptr_t ra = GETPC();
558 check_noshuf(env, slot, vaddr, 4);
559 return cpu_ldl_data_ra(env, vaddr, ra);
560}
561
562static uint64_t mem_load8(CPUHexagonState *env, uint32_t slot,
563 target_ulong vaddr)
564{
565 uintptr_t ra = GETPC();
566 check_noshuf(env, slot, vaddr, 8);
567 return cpu_ldq_data_ra(env, vaddr, ra);
568}
569
570
571float64 HELPER(conv_sf2df)(CPUHexagonState *env, float32 RsV)
572{
573 float64 out_f64;
574 arch_fpop_start(env);
575 out_f64 = float32_to_float64(RsV, &env->fp_status);
576 arch_fpop_end(env);
577 return out_f64;
578}
579
580float32 HELPER(conv_df2sf)(CPUHexagonState *env, float64 RssV)
581{
582 float32 out_f32;
583 arch_fpop_start(env);
584 out_f32 = float64_to_float32(RssV, &env->fp_status);
585 arch_fpop_end(env);
586 return out_f32;
587}
588
589float32 HELPER(conv_uw2sf)(CPUHexagonState *env, int32_t RsV)
590{
591 float32 RdV;
592 arch_fpop_start(env);
593 RdV = uint32_to_float32(RsV, &env->fp_status);
594 arch_fpop_end(env);
595 return RdV;
596}
597
598float64 HELPER(conv_uw2df)(CPUHexagonState *env, int32_t RsV)
599{
600 float64 RddV;
601 arch_fpop_start(env);
602 RddV = uint32_to_float64(RsV, &env->fp_status);
603 arch_fpop_end(env);
604 return RddV;
605}
606
607float32 HELPER(conv_w2sf)(CPUHexagonState *env, int32_t RsV)
608{
609 float32 RdV;
610 arch_fpop_start(env);
611 RdV = int32_to_float32(RsV, &env->fp_status);
612 arch_fpop_end(env);
613 return RdV;
614}
615
616float64 HELPER(conv_w2df)(CPUHexagonState *env, int32_t RsV)
617{
618 float64 RddV;
619 arch_fpop_start(env);
620 RddV = int32_to_float64(RsV, &env->fp_status);
621 arch_fpop_end(env);
622 return RddV;
623}
624
625float32 HELPER(conv_ud2sf)(CPUHexagonState *env, int64_t RssV)
626{
627 float32 RdV;
628 arch_fpop_start(env);
629 RdV = uint64_to_float32(RssV, &env->fp_status);
630 arch_fpop_end(env);
631 return RdV;
632}
633
634float64 HELPER(conv_ud2df)(CPUHexagonState *env, int64_t RssV)
635{
636 float64 RddV;
637 arch_fpop_start(env);
638 RddV = uint64_to_float64(RssV, &env->fp_status);
639 arch_fpop_end(env);
640 return RddV;
641}
642
643float32 HELPER(conv_d2sf)(CPUHexagonState *env, int64_t RssV)
644{
645 float32 RdV;
646 arch_fpop_start(env);
647 RdV = int64_to_float32(RssV, &env->fp_status);
648 arch_fpop_end(env);
649 return RdV;
650}
651
652float64 HELPER(conv_d2df)(CPUHexagonState *env, int64_t RssV)
653{
654 float64 RddV;
655 arch_fpop_start(env);
656 RddV = int64_to_float64(RssV, &env->fp_status);
657 arch_fpop_end(env);
658 return RddV;
659}
660
661uint32_t HELPER(conv_sf2uw)(CPUHexagonState *env, float32 RsV)
662{
663 uint32_t RdV;
664 arch_fpop_start(env);
665
666 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV)) {
667 float_raise(float_flag_invalid, &env->fp_status);
668 RdV = 0;
669 } else {
670 RdV = float32_to_uint32(RsV, &env->fp_status);
671 }
672 arch_fpop_end(env);
673 return RdV;
674}
675
676int32_t HELPER(conv_sf2w)(CPUHexagonState *env, float32 RsV)
677{
678 int32_t RdV;
679 arch_fpop_start(env);
680
681 if (float32_is_any_nan(RsV)) {
682 float_raise(float_flag_invalid, &env->fp_status);
683 RdV = -1;
684 } else {
685 RdV = float32_to_int32(RsV, &env->fp_status);
686 }
687 arch_fpop_end(env);
688 return RdV;
689}
690
691uint64_t HELPER(conv_sf2ud)(CPUHexagonState *env, float32 RsV)
692{
693 uint64_t RddV;
694 arch_fpop_start(env);
695
696 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV)) {
697 float_raise(float_flag_invalid, &env->fp_status);
698 RddV = 0;
699 } else {
700 RddV = float32_to_uint64(RsV, &env->fp_status);
701 }
702 arch_fpop_end(env);
703 return RddV;
704}
705
706int64_t HELPER(conv_sf2d)(CPUHexagonState *env, float32 RsV)
707{
708 int64_t RddV;
709 arch_fpop_start(env);
710
711 if (float32_is_any_nan(RsV)) {
712 float_raise(float_flag_invalid, &env->fp_status);
713 RddV = -1;
714 } else {
715 RddV = float32_to_int64(RsV, &env->fp_status);
716 }
717 arch_fpop_end(env);
718 return RddV;
719}
720
721uint32_t HELPER(conv_df2uw)(CPUHexagonState *env, float64 RssV)
722{
723 uint32_t RdV;
724 arch_fpop_start(env);
725
726 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV)) {
727 float_raise(float_flag_invalid, &env->fp_status);
728 RdV = 0;
729 } else {
730 RdV = float64_to_uint32(RssV, &env->fp_status);
731 }
732 arch_fpop_end(env);
733 return RdV;
734}
735
736int32_t HELPER(conv_df2w)(CPUHexagonState *env, float64 RssV)
737{
738 int32_t RdV;
739 arch_fpop_start(env);
740
741 if (float64_is_any_nan(RssV)) {
742 float_raise(float_flag_invalid, &env->fp_status);
743 RdV = -1;
744 } else {
745 RdV = float64_to_int32(RssV, &env->fp_status);
746 }
747 arch_fpop_end(env);
748 return RdV;
749}
750
751uint64_t HELPER(conv_df2ud)(CPUHexagonState *env, float64 RssV)
752{
753 uint64_t RddV;
754 arch_fpop_start(env);
755
756 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV)) {
757 float_raise(float_flag_invalid, &env->fp_status);
758 RddV = 0;
759 } else {
760 RddV = float64_to_uint64(RssV, &env->fp_status);
761 }
762 arch_fpop_end(env);
763 return RddV;
764}
765
766int64_t HELPER(conv_df2d)(CPUHexagonState *env, float64 RssV)
767{
768 int64_t RddV;
769 arch_fpop_start(env);
770
771 if (float64_is_any_nan(RssV)) {
772 float_raise(float_flag_invalid, &env->fp_status);
773 RddV = -1;
774 } else {
775 RddV = float64_to_int64(RssV, &env->fp_status);
776 }
777 arch_fpop_end(env);
778 return RddV;
779}
780
781uint32_t HELPER(conv_sf2uw_chop)(CPUHexagonState *env, float32 RsV)
782{
783 uint32_t RdV;
784 arch_fpop_start(env);
785
786 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV)) {
787 float_raise(float_flag_invalid, &env->fp_status);
788 RdV = 0;
789 } else {
790 RdV = float32_to_uint32_round_to_zero(RsV, &env->fp_status);
791 }
792 arch_fpop_end(env);
793 return RdV;
794}
795
796int32_t HELPER(conv_sf2w_chop)(CPUHexagonState *env, float32 RsV)
797{
798 int32_t RdV;
799 arch_fpop_start(env);
800
801 if (float32_is_any_nan(RsV)) {
802 float_raise(float_flag_invalid, &env->fp_status);
803 RdV = -1;
804 } else {
805 RdV = float32_to_int32_round_to_zero(RsV, &env->fp_status);
806 }
807 arch_fpop_end(env);
808 return RdV;
809}
810
811uint64_t HELPER(conv_sf2ud_chop)(CPUHexagonState *env, float32 RsV)
812{
813 uint64_t RddV;
814 arch_fpop_start(env);
815
816 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV)) {
817 float_raise(float_flag_invalid, &env->fp_status);
818 RddV = 0;
819 } else {
820 RddV = float32_to_uint64_round_to_zero(RsV, &env->fp_status);
821 }
822 arch_fpop_end(env);
823 return RddV;
824}
825
826int64_t HELPER(conv_sf2d_chop)(CPUHexagonState *env, float32 RsV)
827{
828 int64_t RddV;
829 arch_fpop_start(env);
830
831 if (float32_is_any_nan(RsV)) {
832 float_raise(float_flag_invalid, &env->fp_status);
833 RddV = -1;
834 } else {
835 RddV = float32_to_int64_round_to_zero(RsV, &env->fp_status);
836 }
837 arch_fpop_end(env);
838 return RddV;
839}
840
841uint32_t HELPER(conv_df2uw_chop)(CPUHexagonState *env, float64 RssV)
842{
843 uint32_t RdV;
844 arch_fpop_start(env);
845
846 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV)) {
847 float_raise(float_flag_invalid, &env->fp_status);
848 RdV = 0;
849 } else {
850 RdV = float64_to_uint32_round_to_zero(RssV, &env->fp_status);
851 }
852 arch_fpop_end(env);
853 return RdV;
854}
855
856int32_t HELPER(conv_df2w_chop)(CPUHexagonState *env, float64 RssV)
857{
858 int32_t RdV;
859 arch_fpop_start(env);
860
861 if (float64_is_any_nan(RssV)) {
862 float_raise(float_flag_invalid, &env->fp_status);
863 RdV = -1;
864 } else {
865 RdV = float64_to_int32_round_to_zero(RssV, &env->fp_status);
866 }
867 arch_fpop_end(env);
868 return RdV;
869}
870
871uint64_t HELPER(conv_df2ud_chop)(CPUHexagonState *env, float64 RssV)
872{
873 uint64_t RddV;
874 arch_fpop_start(env);
875
876 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV)) {
877 float_raise(float_flag_invalid, &env->fp_status);
878 RddV = 0;
879 } else {
880 RddV = float64_to_uint64_round_to_zero(RssV, &env->fp_status);
881 }
882 arch_fpop_end(env);
883 return RddV;
884}
885
886int64_t HELPER(conv_df2d_chop)(CPUHexagonState *env, float64 RssV)
887{
888 int64_t RddV;
889 arch_fpop_start(env);
890
891 if (float64_is_any_nan(RssV)) {
892 float_raise(float_flag_invalid, &env->fp_status);
893 RddV = -1;
894 } else {
895 RddV = float64_to_int64_round_to_zero(RssV, &env->fp_status);
896 }
897 arch_fpop_end(env);
898 return RddV;
899}
900
901float32 HELPER(sfadd)(CPUHexagonState *env, float32 RsV, float32 RtV)
902{
903 float32 RdV;
904 arch_fpop_start(env);
905 RdV = float32_add(RsV, RtV, &env->fp_status);
906 arch_fpop_end(env);
907 return RdV;
908}
909
910float32 HELPER(sfsub)(CPUHexagonState *env, float32 RsV, float32 RtV)
911{
912 float32 RdV;
913 arch_fpop_start(env);
914 RdV = float32_sub(RsV, RtV, &env->fp_status);
915 arch_fpop_end(env);
916 return RdV;
917}
918
919int32_t HELPER(sfcmpeq)(CPUHexagonState *env, float32 RsV, float32 RtV)
920{
921 int32_t PdV;
922 arch_fpop_start(env);
923 PdV = f8BITSOF(float32_eq_quiet(RsV, RtV, &env->fp_status));
924 arch_fpop_end(env);
925 return PdV;
926}
927
928int32_t HELPER(sfcmpgt)(CPUHexagonState *env, float32 RsV, float32 RtV)
929{
930 int cmp;
931 int32_t PdV;
932 arch_fpop_start(env);
933 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status);
934 PdV = f8BITSOF(cmp == float_relation_greater);
935 arch_fpop_end(env);
936 return PdV;
937}
938
939int32_t HELPER(sfcmpge)(CPUHexagonState *env, float32 RsV, float32 RtV)
940{
941 int cmp;
942 int32_t PdV;
943 arch_fpop_start(env);
944 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status);
945 PdV = f8BITSOF(cmp == float_relation_greater ||
946 cmp == float_relation_equal);
947 arch_fpop_end(env);
948 return PdV;
949}
950
951int32_t HELPER(sfcmpuo)(CPUHexagonState *env, float32 RsV, float32 RtV)
952{
953 int32_t PdV;
954 arch_fpop_start(env);
955 PdV = f8BITSOF(float32_unordered_quiet(RsV, RtV, &env->fp_status));
956 arch_fpop_end(env);
957 return PdV;
958}
959
960float32 HELPER(sfmax)(CPUHexagonState *env, float32 RsV, float32 RtV)
961{
962 float32 RdV;
963 arch_fpop_start(env);
964 RdV = float32_maximum_number(RsV, RtV, &env->fp_status);
965 arch_fpop_end(env);
966 return RdV;
967}
968
969float32 HELPER(sfmin)(CPUHexagonState *env, float32 RsV, float32 RtV)
970{
971 float32 RdV;
972 arch_fpop_start(env);
973 RdV = float32_minimum_number(RsV, RtV, &env->fp_status);
974 arch_fpop_end(env);
975 return RdV;
976}
977
978int32_t HELPER(sfclass)(CPUHexagonState *env, float32 RsV, int32_t uiV)
979{
980 int32_t PdV = 0;
981 arch_fpop_start(env);
982 if (fGETBIT(0, uiV) && float32_is_zero(RsV)) {
983 PdV = 0xff;
984 }
985 if (fGETBIT(1, uiV) && float32_is_normal(RsV)) {
986 PdV = 0xff;
987 }
988 if (fGETBIT(2, uiV) && float32_is_denormal(RsV)) {
989 PdV = 0xff;
990 }
991 if (fGETBIT(3, uiV) && float32_is_infinity(RsV)) {
992 PdV = 0xff;
993 }
994 if (fGETBIT(4, uiV) && float32_is_any_nan(RsV)) {
995 PdV = 0xff;
996 }
997 set_float_exception_flags(0, &env->fp_status);
998 arch_fpop_end(env);
999 return PdV;
1000}
1001
1002float32 HELPER(sffixupn)(CPUHexagonState *env, float32 RsV, float32 RtV)
1003{
1004 float32 RdV = 0;
1005 int adjust;
1006 arch_fpop_start(env);
1007 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status);
1008 RdV = RsV;
1009 arch_fpop_end(env);
1010 return RdV;
1011}
1012
1013float32 HELPER(sffixupd)(CPUHexagonState *env, float32 RsV, float32 RtV)
1014{
1015 float32 RdV = 0;
1016 int adjust;
1017 arch_fpop_start(env);
1018 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status);
1019 RdV = RtV;
1020 arch_fpop_end(env);
1021 return RdV;
1022}
1023
1024float32 HELPER(sffixupr)(CPUHexagonState *env, float32 RsV)
1025{
1026 float32 RdV = 0;
1027 int adjust;
1028 arch_fpop_start(env);
1029 arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status);
1030 RdV = RsV;
1031 arch_fpop_end(env);
1032 return RdV;
1033}
1034
1035float64 HELPER(dfadd)(CPUHexagonState *env, float64 RssV, float64 RttV)
1036{
1037 float64 RddV;
1038 arch_fpop_start(env);
1039 RddV = float64_add(RssV, RttV, &env->fp_status);
1040 arch_fpop_end(env);
1041 return RddV;
1042}
1043
1044float64 HELPER(dfsub)(CPUHexagonState *env, float64 RssV, float64 RttV)
1045{
1046 float64 RddV;
1047 arch_fpop_start(env);
1048 RddV = float64_sub(RssV, RttV, &env->fp_status);
1049 arch_fpop_end(env);
1050 return RddV;
1051}
1052
1053float64 HELPER(dfmax)(CPUHexagonState *env, float64 RssV, float64 RttV)
1054{
1055 float64 RddV;
1056 arch_fpop_start(env);
1057 RddV = float64_maximum_number(RssV, RttV, &env->fp_status);
1058 arch_fpop_end(env);
1059 return RddV;
1060}
1061
1062float64 HELPER(dfmin)(CPUHexagonState *env, float64 RssV, float64 RttV)
1063{
1064 float64 RddV;
1065 arch_fpop_start(env);
1066 RddV = float64_minimum_number(RssV, RttV, &env->fp_status);
1067 arch_fpop_end(env);
1068 return RddV;
1069}
1070
1071int32_t HELPER(dfcmpeq)(CPUHexagonState *env, float64 RssV, float64 RttV)
1072{
1073 int32_t PdV;
1074 arch_fpop_start(env);
1075 PdV = f8BITSOF(float64_eq_quiet(RssV, RttV, &env->fp_status));
1076 arch_fpop_end(env);
1077 return PdV;
1078}
1079
1080int32_t HELPER(dfcmpgt)(CPUHexagonState *env, float64 RssV, float64 RttV)
1081{
1082 int cmp;
1083 int32_t PdV;
1084 arch_fpop_start(env);
1085 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status);
1086 PdV = f8BITSOF(cmp == float_relation_greater);
1087 arch_fpop_end(env);
1088 return PdV;
1089}
1090
1091int32_t HELPER(dfcmpge)(CPUHexagonState *env, float64 RssV, float64 RttV)
1092{
1093 int cmp;
1094 int32_t PdV;
1095 arch_fpop_start(env);
1096 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status);
1097 PdV = f8BITSOF(cmp == float_relation_greater ||
1098 cmp == float_relation_equal);
1099 arch_fpop_end(env);
1100 return PdV;
1101}
1102
1103int32_t HELPER(dfcmpuo)(CPUHexagonState *env, float64 RssV, float64 RttV)
1104{
1105 int32_t PdV;
1106 arch_fpop_start(env);
1107 PdV = f8BITSOF(float64_unordered_quiet(RssV, RttV, &env->fp_status));
1108 arch_fpop_end(env);
1109 return PdV;
1110}
1111
1112int32_t HELPER(dfclass)(CPUHexagonState *env, float64 RssV, int32_t uiV)
1113{
1114 int32_t PdV = 0;
1115 arch_fpop_start(env);
1116 if (fGETBIT(0, uiV) && float64_is_zero(RssV)) {
1117 PdV = 0xff;
1118 }
1119 if (fGETBIT(1, uiV) && float64_is_normal(RssV)) {
1120 PdV = 0xff;
1121 }
1122 if (fGETBIT(2, uiV) && float64_is_denormal(RssV)) {
1123 PdV = 0xff;
1124 }
1125 if (fGETBIT(3, uiV) && float64_is_infinity(RssV)) {
1126 PdV = 0xff;
1127 }
1128 if (fGETBIT(4, uiV) && float64_is_any_nan(RssV)) {
1129 PdV = 0xff;
1130 }
1131 set_float_exception_flags(0, &env->fp_status);
1132 arch_fpop_end(env);
1133 return PdV;
1134}
1135
1136float32 HELPER(sfmpy)(CPUHexagonState *env, float32 RsV, float32 RtV)
1137{
1138 float32 RdV;
1139 arch_fpop_start(env);
1140 RdV = internal_mpyf(RsV, RtV, &env->fp_status);
1141 arch_fpop_end(env);
1142 return RdV;
1143}
1144
1145float32 HELPER(sffma)(CPUHexagonState *env, float32 RxV,
1146 float32 RsV, float32 RtV)
1147{
1148 arch_fpop_start(env);
1149 RxV = internal_fmafx(RsV, RtV, RxV, 0, &env->fp_status);
1150 arch_fpop_end(env);
1151 return RxV;
1152}
1153
1154static bool is_zero_prod(float32 a, float32 b)
1155{
1156 return ((float32_is_zero(a) && is_finite(b)) ||
1157 (float32_is_zero(b) && is_finite(a)));
1158}
1159
1160static float32 check_nan(float32 dst, float32 x, float_status *fp_status)
1161{
1162 float32 ret = dst;
1163 if (float32_is_any_nan(x)) {
1164 if (extract32(x, 22, 1) == 0) {
1165 float_raise(float_flag_invalid, fp_status);
1166 }
1167 ret = make_float32(0xffffffff);
1168 }
1169 return ret;
1170}
1171
1172float32 HELPER(sffma_sc)(CPUHexagonState *env, float32 RxV,
1173 float32 RsV, float32 RtV, float32 PuV)
1174{
1175 size4s_t tmp;
1176 arch_fpop_start(env);
1177 RxV = check_nan(RxV, RxV, &env->fp_status);
1178 RxV = check_nan(RxV, RsV, &env->fp_status);
1179 RxV = check_nan(RxV, RtV, &env->fp_status);
1180 tmp = internal_fmafx(RsV, RtV, RxV, fSXTN(8, 64, PuV), &env->fp_status);
1181 if (!(float32_is_zero(RxV) && is_zero_prod(RsV, RtV))) {
1182 RxV = tmp;
1183 }
1184 arch_fpop_end(env);
1185 return RxV;
1186}
1187
1188float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV,
1189 float32 RsV, float32 RtV)
1190{
1191 float32 neg_RsV;
1192 arch_fpop_start(env);
1193 neg_RsV = float32_sub(float32_zero, RsV, &env->fp_status);
1194 RxV = internal_fmafx(neg_RsV, RtV, RxV, 0, &env->fp_status);
1195 arch_fpop_end(env);
1196 return RxV;
1197}
1198
1199static bool is_inf_prod(int32_t a, int32_t b)
1200{
1201 return (float32_is_infinity(a) && float32_is_infinity(b)) ||
1202 (float32_is_infinity(a) && is_finite(b) && !float32_is_zero(b)) ||
1203 (float32_is_infinity(b) && is_finite(a) && !float32_is_zero(a));
1204}
1205
1206float32 HELPER(sffma_lib)(CPUHexagonState *env, float32 RxV,
1207 float32 RsV, float32 RtV)
1208{
1209 bool infinp;
1210 bool infminusinf;
1211 float32 tmp;
1212
1213 arch_fpop_start(env);
1214 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1215 infminusinf = float32_is_infinity(RxV) &&
1216 is_inf_prod(RsV, RtV) &&
1217 (fGETBIT(31, RsV ^ RxV ^ RtV) != 0);
1218 infinp = float32_is_infinity(RxV) ||
1219 float32_is_infinity(RtV) ||
1220 float32_is_infinity(RsV);
1221 RxV = check_nan(RxV, RxV, &env->fp_status);
1222 RxV = check_nan(RxV, RsV, &env->fp_status);
1223 RxV = check_nan(RxV, RtV, &env->fp_status);
1224 tmp = internal_fmafx(RsV, RtV, RxV, 0, &env->fp_status);
1225 if (!(float32_is_zero(RxV) && is_zero_prod(RsV, RtV))) {
1226 RxV = tmp;
1227 }
1228 set_float_exception_flags(0, &env->fp_status);
1229 if (float32_is_infinity(RxV) && !infinp) {
1230 RxV = RxV - 1;
1231 }
1232 if (infminusinf) {
1233 RxV = 0;
1234 }
1235 arch_fpop_end(env);
1236 return RxV;
1237}
1238
1239float32 HELPER(sffms_lib)(CPUHexagonState *env, float32 RxV,
1240 float32 RsV, float32 RtV)
1241{
1242 bool infinp;
1243 bool infminusinf;
1244 float32 tmp;
1245
1246 arch_fpop_start(env);
1247 set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
1248 infminusinf = float32_is_infinity(RxV) &&
1249 is_inf_prod(RsV, RtV) &&
1250 (fGETBIT(31, RsV ^ RxV ^ RtV) == 0);
1251 infinp = float32_is_infinity(RxV) ||
1252 float32_is_infinity(RtV) ||
1253 float32_is_infinity(RsV);
1254 RxV = check_nan(RxV, RxV, &env->fp_status);
1255 RxV = check_nan(RxV, RsV, &env->fp_status);
1256 RxV = check_nan(RxV, RtV, &env->fp_status);
1257 float32 minus_RsV = float32_sub(float32_zero, RsV, &env->fp_status);
1258 tmp = internal_fmafx(minus_RsV, RtV, RxV, 0, &env->fp_status);
1259 if (!(float32_is_zero(RxV) && is_zero_prod(RsV, RtV))) {
1260 RxV = tmp;
1261 }
1262 set_float_exception_flags(0, &env->fp_status);
1263 if (float32_is_infinity(RxV) && !infinp) {
1264 RxV = RxV - 1;
1265 }
1266 if (infminusinf) {
1267 RxV = 0;
1268 }
1269 arch_fpop_end(env);
1270 return RxV;
1271}
1272
1273float64 HELPER(dfmpyfix)(CPUHexagonState *env, float64 RssV, float64 RttV)
1274{
1275 int64_t RddV;
1276 arch_fpop_start(env);
1277 if (float64_is_denormal(RssV) &&
1278 (float64_getexp(RttV) >= 512) &&
1279 float64_is_normal(RttV)) {
1280 RddV = float64_mul(RssV, make_float64(0x4330000000000000),
1281 &env->fp_status);
1282 } else if (float64_is_denormal(RttV) &&
1283 (float64_getexp(RssV) >= 512) &&
1284 float64_is_normal(RssV)) {
1285 RddV = float64_mul(RssV, make_float64(0x3cb0000000000000),
1286 &env->fp_status);
1287 } else {
1288 RddV = RssV;
1289 }
1290 arch_fpop_end(env);
1291 return RddV;
1292}
1293
1294float64 HELPER(dfmpyhh)(CPUHexagonState *env, float64 RxxV,
1295 float64 RssV, float64 RttV)
1296{
1297 arch_fpop_start(env);
1298 RxxV = internal_mpyhh(RssV, RttV, RxxV, &env->fp_status);
1299 arch_fpop_end(env);
1300 return RxxV;
1301}
1302
1303
1304
1305void HELPER(vhist)(CPUHexagonState *env)
1306{
1307 MMVector *input = &env->tmp_VRegs[0];
1308
1309 for (int lane = 0; lane < 8; lane++) {
1310 for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
1311 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
1312 unsigned char regno = value >> 3;
1313 unsigned char element = value & 7;
1314
1315 env->VRegs[regno].uh[(sizeof(MMVector) / 16) * lane + element]++;
1316 }
1317 }
1318}
1319
1320void HELPER(vhistq)(CPUHexagonState *env)
1321{
1322 MMVector *input = &env->tmp_VRegs[0];
1323
1324 for (int lane = 0; lane < 8; lane++) {
1325 for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
1326 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
1327 unsigned char regno = value >> 3;
1328 unsigned char element = value & 7;
1329
1330 if (fGETQBIT(env->qtmp, sizeof(MMVector) / 8 * lane + i)) {
1331 env->VRegs[regno].uh[
1332 (sizeof(MMVector) / 16) * lane + element]++;
1333 }
1334 }
1335 }
1336}
1337
1338void HELPER(vwhist256)(CPUHexagonState *env)
1339{
1340 MMVector *input = &env->tmp_VRegs[0];
1341
1342 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1343 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1344 unsigned int weight = fGETUBYTE(1, input->h[i]);
1345 unsigned int vindex = (bucket >> 3) & 0x1F;
1346 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1347
1348 env->VRegs[vindex].uh[elindex] =
1349 env->VRegs[vindex].uh[elindex] + weight;
1350 }
1351}
1352
1353void HELPER(vwhist256q)(CPUHexagonState *env)
1354{
1355 MMVector *input = &env->tmp_VRegs[0];
1356
1357 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1358 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1359 unsigned int weight = fGETUBYTE(1, input->h[i]);
1360 unsigned int vindex = (bucket >> 3) & 0x1F;
1361 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1362
1363 if (fGETQBIT(env->qtmp, 2 * i)) {
1364 env->VRegs[vindex].uh[elindex] =
1365 env->VRegs[vindex].uh[elindex] + weight;
1366 }
1367 }
1368}
1369
1370void HELPER(vwhist256_sat)(CPUHexagonState *env)
1371{
1372 MMVector *input = &env->tmp_VRegs[0];
1373
1374 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1375 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1376 unsigned int weight = fGETUBYTE(1, input->h[i]);
1377 unsigned int vindex = (bucket >> 3) & 0x1F;
1378 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1379
1380 env->VRegs[vindex].uh[elindex] =
1381 fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
1382 }
1383}
1384
1385void HELPER(vwhist256q_sat)(CPUHexagonState *env)
1386{
1387 MMVector *input = &env->tmp_VRegs[0];
1388
1389 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1390 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1391 unsigned int weight = fGETUBYTE(1, input->h[i]);
1392 unsigned int vindex = (bucket >> 3) & 0x1F;
1393 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1394
1395 if (fGETQBIT(env->qtmp, 2 * i)) {
1396 env->VRegs[vindex].uh[elindex] =
1397 fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
1398 }
1399 }
1400}
1401
1402void HELPER(vwhist128)(CPUHexagonState *env)
1403{
1404 MMVector *input = &env->tmp_VRegs[0];
1405
1406 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1407 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1408 unsigned int weight = fGETUBYTE(1, input->h[i]);
1409 unsigned int vindex = (bucket >> 3) & 0x1F;
1410 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1411
1412 env->VRegs[vindex].uw[elindex] =
1413 env->VRegs[vindex].uw[elindex] + weight;
1414 }
1415}
1416
1417void HELPER(vwhist128q)(CPUHexagonState *env)
1418{
1419 MMVector *input = &env->tmp_VRegs[0];
1420
1421 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1422 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1423 unsigned int weight = fGETUBYTE(1, input->h[i]);
1424 unsigned int vindex = (bucket >> 3) & 0x1F;
1425 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1426
1427 if (fGETQBIT(env->qtmp, 2 * i)) {
1428 env->VRegs[vindex].uw[elindex] =
1429 env->VRegs[vindex].uw[elindex] + weight;
1430 }
1431 }
1432}
1433
1434void HELPER(vwhist128m)(CPUHexagonState *env, int32_t uiV)
1435{
1436 MMVector *input = &env->tmp_VRegs[0];
1437
1438 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1439 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1440 unsigned int weight = fGETUBYTE(1, input->h[i]);
1441 unsigned int vindex = (bucket >> 3) & 0x1F;
1442 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1443
1444 if ((bucket & 1) == uiV) {
1445 env->VRegs[vindex].uw[elindex] =
1446 env->VRegs[vindex].uw[elindex] + weight;
1447 }
1448 }
1449}
1450
1451void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
1452{
1453 MMVector *input = &env->tmp_VRegs[0];
1454
1455 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1456 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1457 unsigned int weight = fGETUBYTE(1, input->h[i]);
1458 unsigned int vindex = (bucket >> 3) & 0x1F;
1459 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1460
1461 if (((bucket & 1) == uiV) && fGETQBIT(env->qtmp, 2 * i)) {
1462 env->VRegs[vindex].uw[elindex] =
1463 env->VRegs[vindex].uw[elindex] + weight;
1464 }
1465 }
1466}
1467
1468static void cancel_slot(CPUHexagonState *env, uint32_t slot)
1469{
1470 HEX_DEBUG_LOG("Slot %d cancelled\n", slot);
1471 env->slot_cancelled |= (1 << slot);
1472}
1473
1474
1475#define warn(...)
1476#define fatal(...) g_assert_not_reached();
1477
1478#define BOGUS_HELPER(tag) \
1479 printf("ERROR: bogus helper: " #tag "\n")
1480
1481#include "helper_funcs_generated.c.inc"
1482