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