xref: /qemu/target/hexagon/op_helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
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