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