2 * Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 #include "qemu/osdep.h"
20 #include "exec/exec-all.h"
21 #include "exec/cpu_ldst.h"
22 #include "exec/helper-proto.h"
23 #include "fpu/softfloat.h"
28 #include "hex_arch_types.h"
30 #include "mmvec/mmvec.h"
31 #include "mmvec/macros.h"
32 #include "op_helper.h"
33 #include "translate.h"
36 #define SF_MANTBITS 23
38 /* Exceptions processing helpers */
40 void do_raise_exception_err(CPUHexagonState
*env
,
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
);
50 G_NORETURN
void HELPER(raise_exception
)(CPUHexagonState
*env
, uint32_t excp
)
52 do_raise_exception_err(env
, excp
, 0);
55 void log_store32(CPUHexagonState
*env
, target_ulong addr
,
56 target_ulong val
, int width
, int slot
)
58 HEX_DEBUG_LOG("log_store%d(0x" TARGET_FMT_lx
59 ", %" PRId32
" [0x08%" PRIx32
"])\n",
60 width
, addr
, val
, val
);
61 env
->mem_log_stores
[slot
].va
= addr
;
62 env
->mem_log_stores
[slot
].width
= width
;
63 env
->mem_log_stores
[slot
].data32
= val
;
66 void log_store64(CPUHexagonState
*env
, target_ulong addr
,
67 int64_t val
, int width
, int slot
)
69 HEX_DEBUG_LOG("log_store%d(0x" TARGET_FMT_lx
70 ", %" PRId64
" [0x016%" PRIx64
"])\n",
71 width
, addr
, val
, val
);
72 env
->mem_log_stores
[slot
].va
= addr
;
73 env
->mem_log_stores
[slot
].width
= width
;
74 env
->mem_log_stores
[slot
].data64
= val
;
77 /* Handy place to set a breakpoint */
78 void HELPER(debug_start_packet
)(CPUHexagonState
*env
)
80 HEX_DEBUG_LOG("Start packet: pc = 0x" TARGET_FMT_lx
"\n",
81 env
->gpr
[HEX_REG_PC
]);
83 for (int i
= 0; i
< TOTAL_PER_THREAD_REGS
; i
++) {
84 env
->reg_written
[i
] = 0;
88 /* Checks for bookkeeping errors between disassembly context and runtime */
89 void HELPER(debug_check_store_width
)(CPUHexagonState
*env
, int slot
, int check
)
91 if (env
->mem_log_stores
[slot
].width
!= check
) {
92 HEX_DEBUG_LOG("ERROR: %d != %d\n",
93 env
->mem_log_stores
[slot
].width
, check
);
94 g_assert_not_reached();
98 void HELPER(commit_store
)(CPUHexagonState
*env
, int slot_num
)
100 uintptr_t ra
= GETPC();
101 uint8_t width
= env
->mem_log_stores
[slot_num
].width
;
102 target_ulong va
= env
->mem_log_stores
[slot_num
].va
;
106 cpu_stb_data_ra(env
, va
, env
->mem_log_stores
[slot_num
].data32
, ra
);
109 cpu_stw_data_ra(env
, va
, env
->mem_log_stores
[slot_num
].data32
, ra
);
112 cpu_stl_data_ra(env
, va
, env
->mem_log_stores
[slot_num
].data32
, ra
);
115 cpu_stq_data_ra(env
, va
, env
->mem_log_stores
[slot_num
].data64
, ra
);
118 g_assert_not_reached();
122 void HELPER(gather_store
)(CPUHexagonState
*env
, uint32_t addr
, int slot
)
124 mem_gather_store(env
, addr
, slot
);
127 void HELPER(commit_hvx_stores
)(CPUHexagonState
*env
)
129 uintptr_t ra
= GETPC();
132 /* Normal (possibly masked) vector store */
133 for (i
= 0; i
< VSTORES_MAX
; i
++) {
134 if (env
->vstore_pending
[i
]) {
135 env
->vstore_pending
[i
] = 0;
136 target_ulong va
= env
->vstore
[i
].va
;
137 int size
= env
->vstore
[i
].size
;
138 for (int j
= 0; j
< size
; j
++) {
139 if (test_bit(j
, env
->vstore
[i
].mask
)) {
140 cpu_stb_data_ra(env
, va
+ j
, env
->vstore
[i
].data
.ub
[j
], ra
);
147 if (env
->vtcm_pending
) {
148 env
->vtcm_pending
= false;
149 if (env
->vtcm_log
.op
) {
150 /* Need to perform the scatter read/modify/write at commit time */
151 if (env
->vtcm_log
.op_size
== 2) {
152 SCATTER_OP_WRITE_TO_MEM(uint16_t);
153 } else if (env
->vtcm_log
.op_size
== 4) {
154 /* Word Scatter += */
155 SCATTER_OP_WRITE_TO_MEM(uint32_t);
157 g_assert_not_reached();
160 for (i
= 0; i
< sizeof(MMVector
); i
++) {
161 if (test_bit(i
, env
->vtcm_log
.mask
)) {
162 cpu_stb_data_ra(env
, env
->vtcm_log
.va
[i
],
163 env
->vtcm_log
.data
.ub
[i
], ra
);
164 clear_bit(i
, env
->vtcm_log
.mask
);
165 env
->vtcm_log
.data
.ub
[i
] = 0;
173 static void print_store(CPUHexagonState
*env
, int slot
)
175 if (!(env
->slot_cancelled
& (1 << slot
))) {
176 uint8_t width
= env
->mem_log_stores
[slot
].width
;
178 uint32_t data
= env
->mem_log_stores
[slot
].data32
& 0xff;
179 HEX_DEBUG_LOG("\tmemb[0x" TARGET_FMT_lx
"] = %" PRId32
180 " (0x%02" PRIx32
")\n",
181 env
->mem_log_stores
[slot
].va
, data
, data
);
182 } else if (width
== 2) {
183 uint32_t data
= env
->mem_log_stores
[slot
].data32
& 0xffff;
184 HEX_DEBUG_LOG("\tmemh[0x" TARGET_FMT_lx
"] = %" PRId32
185 " (0x%04" PRIx32
")\n",
186 env
->mem_log_stores
[slot
].va
, data
, data
);
187 } else if (width
== 4) {
188 uint32_t data
= env
->mem_log_stores
[slot
].data32
;
189 HEX_DEBUG_LOG("\tmemw[0x" TARGET_FMT_lx
"] = %" PRId32
190 " (0x%08" PRIx32
")\n",
191 env
->mem_log_stores
[slot
].va
, data
, data
);
192 } else if (width
== 8) {
193 HEX_DEBUG_LOG("\tmemd[0x" TARGET_FMT_lx
"] = %" PRId64
194 " (0x%016" PRIx64
")\n",
195 env
->mem_log_stores
[slot
].va
,
196 env
->mem_log_stores
[slot
].data64
,
197 env
->mem_log_stores
[slot
].data64
);
199 HEX_DEBUG_LOG("\tBad store width %d\n", width
);
200 g_assert_not_reached();
205 /* This function is a handy place to set a breakpoint */
206 void HELPER(debug_commit_end
)(CPUHexagonState
*env
, uint32_t this_PC
,
207 int pred_written
, int has_st0
, int has_st1
)
209 bool reg_printed
= false;
210 bool pred_printed
= false;
213 HEX_DEBUG_LOG("Packet committed: pc = 0x" TARGET_FMT_lx
"\n", this_PC
);
214 HEX_DEBUG_LOG("slot_cancelled = %d\n", env
->slot_cancelled
);
216 for (i
= 0; i
< TOTAL_PER_THREAD_REGS
; i
++) {
217 if (env
->reg_written
[i
]) {
219 HEX_DEBUG_LOG("Regs written\n");
222 HEX_DEBUG_LOG("\tr%d = " TARGET_FMT_ld
" (0x" TARGET_FMT_lx
")\n",
223 i
, env
->gpr
[i
], env
->gpr
[i
]);
227 for (i
= 0; i
< NUM_PREGS
; i
++) {
228 if (pred_written
& (1 << i
)) {
230 HEX_DEBUG_LOG("Predicates written\n");
233 HEX_DEBUG_LOG("\tp%d = 0x" TARGET_FMT_lx
"\n",
238 if (has_st0
|| has_st1
) {
239 HEX_DEBUG_LOG("Stores\n");
248 HEX_DEBUG_LOG("Next PC = " TARGET_FMT_lx
"\n", env
->gpr
[HEX_REG_PC
]);
249 HEX_DEBUG_LOG("Exec counters: pkt = " TARGET_FMT_lx
250 ", insn = " TARGET_FMT_lx
251 ", hvx = " TARGET_FMT_lx
"\n",
252 env
->gpr
[HEX_REG_QEMU_PKT_CNT
],
253 env
->gpr
[HEX_REG_QEMU_INSN_CNT
],
254 env
->gpr
[HEX_REG_QEMU_HVX_CNT
]);
258 int32_t HELPER(fcircadd
)(int32_t RxV
, int32_t offset
, int32_t M
, int32_t CS
)
260 uint32_t K_const
= extract32(M
, 24, 4);
261 uint32_t length
= extract32(M
, 0, 17);
262 uint32_t new_ptr
= RxV
+ offset
;
266 if (K_const
== 0 && length
>= 4) {
268 end_addr
= start_addr
+ length
;
271 * Versions v3 and earlier used the K value to specify a power-of-2 size
272 * 2^(K+2) that is greater than the buffer length
274 int32_t mask
= (1 << (K_const
+ 2)) - 1;
275 start_addr
= RxV
& (~mask
);
276 end_addr
= start_addr
| length
;
279 if (new_ptr
>= end_addr
) {
281 } else if (new_ptr
< start_addr
) {
288 uint32_t HELPER(fbrev
)(uint32_t addr
)
291 * Bit reverse the low 16 bits of the address
293 return deposit32(addr
, 0, 16, revbit16(addr
));
296 static float32
build_float32(uint8_t sign
, uint32_t exp
, uint32_t mant
)
300 ((exp
& 0xff) << SF_MANTBITS
) |
301 (mant
& ((1 << SF_MANTBITS
) - 1)));
305 * sfrecipa, sfinvsqrta have two 32-bit results
306 * r0,p0=sfrecipa(r1,r2)
307 * r0,p0=sfinvsqrta(r1)
309 * Since helpers can only return a single value, we pack the two results
310 * into a 64-bit value.
312 uint64_t HELPER(sfrecipa
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
321 arch_fpop_start(env
);
322 if (arch_sf_recip_common(&RsV
, &RtV
, &RdV
, &adjust
, &env
->fp_status
)) {
324 idx
= (RtV
>> 16) & 0x7f;
325 mant
= (recip_lookup_table
[idx
] << 15) | 1;
326 exp
= SF_BIAS
- (float32_getexp(RtV
) - SF_BIAS
) - 1;
327 RdV
= build_float32(extract32(RtV
, 31, 1), exp
, mant
);
330 return ((uint64_t)RdV
<< 32) | PeV
;
333 uint64_t HELPER(sfinvsqrta
)(CPUHexagonState
*env
, float32 RsV
)
342 arch_fpop_start(env
);
343 if (arch_sf_invsqrt_common(&RsV
, &RdV
, &adjust
, &env
->fp_status
)) {
345 idx
= (RsV
>> 17) & 0x7f;
346 mant
= (invsqrt_lookup_table
[idx
] << 15);
347 exp
= SF_BIAS
- ((float32_getexp(RsV
) - SF_BIAS
) >> 1) - 1;
348 RdV
= build_float32(extract32(RsV
, 31, 1), exp
, mant
);
351 return ((uint64_t)RdV
<< 32) | PeV
;
354 int64_t HELPER(vacsh_val
)(CPUHexagonState
*env
,
355 int64_t RxxV
, int64_t RssV
, int64_t RttV
,
356 uint32_t pkt_need_commit
)
358 for (int i
= 0; i
< 4; i
++) {
359 int xv
= sextract64(RxxV
, i
* 16, 16);
360 int sv
= sextract64(RssV
, i
* 16, 16);
361 int tv
= sextract64(RttV
, i
* 16, 16);
365 max
= xv
> sv
? xv
: sv
;
366 /* Note that fSATH can set the OVF bit in usr */
367 RxxV
= deposit64(RxxV
, i
* 16, 16, fSATH(max
));
372 int32_t HELPER(vacsh_pred
)(CPUHexagonState
*env
,
373 int64_t RxxV
, int64_t RssV
, int64_t RttV
)
376 for (int i
= 0; i
< 4; i
++) {
377 int xv
= sextract64(RxxV
, i
* 16, 16);
378 int sv
= sextract64(RssV
, i
* 16, 16);
379 int tv
= sextract64(RttV
, i
* 16, 16);
382 PeV
= deposit32(PeV
, i
* 2, 1, (xv
> sv
));
383 PeV
= deposit32(PeV
, i
* 2 + 1, 1, (xv
> sv
));
388 int64_t HELPER(cabacdecbin_val
)(int64_t RssV
, int64_t RttV
)
399 state
= fEXTRACTU_RANGE(fGETWORD(1, RttV
), 5, 0);
400 valMPS
= fEXTRACTU_RANGE(fGETWORD(1, RttV
), 8, 8);
401 bitpos
= fEXTRACTU_RANGE(fGETWORD(0, RttV
), 4, 0);
402 range
= fGETWORD(0, RssV
);
403 offset
= fGETWORD(1, RssV
);
408 rLPS
= rLPS_table_64x4
[state
][(range
>> 29) & 3];
409 rLPS
= rLPS
<< 23; /* left aligned */
412 rMPS
= (range
& 0xff800000) - rLPS
;
414 /* most probable region */
416 RddV
= AC_next_state_MPS_64
[state
];
417 fINSERT_RANGE(RddV
, 8, 8, valMPS
);
418 fINSERT_RANGE(RddV
, 31, 23, (rMPS
>> 23));
419 fSETWORD(1, RddV
, offset
);
421 /* least probable region */
423 RddV
= AC_next_state_LPS_64
[state
];
424 fINSERT_RANGE(RddV
, 8, 8, ((!state
) ? (1 - valMPS
) : (valMPS
)));
425 fINSERT_RANGE(RddV
, 31, 23, (rLPS
>> 23));
426 fSETWORD(1, RddV
, (offset
- rMPS
));
431 int32_t HELPER(cabacdecbin_pred
)(int64_t RssV
, int64_t RttV
)
442 state
= fEXTRACTU_RANGE(fGETWORD(1, RttV
), 5, 0);
443 valMPS
= fEXTRACTU_RANGE(fGETWORD(1, RttV
), 8, 8);
444 bitpos
= fEXTRACTU_RANGE(fGETWORD(0, RttV
), 4, 0);
445 range
= fGETWORD(0, RssV
);
446 offset
= fGETWORD(1, RssV
);
451 rLPS
= rLPS_table_64x4
[state
][(range
>> 29) & 3];
452 rLPS
= rLPS
<< 23; /* left aligned */
455 rMPS
= (range
& 0xff800000) - rLPS
;
457 /* most probable region */
462 /* least probable region */
469 static void probe_store(CPUHexagonState
*env
, int slot
, int mmu_idx
,
472 if (!is_predicated
|| !(env
->slot_cancelled
& (1 << slot
))) {
473 size1u_t width
= env
->mem_log_stores
[slot
].width
;
474 target_ulong va
= env
->mem_log_stores
[slot
].va
;
475 uintptr_t ra
= GETPC();
476 probe_write(env
, va
, width
, mmu_idx
, ra
);
481 * Called from a mem_noshuf packet to make sure the load doesn't
484 void HELPER(probe_noshuf_load
)(CPUHexagonState
*env
, target_ulong va
,
485 int size
, int mmu_idx
)
487 uintptr_t retaddr
= GETPC();
488 probe_read(env
, va
, size
, mmu_idx
, retaddr
);
491 /* Called during packet commit when there are two scalar stores */
492 void HELPER(probe_pkt_scalar_store_s0
)(CPUHexagonState
*env
, int args
)
494 int mmu_idx
= FIELD_EX32(args
, PROBE_PKT_SCALAR_STORE_S0
, MMU_IDX
);
496 FIELD_EX32(args
, PROBE_PKT_SCALAR_STORE_S0
, IS_PREDICATED
);
497 probe_store(env
, 0, mmu_idx
, is_predicated
);
500 void HELPER(probe_hvx_stores
)(CPUHexagonState
*env
, int mmu_idx
)
502 uintptr_t retaddr
= GETPC();
505 /* Normal (possibly masked) vector store */
506 for (i
= 0; i
< VSTORES_MAX
; i
++) {
507 if (env
->vstore_pending
[i
]) {
508 target_ulong va
= env
->vstore
[i
].va
;
509 int size
= env
->vstore
[i
].size
;
510 for (int j
= 0; j
< size
; j
++) {
511 if (test_bit(j
, env
->vstore
[i
].mask
)) {
512 probe_write(env
, va
+ j
, 1, mmu_idx
, retaddr
);
519 if (env
->vtcm_pending
) {
520 if (env
->vtcm_log
.op
) {
521 /* Need to perform the scatter read/modify/write at commit time */
522 if (env
->vtcm_log
.op_size
== 2) {
523 SCATTER_OP_PROBE_MEM(size2u_t
, mmu_idx
, retaddr
);
524 } else if (env
->vtcm_log
.op_size
== 4) {
525 /* Word Scatter += */
526 SCATTER_OP_PROBE_MEM(size4u_t
, mmu_idx
, retaddr
);
528 g_assert_not_reached();
531 for (int i
= 0; i
< sizeof(MMVector
); i
++) {
532 if (test_bit(i
, env
->vtcm_log
.mask
)) {
533 probe_write(env
, env
->vtcm_log
.va
[i
], 1, mmu_idx
, retaddr
);
541 void HELPER(probe_pkt_scalar_hvx_stores
)(CPUHexagonState
*env
, int mask
)
543 bool has_st0
= FIELD_EX32(mask
, PROBE_PKT_SCALAR_HVX_STORES
, HAS_ST0
);
544 bool has_st1
= FIELD_EX32(mask
, PROBE_PKT_SCALAR_HVX_STORES
, HAS_ST1
);
545 bool has_hvx_stores
=
546 FIELD_EX32(mask
, PROBE_PKT_SCALAR_HVX_STORES
, HAS_HVX_STORES
);
547 bool s0_is_pred
= FIELD_EX32(mask
, PROBE_PKT_SCALAR_HVX_STORES
, S0_IS_PRED
);
548 bool s1_is_pred
= FIELD_EX32(mask
, PROBE_PKT_SCALAR_HVX_STORES
, S1_IS_PRED
);
549 int mmu_idx
= FIELD_EX32(mask
, PROBE_PKT_SCALAR_HVX_STORES
, MMU_IDX
);
552 probe_store(env
, 0, mmu_idx
, s0_is_pred
);
555 probe_store(env
, 1, mmu_idx
, s1_is_pred
);
557 if (has_hvx_stores
) {
558 HELPER(probe_hvx_stores
)(env
, mmu_idx
);
564 * Section 5.5 of the Hexagon V67 Programmer's Reference Manual
566 * If the load is in slot 0 and there is a store in slot1 (that
567 * wasn't cancelled), we have to do the store first.
569 static void check_noshuf(CPUHexagonState
*env
, bool pkt_has_store_s1
,
570 uint32_t slot
, target_ulong vaddr
, int size
)
572 if (slot
== 0 && pkt_has_store_s1
&&
573 ((env
->slot_cancelled
& (1 << 1)) == 0)) {
574 HELPER(probe_noshuf_load
)(env
, vaddr
, size
, MMU_USER_IDX
);
575 HELPER(commit_store
)(env
, 1);
579 uint8_t mem_load1(CPUHexagonState
*env
, bool pkt_has_store_s1
,
580 uint32_t slot
, target_ulong vaddr
)
582 uintptr_t ra
= GETPC();
583 check_noshuf(env
, pkt_has_store_s1
, slot
, vaddr
, 1);
584 return cpu_ldub_data_ra(env
, vaddr
, ra
);
587 uint16_t mem_load2(CPUHexagonState
*env
, bool pkt_has_store_s1
,
588 uint32_t slot
, target_ulong vaddr
)
590 uintptr_t ra
= GETPC();
591 check_noshuf(env
, pkt_has_store_s1
, slot
, vaddr
, 2);
592 return cpu_lduw_data_ra(env
, vaddr
, ra
);
595 uint32_t mem_load4(CPUHexagonState
*env
, bool pkt_has_store_s1
,
596 uint32_t slot
, target_ulong vaddr
)
598 uintptr_t ra
= GETPC();
599 check_noshuf(env
, pkt_has_store_s1
, slot
, vaddr
, 4);
600 return cpu_ldl_data_ra(env
, vaddr
, ra
);
603 uint64_t mem_load8(CPUHexagonState
*env
, bool pkt_has_store_s1
,
604 uint32_t slot
, target_ulong vaddr
)
606 uintptr_t ra
= GETPC();
607 check_noshuf(env
, pkt_has_store_s1
, slot
, vaddr
, 8);
608 return cpu_ldq_data_ra(env
, vaddr
, ra
);
612 float64
HELPER(conv_sf2df
)(CPUHexagonState
*env
, float32 RsV
)
615 arch_fpop_start(env
);
616 out_f64
= float32_to_float64(RsV
, &env
->fp_status
);
621 float32
HELPER(conv_df2sf
)(CPUHexagonState
*env
, float64 RssV
)
624 arch_fpop_start(env
);
625 out_f32
= float64_to_float32(RssV
, &env
->fp_status
);
630 float32
HELPER(conv_uw2sf
)(CPUHexagonState
*env
, int32_t RsV
)
633 arch_fpop_start(env
);
634 RdV
= uint32_to_float32(RsV
, &env
->fp_status
);
639 float64
HELPER(conv_uw2df
)(CPUHexagonState
*env
, int32_t RsV
)
642 arch_fpop_start(env
);
643 RddV
= uint32_to_float64(RsV
, &env
->fp_status
);
648 float32
HELPER(conv_w2sf
)(CPUHexagonState
*env
, int32_t RsV
)
651 arch_fpop_start(env
);
652 RdV
= int32_to_float32(RsV
, &env
->fp_status
);
657 float64
HELPER(conv_w2df
)(CPUHexagonState
*env
, int32_t RsV
)
660 arch_fpop_start(env
);
661 RddV
= int32_to_float64(RsV
, &env
->fp_status
);
666 float32
HELPER(conv_ud2sf
)(CPUHexagonState
*env
, int64_t RssV
)
669 arch_fpop_start(env
);
670 RdV
= uint64_to_float32(RssV
, &env
->fp_status
);
675 float64
HELPER(conv_ud2df
)(CPUHexagonState
*env
, int64_t RssV
)
678 arch_fpop_start(env
);
679 RddV
= uint64_to_float64(RssV
, &env
->fp_status
);
684 float32
HELPER(conv_d2sf
)(CPUHexagonState
*env
, int64_t RssV
)
687 arch_fpop_start(env
);
688 RdV
= int64_to_float32(RssV
, &env
->fp_status
);
693 float64
HELPER(conv_d2df
)(CPUHexagonState
*env
, int64_t RssV
)
696 arch_fpop_start(env
);
697 RddV
= int64_to_float64(RssV
, &env
->fp_status
);
702 uint32_t HELPER(conv_sf2uw
)(CPUHexagonState
*env
, float32 RsV
)
705 arch_fpop_start(env
);
706 /* Hexagon checks the sign before rounding */
707 if (float32_is_neg(RsV
) && !float32_is_any_nan(RsV
)) {
708 float_raise(float_flag_invalid
, &env
->fp_status
);
711 RdV
= float32_to_uint32(RsV
, &env
->fp_status
);
717 int32_t HELPER(conv_sf2w
)(CPUHexagonState
*env
, float32 RsV
)
720 arch_fpop_start(env
);
721 /* Hexagon returns -1 for NaN */
722 if (float32_is_any_nan(RsV
)) {
723 float_raise(float_flag_invalid
, &env
->fp_status
);
726 RdV
= float32_to_int32(RsV
, &env
->fp_status
);
732 uint64_t HELPER(conv_sf2ud
)(CPUHexagonState
*env
, float32 RsV
)
735 arch_fpop_start(env
);
736 /* Hexagon checks the sign before rounding */
737 if (float32_is_neg(RsV
) && !float32_is_any_nan(RsV
)) {
738 float_raise(float_flag_invalid
, &env
->fp_status
);
741 RddV
= float32_to_uint64(RsV
, &env
->fp_status
);
747 int64_t HELPER(conv_sf2d
)(CPUHexagonState
*env
, float32 RsV
)
750 arch_fpop_start(env
);
751 /* Hexagon returns -1 for NaN */
752 if (float32_is_any_nan(RsV
)) {
753 float_raise(float_flag_invalid
, &env
->fp_status
);
756 RddV
= float32_to_int64(RsV
, &env
->fp_status
);
762 uint32_t HELPER(conv_df2uw
)(CPUHexagonState
*env
, float64 RssV
)
765 arch_fpop_start(env
);
766 /* Hexagon checks the sign before rounding */
767 if (float64_is_neg(RssV
) && !float64_is_any_nan(RssV
)) {
768 float_raise(float_flag_invalid
, &env
->fp_status
);
771 RdV
= float64_to_uint32(RssV
, &env
->fp_status
);
777 int32_t HELPER(conv_df2w
)(CPUHexagonState
*env
, float64 RssV
)
780 arch_fpop_start(env
);
781 /* Hexagon returns -1 for NaN */
782 if (float64_is_any_nan(RssV
)) {
783 float_raise(float_flag_invalid
, &env
->fp_status
);
786 RdV
= float64_to_int32(RssV
, &env
->fp_status
);
792 uint64_t HELPER(conv_df2ud
)(CPUHexagonState
*env
, float64 RssV
)
795 arch_fpop_start(env
);
796 /* Hexagon checks the sign before rounding */
797 if (float64_is_neg(RssV
) && !float64_is_any_nan(RssV
)) {
798 float_raise(float_flag_invalid
, &env
->fp_status
);
801 RddV
= float64_to_uint64(RssV
, &env
->fp_status
);
807 int64_t HELPER(conv_df2d
)(CPUHexagonState
*env
, float64 RssV
)
810 arch_fpop_start(env
);
811 /* Hexagon returns -1 for NaN */
812 if (float64_is_any_nan(RssV
)) {
813 float_raise(float_flag_invalid
, &env
->fp_status
);
816 RddV
= float64_to_int64(RssV
, &env
->fp_status
);
822 uint32_t HELPER(conv_sf2uw_chop
)(CPUHexagonState
*env
, float32 RsV
)
825 arch_fpop_start(env
);
826 /* Hexagon checks the sign before rounding */
827 if (float32_is_neg(RsV
) && !float32_is_any_nan(RsV
)) {
828 float_raise(float_flag_invalid
, &env
->fp_status
);
831 RdV
= float32_to_uint32_round_to_zero(RsV
, &env
->fp_status
);
837 int32_t HELPER(conv_sf2w_chop
)(CPUHexagonState
*env
, float32 RsV
)
840 arch_fpop_start(env
);
841 /* Hexagon returns -1 for NaN */
842 if (float32_is_any_nan(RsV
)) {
843 float_raise(float_flag_invalid
, &env
->fp_status
);
846 RdV
= float32_to_int32_round_to_zero(RsV
, &env
->fp_status
);
852 uint64_t HELPER(conv_sf2ud_chop
)(CPUHexagonState
*env
, float32 RsV
)
855 arch_fpop_start(env
);
856 /* Hexagon checks the sign before rounding */
857 if (float32_is_neg(RsV
) && !float32_is_any_nan(RsV
)) {
858 float_raise(float_flag_invalid
, &env
->fp_status
);
861 RddV
= float32_to_uint64_round_to_zero(RsV
, &env
->fp_status
);
867 int64_t HELPER(conv_sf2d_chop
)(CPUHexagonState
*env
, float32 RsV
)
870 arch_fpop_start(env
);
871 /* Hexagon returns -1 for NaN */
872 if (float32_is_any_nan(RsV
)) {
873 float_raise(float_flag_invalid
, &env
->fp_status
);
876 RddV
= float32_to_int64_round_to_zero(RsV
, &env
->fp_status
);
882 uint32_t HELPER(conv_df2uw_chop
)(CPUHexagonState
*env
, float64 RssV
)
885 arch_fpop_start(env
);
886 /* Hexagon checks the sign before rounding */
887 if (float64_is_neg(RssV
) && !float64_is_any_nan(RssV
)) {
888 float_raise(float_flag_invalid
, &env
->fp_status
);
891 RdV
= float64_to_uint32_round_to_zero(RssV
, &env
->fp_status
);
897 int32_t HELPER(conv_df2w_chop
)(CPUHexagonState
*env
, float64 RssV
)
900 arch_fpop_start(env
);
901 /* Hexagon returns -1 for NaN */
902 if (float64_is_any_nan(RssV
)) {
903 float_raise(float_flag_invalid
, &env
->fp_status
);
906 RdV
= float64_to_int32_round_to_zero(RssV
, &env
->fp_status
);
912 uint64_t HELPER(conv_df2ud_chop
)(CPUHexagonState
*env
, float64 RssV
)
915 arch_fpop_start(env
);
916 /* Hexagon checks the sign before rounding */
917 if (float64_is_neg(RssV
) && !float64_is_any_nan(RssV
)) {
918 float_raise(float_flag_invalid
, &env
->fp_status
);
921 RddV
= float64_to_uint64_round_to_zero(RssV
, &env
->fp_status
);
927 int64_t HELPER(conv_df2d_chop
)(CPUHexagonState
*env
, float64 RssV
)
930 arch_fpop_start(env
);
931 /* Hexagon returns -1 for NaN */
932 if (float64_is_any_nan(RssV
)) {
933 float_raise(float_flag_invalid
, &env
->fp_status
);
936 RddV
= float64_to_int64_round_to_zero(RssV
, &env
->fp_status
);
942 float32
HELPER(sfadd
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
945 arch_fpop_start(env
);
946 RdV
= float32_add(RsV
, RtV
, &env
->fp_status
);
951 float32
HELPER(sfsub
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
954 arch_fpop_start(env
);
955 RdV
= float32_sub(RsV
, RtV
, &env
->fp_status
);
960 int32_t HELPER(sfcmpeq
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
963 arch_fpop_start(env
);
964 PdV
= f8BITSOF(float32_eq_quiet(RsV
, RtV
, &env
->fp_status
));
969 int32_t HELPER(sfcmpgt
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
973 arch_fpop_start(env
);
974 cmp
= float32_compare_quiet(RsV
, RtV
, &env
->fp_status
);
975 PdV
= f8BITSOF(cmp
== float_relation_greater
);
980 int32_t HELPER(sfcmpge
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
984 arch_fpop_start(env
);
985 cmp
= float32_compare_quiet(RsV
, RtV
, &env
->fp_status
);
986 PdV
= f8BITSOF(cmp
== float_relation_greater
||
987 cmp
== float_relation_equal
);
992 int32_t HELPER(sfcmpuo
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
995 arch_fpop_start(env
);
996 PdV
= f8BITSOF(float32_unordered_quiet(RsV
, RtV
, &env
->fp_status
));
1001 float32
HELPER(sfmax
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
1004 arch_fpop_start(env
);
1005 RdV
= float32_maximum_number(RsV
, RtV
, &env
->fp_status
);
1010 float32
HELPER(sfmin
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
1013 arch_fpop_start(env
);
1014 RdV
= float32_minimum_number(RsV
, RtV
, &env
->fp_status
);
1019 int32_t HELPER(sfclass
)(CPUHexagonState
*env
, float32 RsV
, int32_t uiV
)
1022 arch_fpop_start(env
);
1023 if (fGETBIT(0, uiV
) && float32_is_zero(RsV
)) {
1026 if (fGETBIT(1, uiV
) && float32_is_normal(RsV
)) {
1029 if (fGETBIT(2, uiV
) && float32_is_denormal(RsV
)) {
1032 if (fGETBIT(3, uiV
) && float32_is_infinity(RsV
)) {
1035 if (fGETBIT(4, uiV
) && float32_is_any_nan(RsV
)) {
1038 set_float_exception_flags(0, &env
->fp_status
);
1043 float32
HELPER(sffixupn
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
1047 arch_fpop_start(env
);
1048 arch_sf_recip_common(&RsV
, &RtV
, &RdV
, &adjust
, &env
->fp_status
);
1054 float32
HELPER(sffixupd
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
1058 arch_fpop_start(env
);
1059 arch_sf_recip_common(&RsV
, &RtV
, &RdV
, &adjust
, &env
->fp_status
);
1065 float32
HELPER(sffixupr
)(CPUHexagonState
*env
, float32 RsV
)
1069 arch_fpop_start(env
);
1070 arch_sf_invsqrt_common(&RsV
, &RdV
, &adjust
, &env
->fp_status
);
1076 float64
HELPER(dfadd
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1079 arch_fpop_start(env
);
1080 RddV
= float64_add(RssV
, RttV
, &env
->fp_status
);
1085 float64
HELPER(dfsub
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1088 arch_fpop_start(env
);
1089 RddV
= float64_sub(RssV
, RttV
, &env
->fp_status
);
1094 float64
HELPER(dfmax
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1097 arch_fpop_start(env
);
1098 RddV
= float64_maximum_number(RssV
, RttV
, &env
->fp_status
);
1103 float64
HELPER(dfmin
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1106 arch_fpop_start(env
);
1107 RddV
= float64_minimum_number(RssV
, RttV
, &env
->fp_status
);
1112 int32_t HELPER(dfcmpeq
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1115 arch_fpop_start(env
);
1116 PdV
= f8BITSOF(float64_eq_quiet(RssV
, RttV
, &env
->fp_status
));
1121 int32_t HELPER(dfcmpgt
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1125 arch_fpop_start(env
);
1126 cmp
= float64_compare_quiet(RssV
, RttV
, &env
->fp_status
);
1127 PdV
= f8BITSOF(cmp
== float_relation_greater
);
1132 int32_t HELPER(dfcmpge
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1136 arch_fpop_start(env
);
1137 cmp
= float64_compare_quiet(RssV
, RttV
, &env
->fp_status
);
1138 PdV
= f8BITSOF(cmp
== float_relation_greater
||
1139 cmp
== float_relation_equal
);
1144 int32_t HELPER(dfcmpuo
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1147 arch_fpop_start(env
);
1148 PdV
= f8BITSOF(float64_unordered_quiet(RssV
, RttV
, &env
->fp_status
));
1153 int32_t HELPER(dfclass
)(CPUHexagonState
*env
, float64 RssV
, int32_t uiV
)
1156 arch_fpop_start(env
);
1157 if (fGETBIT(0, uiV
) && float64_is_zero(RssV
)) {
1160 if (fGETBIT(1, uiV
) && float64_is_normal(RssV
)) {
1163 if (fGETBIT(2, uiV
) && float64_is_denormal(RssV
)) {
1166 if (fGETBIT(3, uiV
) && float64_is_infinity(RssV
)) {
1169 if (fGETBIT(4, uiV
) && float64_is_any_nan(RssV
)) {
1172 set_float_exception_flags(0, &env
->fp_status
);
1177 float32
HELPER(sfmpy
)(CPUHexagonState
*env
, float32 RsV
, float32 RtV
)
1180 arch_fpop_start(env
);
1181 RdV
= internal_mpyf(RsV
, RtV
, &env
->fp_status
);
1186 float32
HELPER(sffma
)(CPUHexagonState
*env
, float32 RxV
,
1187 float32 RsV
, float32 RtV
)
1189 arch_fpop_start(env
);
1190 RxV
= internal_fmafx(RsV
, RtV
, RxV
, 0, &env
->fp_status
);
1195 static bool is_zero_prod(float32 a
, float32 b
)
1197 return ((float32_is_zero(a
) && is_finite(b
)) ||
1198 (float32_is_zero(b
) && is_finite(a
)));
1201 static float32
check_nan(float32 dst
, float32 x
, float_status
*fp_status
)
1204 if (float32_is_any_nan(x
)) {
1205 if (extract32(x
, 22, 1) == 0) {
1206 float_raise(float_flag_invalid
, fp_status
);
1208 ret
= make_float32(0xffffffff); /* nan */
1213 float32
HELPER(sffma_sc
)(CPUHexagonState
*env
, float32 RxV
,
1214 float32 RsV
, float32 RtV
, float32 PuV
)
1217 arch_fpop_start(env
);
1218 RxV
= check_nan(RxV
, RxV
, &env
->fp_status
);
1219 RxV
= check_nan(RxV
, RsV
, &env
->fp_status
);
1220 RxV
= check_nan(RxV
, RtV
, &env
->fp_status
);
1221 tmp
= internal_fmafx(RsV
, RtV
, RxV
, fSXTN(8, 64, PuV
), &env
->fp_status
);
1222 if (!(float32_is_zero(RxV
) && is_zero_prod(RsV
, RtV
))) {
1229 float32
HELPER(sffms
)(CPUHexagonState
*env
, float32 RxV
,
1230 float32 RsV
, float32 RtV
)
1233 arch_fpop_start(env
);
1234 neg_RsV
= float32_set_sign(RsV
, float32_is_neg(RsV
) ? 0 : 1);
1235 RxV
= internal_fmafx(neg_RsV
, RtV
, RxV
, 0, &env
->fp_status
);
1240 static bool is_inf_prod(int32_t a
, int32_t b
)
1242 return (float32_is_infinity(a
) && float32_is_infinity(b
)) ||
1243 (float32_is_infinity(a
) && is_finite(b
) && !float32_is_zero(b
)) ||
1244 (float32_is_infinity(b
) && is_finite(a
) && !float32_is_zero(a
));
1247 float32
HELPER(sffma_lib
)(CPUHexagonState
*env
, float32 RxV
,
1248 float32 RsV
, float32 RtV
)
1254 arch_fpop_start(env
);
1255 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
1256 infminusinf
= float32_is_infinity(RxV
) &&
1257 is_inf_prod(RsV
, RtV
) &&
1258 (fGETBIT(31, RsV
^ RxV
^ RtV
) != 0);
1259 infinp
= float32_is_infinity(RxV
) ||
1260 float32_is_infinity(RtV
) ||
1261 float32_is_infinity(RsV
);
1262 RxV
= check_nan(RxV
, RxV
, &env
->fp_status
);
1263 RxV
= check_nan(RxV
, RsV
, &env
->fp_status
);
1264 RxV
= check_nan(RxV
, RtV
, &env
->fp_status
);
1265 tmp
= internal_fmafx(RsV
, RtV
, RxV
, 0, &env
->fp_status
);
1266 if (!(float32_is_zero(RxV
) && is_zero_prod(RsV
, RtV
))) {
1269 set_float_exception_flags(0, &env
->fp_status
);
1270 if (float32_is_infinity(RxV
) && !infinp
) {
1280 float32
HELPER(sffms_lib
)(CPUHexagonState
*env
, float32 RxV
,
1281 float32 RsV
, float32 RtV
)
1287 arch_fpop_start(env
);
1288 set_float_rounding_mode(float_round_nearest_even
, &env
->fp_status
);
1289 infminusinf
= float32_is_infinity(RxV
) &&
1290 is_inf_prod(RsV
, RtV
) &&
1291 (fGETBIT(31, RsV
^ RxV
^ RtV
) == 0);
1292 infinp
= float32_is_infinity(RxV
) ||
1293 float32_is_infinity(RtV
) ||
1294 float32_is_infinity(RsV
);
1295 RxV
= check_nan(RxV
, RxV
, &env
->fp_status
);
1296 RxV
= check_nan(RxV
, RsV
, &env
->fp_status
);
1297 RxV
= check_nan(RxV
, RtV
, &env
->fp_status
);
1298 float32 minus_RsV
= float32_sub(float32_zero
, RsV
, &env
->fp_status
);
1299 tmp
= internal_fmafx(minus_RsV
, RtV
, RxV
, 0, &env
->fp_status
);
1300 if (!(float32_is_zero(RxV
) && is_zero_prod(RsV
, RtV
))) {
1303 set_float_exception_flags(0, &env
->fp_status
);
1304 if (float32_is_infinity(RxV
) && !infinp
) {
1314 float64
HELPER(dfmpyfix
)(CPUHexagonState
*env
, float64 RssV
, float64 RttV
)
1317 arch_fpop_start(env
);
1318 if (float64_is_denormal(RssV
) &&
1319 (float64_getexp(RttV
) >= 512) &&
1320 float64_is_normal(RttV
)) {
1321 RddV
= float64_mul(RssV
, make_float64(0x4330000000000000),
1323 } else if (float64_is_denormal(RttV
) &&
1324 (float64_getexp(RssV
) >= 512) &&
1325 float64_is_normal(RssV
)) {
1326 RddV
= float64_mul(RssV
, make_float64(0x3cb0000000000000),
1335 float64
HELPER(dfmpyhh
)(CPUHexagonState
*env
, float64 RxxV
,
1336 float64 RssV
, float64 RttV
)
1338 arch_fpop_start(env
);
1339 RxxV
= internal_mpyhh(RssV
, RttV
, RxxV
, &env
->fp_status
);
1344 /* Histogram instructions */
1346 void HELPER(vhist
)(CPUHexagonState
*env
)
1348 MMVector
*input
= &env
->tmp_VRegs
[0];
1350 for (int lane
= 0; lane
< 8; lane
++) {
1351 for (int i
= 0; i
< sizeof(MMVector
) / 8; ++i
) {
1352 unsigned char value
= input
->ub
[(sizeof(MMVector
) / 8) * lane
+ i
];
1353 unsigned char regno
= value
>> 3;
1354 unsigned char element
= value
& 7;
1356 env
->VRegs
[regno
].uh
[(sizeof(MMVector
) / 16) * lane
+ element
]++;
1361 void HELPER(vhistq
)(CPUHexagonState
*env
)
1363 MMVector
*input
= &env
->tmp_VRegs
[0];
1365 for (int lane
= 0; lane
< 8; lane
++) {
1366 for (int i
= 0; i
< sizeof(MMVector
) / 8; ++i
) {
1367 unsigned char value
= input
->ub
[(sizeof(MMVector
) / 8) * lane
+ i
];
1368 unsigned char regno
= value
>> 3;
1369 unsigned char element
= value
& 7;
1371 if (fGETQBIT(env
->qtmp
, sizeof(MMVector
) / 8 * lane
+ i
)) {
1372 env
->VRegs
[regno
].uh
[
1373 (sizeof(MMVector
) / 16) * lane
+ element
]++;
1379 void HELPER(vwhist256
)(CPUHexagonState
*env
)
1381 MMVector
*input
= &env
->tmp_VRegs
[0];
1383 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1384 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1385 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1386 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1387 unsigned int elindex
= ((i
>> 0) & (~7)) | ((bucket
>> 0) & 7);
1389 env
->VRegs
[vindex
].uh
[elindex
] =
1390 env
->VRegs
[vindex
].uh
[elindex
] + weight
;
1394 void HELPER(vwhist256q
)(CPUHexagonState
*env
)
1396 MMVector
*input
= &env
->tmp_VRegs
[0];
1398 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1399 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1400 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1401 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1402 unsigned int elindex
= ((i
>> 0) & (~7)) | ((bucket
>> 0) & 7);
1404 if (fGETQBIT(env
->qtmp
, 2 * i
)) {
1405 env
->VRegs
[vindex
].uh
[elindex
] =
1406 env
->VRegs
[vindex
].uh
[elindex
] + weight
;
1411 void HELPER(vwhist256_sat
)(CPUHexagonState
*env
)
1413 MMVector
*input
= &env
->tmp_VRegs
[0];
1415 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1416 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1417 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1418 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1419 unsigned int elindex
= ((i
>> 0) & (~7)) | ((bucket
>> 0) & 7);
1421 env
->VRegs
[vindex
].uh
[elindex
] =
1422 fVSATUH(env
->VRegs
[vindex
].uh
[elindex
] + weight
);
1426 void HELPER(vwhist256q_sat
)(CPUHexagonState
*env
)
1428 MMVector
*input
= &env
->tmp_VRegs
[0];
1430 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1431 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1432 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1433 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1434 unsigned int elindex
= ((i
>> 0) & (~7)) | ((bucket
>> 0) & 7);
1436 if (fGETQBIT(env
->qtmp
, 2 * i
)) {
1437 env
->VRegs
[vindex
].uh
[elindex
] =
1438 fVSATUH(env
->VRegs
[vindex
].uh
[elindex
] + weight
);
1443 void HELPER(vwhist128
)(CPUHexagonState
*env
)
1445 MMVector
*input
= &env
->tmp_VRegs
[0];
1447 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1448 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1449 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1450 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1451 unsigned int elindex
= ((i
>> 1) & (~3)) | ((bucket
>> 1) & 3);
1453 env
->VRegs
[vindex
].uw
[elindex
] =
1454 env
->VRegs
[vindex
].uw
[elindex
] + weight
;
1458 void HELPER(vwhist128q
)(CPUHexagonState
*env
)
1460 MMVector
*input
= &env
->tmp_VRegs
[0];
1462 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1463 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1464 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1465 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1466 unsigned int elindex
= ((i
>> 1) & (~3)) | ((bucket
>> 1) & 3);
1468 if (fGETQBIT(env
->qtmp
, 2 * i
)) {
1469 env
->VRegs
[vindex
].uw
[elindex
] =
1470 env
->VRegs
[vindex
].uw
[elindex
] + weight
;
1475 void HELPER(vwhist128m
)(CPUHexagonState
*env
, int32_t uiV
)
1477 MMVector
*input
= &env
->tmp_VRegs
[0];
1479 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1480 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1481 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1482 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1483 unsigned int elindex
= ((i
>> 1) & (~3)) | ((bucket
>> 1) & 3);
1485 if ((bucket
& 1) == uiV
) {
1486 env
->VRegs
[vindex
].uw
[elindex
] =
1487 env
->VRegs
[vindex
].uw
[elindex
] + weight
;
1492 void HELPER(vwhist128qm
)(CPUHexagonState
*env
, int32_t uiV
)
1494 MMVector
*input
= &env
->tmp_VRegs
[0];
1496 for (int i
= 0; i
< (sizeof(MMVector
) / 2); i
++) {
1497 unsigned int bucket
= fGETUBYTE(0, input
->h
[i
]);
1498 unsigned int weight
= fGETUBYTE(1, input
->h
[i
]);
1499 unsigned int vindex
= (bucket
>> 3) & 0x1F;
1500 unsigned int elindex
= ((i
>> 1) & (~3)) | ((bucket
>> 1) & 3);
1502 if (((bucket
& 1) == uiV
) && fGETQBIT(env
->qtmp
, 2 * i
)) {
1503 env
->VRegs
[vindex
].uw
[elindex
] =
1504 env
->VRegs
[vindex
].uw
[elindex
] + weight
;
1509 /* These macros can be referenced in the generated helper functions */
1510 #define warn(...) /* Nothing */
1511 #define fatal(...) g_assert_not_reached();
1513 #define BOGUS_HELPER(tag) \
1514 printf("ERROR: bogus helper: " #tag "\n")
1516 #include "helper_funcs_generated.c.inc"