master
c 1,984 lines 58.9 KB
Raw
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/cpu-loop.h"
22 #include "accel/tcg/probe.h"
23 #include "qemu/main-loop.h"
24 #include "cpu.h"
25 #include "exec/helper-proto.h"
26 #include "fpu/softfloat.h"
27 #include "exec/cpu-interrupt.h"
28 #include "internal.h"
29 #include "macros.h"
30 #include "sys_macros.h"
31 #include "arch.h"
32 #include "hex_arch_types.h"
33 #include "fma_emu.h"
34 #include "mmvec/mmvec.h"
35 #include "mmvec/macros.h"
36 #include "op_helper.h"
37 #include "cpu_helper.h"
38 #include "tcg/tcg-gvec-desc.h"
39 #include "translate.h"
40 #ifndef CONFIG_USER_ONLY
41 #include "hw/hexagon/hexagon_globalreg.h"
42 #include "hex_mmu.h"
43 #include "hw/hexagon/hexagon_tlb.h"
44 #include "hw/intc/hex-l2vic.h"
45 #include "hex_interrupts.h"
46 #include "hexswi.h"
47 #endif
48
49 #define SF_BIAS 127
50 #define SF_MANTBITS 23
51
52 /* Exceptions processing helpers */
53 G_NORETURN
54 void do_raise_exception(CPUHexagonState *env, uint32_t exception,
55 uint32_t PC, uintptr_t retaddr)
56 {
57 CPUState *cs = env_cpu(env);
58 qemu_log_mask(CPU_LOG_INT, "%s: 0x%08" PRIx32 ", @ %08" PRIx32 "\n",
59 __func__, exception, PC);
60 ASSERT_DIRECT_TO_GUEST_UNSET(env, exception);
61
62 env->gpr[HEX_REG_PC] = PC;
63 cs->exception_index = exception;
64 cpu_loop_exit_restore(cs, retaddr);
65 }
66
67 G_NORETURN void hexagon_raise_exception_err(CPUHexagonState *env,
68 uint32_t exception,
69 uintptr_t pc)
70 {
71 do_raise_exception(env, exception, pc, 0);
72 }
73
74 G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp,
75 uint32_t PC)
76 {
77 hexagon_raise_exception_err(env, excp, PC);
78 }
79
80 void log_store32(CPUHexagonState *env, target_ulong addr,
81 target_ulong val, uint32_t width, int slot)
82 {
83 env->mem_log_stores[slot].va = addr;
84 env->mem_log_stores[slot].width = width;
85 env->mem_log_stores[slot].data32 = val;
86 }
87
88 void log_store64(CPUHexagonState *env, target_ulong addr,
89 int64_t val, uint32_t width, int slot)
90 {
91 env->mem_log_stores[slot].va = addr;
92 env->mem_log_stores[slot].width = width;
93 env->mem_log_stores[slot].data64 = val;
94 }
95
96 static void commit_store(CPUHexagonState *env, int slot_num, uintptr_t ra)
97 {
98 uint32_t width = env->mem_log_stores[slot_num].width;
99 target_ulong va = env->mem_log_stores[slot_num].va;
100 MemOpIdx oi;
101
102 switch (width) {
103 case 1:
104 cpu_stb_data_ra(env, va, env->mem_log_stores[slot_num].data32, ra);
105 break;
106 case 2:
107 oi = make_memop_idx(MO_LEUW | MO_ALIGN,
108 cpu_mmu_index(env_cpu(env), false));
109 cpu_stw_mmu(env, va, env->mem_log_stores[slot_num].data32, oi, ra);
110 break;
111 case 4:
112 oi = make_memop_idx(MO_LEUL | MO_ALIGN,
113 cpu_mmu_index(env_cpu(env), false));
114 cpu_stl_mmu(env, va, env->mem_log_stores[slot_num].data32, oi, ra);
115 break;
116 case 8:
117 oi = make_memop_idx(MO_LEUQ | MO_ALIGN,
118 cpu_mmu_index(env_cpu(env), false));
119 cpu_stq_mmu(env, va, env->mem_log_stores[slot_num].data64, oi, ra);
120 break;
121 default:
122 g_assert_not_reached();
123 }
124 }
125
126 void HELPER(commit_store)(CPUHexagonState *env, int slot_num)
127 {
128 uintptr_t ra = GETPC();
129 commit_store(env, slot_num, ra);
130 }
131
132 void HELPER(gather_store)(CPUHexagonState *env, uint32_t addr, int slot)
133 {
134 mem_gather_store(env, addr, slot);
135 }
136
137 void HELPER(commit_hvx_stores)(CPUHexagonState *env)
138 {
139 uintptr_t ra = GETPC();
140
141 /* Normal (possibly masked) vector store */
142 for (int i = 0; i < VSTORES_MAX; i++) {
143 if (env->vstore_pending[i]) {
144 env->vstore_pending[i] = 0;
145 target_ulong va = env->vstore[i].va;
146 int size = env->vstore[i].size;
147 for (int j = 0; j < size; j++) {
148 if (test_bit(j, env->vstore[i].mask)) {
149 cpu_stb_data_ra(env, va + j, env->vstore[i].data.ub[j], ra);
150 }
151 }
152 }
153 }
154
155 /* Scatter store */
156 if (env->vtcm_pending) {
157 env->vtcm_pending = false;
158 if (env->vtcm_log.op) {
159 /* Need to perform the scatter read/modify/write at commit time */
160 if (env->vtcm_log.op_size == 2) {
161 SCATTER_OP_WRITE_TO_MEM(uint16_t);
162 } else if (env->vtcm_log.op_size == 4) {
163 /* Word Scatter += */
164 SCATTER_OP_WRITE_TO_MEM(uint32_t);
165 } else {
166 g_assert_not_reached();
167 }
168 } else {
169 for (int i = 0; i < sizeof(MMVector); i++) {
170 if (test_bit(i, env->vtcm_log.mask)) {
171 cpu_stb_data_ra(env, env->vtcm_log.va[i],
172 env->vtcm_log.data.ub[i], ra);
173 clear_bit(i, env->vtcm_log.mask);
174 env->vtcm_log.data.ub[i] = 0;
175 }
176
177 }
178 }
179 }
180 }
181
182 int32_t HELPER(fcircadd)(int32_t RxV, int32_t offset, int32_t M, int32_t CS)
183 {
184 uint32_t K_const = extract32(M, 24, 4);
185 uint32_t length = extract32(M, 0, 17);
186 uint32_t new_ptr = RxV + offset;
187 uint32_t start_addr;
188 uint32_t end_addr;
189
190 if (K_const == 0 && length >= 4) {
191 start_addr = CS;
192 end_addr = start_addr + length;
193 } else {
194 /*
195 * Versions v3 and earlier used the K value to specify a power-of-2 size
196 * 2^(K+2) that is greater than the buffer length
197 */
198 int32_t mask = (1 << (K_const + 2)) - 1;
199 start_addr = RxV & (~mask);
200 end_addr = start_addr | length;
201 }
202
203 if (new_ptr >= end_addr) {
204 new_ptr -= length;
205 } else if (new_ptr < start_addr) {
206 new_ptr += length;
207 }
208
209 return new_ptr;
210 }
211
212 uint32_t HELPER(fbrev)(uint32_t addr)
213 {
214 /*
215 * Bit reverse the low 16 bits of the address
216 */
217 return deposit32(addr, 0, 16, revbit16(addr));
218 }
219
220 static float32 build_float32(uint8_t sign, uint32_t exp, uint32_t mant)
221 {
222 return make_float32(
223 ((sign & 1) << 31) |
224 ((exp & 0xff) << SF_MANTBITS) |
225 (mant & ((1 << SF_MANTBITS) - 1)));
226 }
227
228 /*
229 * sfrecipa, sfinvsqrta have two 32-bit results
230 * r0,p0=sfrecipa(r1,r2)
231 * r0,p0=sfinvsqrta(r1)
232 *
233 * Since helpers can only return a single value, we pack the two results
234 * into a 64-bit value.
235 */
236 uint64_t HELPER(sfrecipa)(CPUHexagonState *env, float32 RsV, float32 RtV,
237 uint32_t pkt_need_commit)
238 {
239 int32_t PeV = 0;
240 float32 RdV;
241 int idx;
242 int adjust;
243 int mant;
244 int exp;
245
246 arch_fpop_start(env);
247 if (arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status)) {
248 PeV = adjust;
249 idx = (RtV >> 16) & 0x7f;
250 mant = (recip_lookup_table[idx] << 15) | 1;
251 exp = SF_BIAS - (float32_getexp(RtV) - SF_BIAS) - 1;
252 RdV = build_float32(extract32(RtV, 31, 1), exp, mant);
253 }
254 arch_fpop_end(env, pkt_need_commit);
255 return ((uint64_t)RdV << 32) | PeV;
256 }
257
258 uint64_t HELPER(sfinvsqrta)(CPUHexagonState *env, float32 RsV,
259 uint32_t pkt_need_commit)
260 {
261 int PeV = 0;
262 float32 RdV;
263 int idx;
264 int adjust;
265 int mant;
266 int exp;
267
268 arch_fpop_start(env);
269 if (arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status)) {
270 PeV = adjust;
271 idx = (RsV >> 17) & 0x7f;
272 mant = (invsqrt_lookup_table[idx] << 15);
273 exp = SF_BIAS - ((float32_getexp(RsV) - SF_BIAS) >> 1) - 1;
274 RdV = build_float32(extract32(RsV, 31, 1), exp, mant);
275 }
276 arch_fpop_end(env, pkt_need_commit);
277 return ((uint64_t)RdV << 32) | PeV;
278 }
279
280 int64_t HELPER(vacsh_val)(CPUHexagonState *env,
281 int64_t RxxV, int64_t RssV, int64_t RttV,
282 uint32_t pkt_need_commit)
283 {
284 for (int i = 0; i < 4; i++) {
285 int xv = sextract64(RxxV, i * 16, 16);
286 int sv = sextract64(RssV, i * 16, 16);
287 int tv = sextract64(RttV, i * 16, 16);
288 int max;
289 xv = xv + tv;
290 sv = sv - tv;
291 max = xv > sv ? xv : sv;
292 /* Note that fSATH can set the OVF bit in usr */
293 RxxV = deposit64(RxxV, i * 16, 16, fSATH(max));
294 }
295 return RxxV;
296 }
297
298 int32_t HELPER(vacsh_pred)(CPUHexagonState *env,
299 int64_t RxxV, int64_t RssV, int64_t RttV)
300 {
301 int32_t PeV = 0;
302 for (int i = 0; i < 4; i++) {
303 int xv = sextract64(RxxV, i * 16, 16);
304 int sv = sextract64(RssV, i * 16, 16);
305 int tv = sextract64(RttV, i * 16, 16);
306 xv = xv + tv;
307 sv = sv - tv;
308 PeV = deposit32(PeV, i * 2, 1, (xv > sv));
309 PeV = deposit32(PeV, i * 2 + 1, 1, (xv > sv));
310 }
311 return PeV;
312 }
313
314 int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV)
315 {
316 int64_t RddV = 0;
317 size4u_t state;
318 size4u_t valMPS;
319 size4u_t bitpos;
320 size4u_t range;
321 size4u_t offset;
322 size4u_t rLPS;
323 size4u_t rMPS;
324
325 state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0);
326 valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8);
327 bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0);
328 range = fGETWORD(0, RssV);
329 offset = fGETWORD(1, RssV);
330
331 /* calculate rLPS */
332 range <<= bitpos;
333 offset <<= bitpos;
334 rLPS = rLPS_table_64x4[state][(range >> 29) & 3];
335 rLPS = rLPS << 23; /* left aligned */
336
337 /* calculate rMPS */
338 rMPS = (range & 0xff800000) - rLPS;
339
340 /* most probable region */
341 if (offset < rMPS) {
342 RddV = AC_next_state_MPS_64[state];
343 fINSERT_RANGE(RddV, 8, 8, valMPS);
344 fINSERT_RANGE(RddV, 31, 23, (rMPS >> 23));
345 fSETWORD(1, RddV, offset);
346 }
347 /* least probable region */
348 else {
349 RddV = AC_next_state_LPS_64[state];
350 fINSERT_RANGE(RddV, 8, 8, ((!state) ? (1 - valMPS) : (valMPS)));
351 fINSERT_RANGE(RddV, 31, 23, (rLPS >> 23));
352 fSETWORD(1, RddV, (offset - rMPS));
353 }
354 return RddV;
355 }
356
357 int32_t HELPER(cabacdecbin_pred)(int64_t RssV, int64_t RttV)
358 {
359 int32_t p0 = 0;
360 size4u_t state;
361 size4u_t valMPS;
362 size4u_t bitpos;
363 size4u_t range;
364 size4u_t offset;
365 size4u_t rLPS;
366 size4u_t rMPS;
367
368 state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0);
369 valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8);
370 bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0);
371 range = fGETWORD(0, RssV);
372 offset = fGETWORD(1, RssV);
373
374 /* calculate rLPS */
375 range <<= bitpos;
376 offset <<= bitpos;
377 rLPS = rLPS_table_64x4[state][(range >> 29) & 3];
378 rLPS = rLPS << 23; /* left aligned */
379
380 /* calculate rMPS */
381 rMPS = (range & 0xff800000) - rLPS;
382
383 /* most probable region */
384 if (offset < rMPS) {
385 p0 = valMPS;
386
387 }
388 /* least probable region */
389 else {
390 p0 = valMPS ^ 1;
391 }
392 return p0;
393 }
394
395 static void probe_store(CPUHexagonState *env, int slot, int mmu_idx,
396 bool is_predicated, uintptr_t retaddr)
397 {
398 if (!is_predicated || !(env->slot_cancelled & (1 << slot))) {
399 uint32_t width = env->mem_log_stores[slot].width;
400 target_ulong va = env->mem_log_stores[slot].va;
401 probe_write(env, va, width, mmu_idx, retaddr);
402 }
403 }
404
405 /*
406 * Called from a mem_noshuf packet to make sure the load doesn't
407 * raise an exception
408 */
409 void HELPER(probe_noshuf_load)(CPUHexagonState *env, target_ulong va,
410 int size, int mmu_idx)
411 {
412 uintptr_t retaddr = GETPC();
413 probe_read(env, va, size, mmu_idx, retaddr);
414 }
415
416 /* Called during packet commit when there are two scalar stores */
417 void HELPER(probe_pkt_scalar_store_s0)(CPUHexagonState *env, int args)
418 {
419 int mmu_idx = FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, MMU_IDX);
420 bool is_predicated =
421 FIELD_EX32(args, PROBE_PKT_SCALAR_STORE_S0, IS_PREDICATED);
422 uintptr_t ra = GETPC();
423 probe_store(env, 0, mmu_idx, is_predicated, ra);
424 }
425
426 static void probe_hvx_stores(CPUHexagonState *env, int mmu_idx,
427 uintptr_t retaddr)
428 {
429 /* Normal (possibly masked) vector store */
430 for (int i = 0; i < VSTORES_MAX; i++) {
431 if (env->vstore_pending[i]) {
432 target_ulong va = env->vstore[i].va;
433 int size = env->vstore[i].size;
434 for (int j = 0; j < size; j++) {
435 if (test_bit(j, env->vstore[i].mask)) {
436 probe_write(env, va + j, 1, mmu_idx, retaddr);
437 }
438 }
439 }
440 }
441
442 /* Scatter store */
443 if (env->vtcm_pending) {
444 if (env->vtcm_log.op) {
445 /* Need to perform the scatter read/modify/write at commit time */
446 if (env->vtcm_log.op_size == 2) {
447 SCATTER_OP_PROBE_MEM(size2u_t, mmu_idx, retaddr);
448 } else if (env->vtcm_log.op_size == 4) {
449 /* Word Scatter += */
450 SCATTER_OP_PROBE_MEM(size4u_t, mmu_idx, retaddr);
451 } else {
452 g_assert_not_reached();
453 }
454 } else {
455 for (int i = 0; i < sizeof(MMVector); i++) {
456 if (test_bit(i, env->vtcm_log.mask)) {
457 probe_write(env, env->vtcm_log.va[i], 1, mmu_idx, retaddr);
458 }
459
460 }
461 }
462 }
463 }
464
465 void HELPER(probe_hvx_stores)(CPUHexagonState *env, int mmu_idx)
466 {
467 uintptr_t retaddr = GETPC();
468 probe_hvx_stores(env, mmu_idx, retaddr);
469 }
470
471 void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask)
472 {
473 bool has_st0 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST0);
474 bool has_st1 = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_ST1);
475 bool has_hvx_stores =
476 FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, HAS_HVX_STORES);
477 bool s0_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S0_IS_PRED);
478 bool s1_is_pred = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, S1_IS_PRED);
479 int mmu_idx = FIELD_EX32(mask, PROBE_PKT_SCALAR_HVX_STORES, MMU_IDX);
480 uintptr_t ra = GETPC();
481
482 if (has_st0) {
483 probe_store(env, 0, mmu_idx, s0_is_pred, ra);
484 }
485 if (has_st1) {
486 probe_store(env, 1, mmu_idx, s1_is_pred, ra);
487 }
488 if (has_hvx_stores) {
489 probe_hvx_stores(env, mmu_idx, ra);
490 }
491 }
492
493 #ifndef CONFIG_HEXAGON_IDEF_PARSER
494 /*
495 * mem_noshuf
496 * Section 5.5 of the Hexagon V67 Programmer's Reference Manual
497 *
498 * If the load is in slot 0 and there is a store in slot1 (that
499 * wasn't cancelled), we have to do the store first.
500 */
501 static void check_noshuf(CPUHexagonState *env, bool pkt_has_scalar_store_s1,
502 uint32_t slot, target_ulong vaddr, int size,
503 uintptr_t ra)
504 {
505 if (slot == 0 && pkt_has_scalar_store_s1 &&
506 ((env->slot_cancelled & (1 << 1)) == 0)) {
507 probe_read(env, vaddr, size, MMU_USER_IDX, ra);
508 commit_store(env, 1, ra);
509 }
510 }
511 #endif
512
513 /* Floating point */
514 float64 HELPER(conv_sf2df)(CPUHexagonState *env, float32 RsV,
515 uint32_t pkt_need_commit)
516 {
517 float64 out_f64;
518 arch_fpop_start(env);
519 out_f64 = float32_to_float64(RsV, &env->fp_status);
520 arch_fpop_end(env, pkt_need_commit);
521 return out_f64;
522 }
523
524 float32 HELPER(conv_df2sf)(CPUHexagonState *env, float64 RssV,
525 uint32_t pkt_need_commit)
526 {
527 float32 out_f32;
528 arch_fpop_start(env);
529 out_f32 = float64_to_float32(RssV, &env->fp_status);
530 arch_fpop_end(env, pkt_need_commit);
531 return out_f32;
532 }
533
534 float32 HELPER(conv_uw2sf)(CPUHexagonState *env, int32_t RsV,
535 uint32_t pkt_need_commit)
536 {
537 float32 RdV;
538 arch_fpop_start(env);
539 RdV = uint32_to_float32(RsV, &env->fp_status);
540 arch_fpop_end(env, pkt_need_commit);
541 return RdV;
542 }
543
544 float64 HELPER(conv_uw2df)(CPUHexagonState *env, int32_t RsV,
545 uint32_t pkt_need_commit)
546 {
547 float64 RddV;
548 arch_fpop_start(env);
549 RddV = uint32_to_float64(RsV, &env->fp_status);
550 arch_fpop_end(env, pkt_need_commit);
551 return RddV;
552 }
553
554 float32 HELPER(conv_w2sf)(CPUHexagonState *env, int32_t RsV,
555 uint32_t pkt_need_commit)
556 {
557 float32 RdV;
558 arch_fpop_start(env);
559 RdV = int32_to_float32(RsV, &env->fp_status);
560 arch_fpop_end(env, pkt_need_commit);
561 return RdV;
562 }
563
564 float64 HELPER(conv_w2df)(CPUHexagonState *env, int32_t RsV,
565 uint32_t pkt_need_commit)
566 {
567 float64 RddV;
568 arch_fpop_start(env);
569 RddV = int32_to_float64(RsV, &env->fp_status);
570 arch_fpop_end(env, pkt_need_commit);
571 return RddV;
572 }
573
574 float32 HELPER(conv_ud2sf)(CPUHexagonState *env, int64_t RssV,
575 uint32_t pkt_need_commit)
576 {
577 float32 RdV;
578 arch_fpop_start(env);
579 RdV = uint64_to_float32(RssV, &env->fp_status);
580 arch_fpop_end(env, pkt_need_commit);
581 return RdV;
582 }
583
584 float64 HELPER(conv_ud2df)(CPUHexagonState *env, int64_t RssV,
585 uint32_t pkt_need_commit)
586 {
587 float64 RddV;
588 arch_fpop_start(env);
589 RddV = uint64_to_float64(RssV, &env->fp_status);
590 arch_fpop_end(env, pkt_need_commit);
591 return RddV;
592 }
593
594 float32 HELPER(conv_d2sf)(CPUHexagonState *env, int64_t RssV,
595 uint32_t pkt_need_commit)
596 {
597 float32 RdV;
598 arch_fpop_start(env);
599 RdV = int64_to_float32(RssV, &env->fp_status);
600 arch_fpop_end(env, pkt_need_commit);
601 return RdV;
602 }
603
604 float64 HELPER(conv_d2df)(CPUHexagonState *env, int64_t RssV,
605 uint32_t pkt_need_commit)
606 {
607 float64 RddV;
608 arch_fpop_start(env);
609 RddV = int64_to_float64(RssV, &env->fp_status);
610 arch_fpop_end(env, pkt_need_commit);
611 return RddV;
612 }
613
614 uint32_t HELPER(conv_sf2uw)(CPUHexagonState *env, float32 RsV,
615 uint32_t pkt_need_commit)
616 {
617 uint32_t RdV;
618 arch_fpop_start(env);
619 /* Hexagon checks the sign before rounding */
620 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
621 float_raise(float_flag_invalid, &env->fp_status);
622 RdV = 0;
623 } else {
624 RdV = float32_to_uint32(RsV, &env->fp_status);
625 }
626 arch_fpop_end(env, pkt_need_commit);
627 return RdV;
628 }
629
630 int32_t HELPER(conv_sf2w)(CPUHexagonState *env, float32 RsV,
631 uint32_t pkt_need_commit)
632 {
633 int32_t RdV;
634 arch_fpop_start(env);
635 /* Hexagon returns -1 for NaN */
636 if (float32_is_any_nan(RsV)) {
637 float_raise(float_flag_invalid, &env->fp_status);
638 RdV = -1;
639 } else {
640 RdV = float32_to_int32(RsV, &env->fp_status);
641 }
642 arch_fpop_end(env, pkt_need_commit);
643 return RdV;
644 }
645
646 uint64_t HELPER(conv_sf2ud)(CPUHexagonState *env, float32 RsV,
647 uint32_t pkt_need_commit)
648 {
649 uint64_t RddV;
650 arch_fpop_start(env);
651 /* Hexagon checks the sign before rounding */
652 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
653 float_raise(float_flag_invalid, &env->fp_status);
654 RddV = 0;
655 } else {
656 RddV = float32_to_uint64(RsV, &env->fp_status);
657 }
658 arch_fpop_end(env, pkt_need_commit);
659 return RddV;
660 }
661
662 int64_t HELPER(conv_sf2d)(CPUHexagonState *env, float32 RsV,
663 uint32_t pkt_need_commit)
664 {
665 int64_t RddV;
666 arch_fpop_start(env);
667 /* Hexagon returns -1 for NaN */
668 if (float32_is_any_nan(RsV)) {
669 float_raise(float_flag_invalid, &env->fp_status);
670 RddV = -1;
671 } else {
672 RddV = float32_to_int64(RsV, &env->fp_status);
673 }
674 arch_fpop_end(env, pkt_need_commit);
675 return RddV;
676 }
677
678 uint32_t HELPER(conv_df2uw)(CPUHexagonState *env, float64 RssV,
679 uint32_t pkt_need_commit)
680 {
681 uint32_t RdV;
682 arch_fpop_start(env);
683 /* Hexagon checks the sign before rounding */
684 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
685 float_raise(float_flag_invalid, &env->fp_status);
686 RdV = 0;
687 } else {
688 RdV = float64_to_uint32(RssV, &env->fp_status);
689 }
690 arch_fpop_end(env, pkt_need_commit);
691 return RdV;
692 }
693
694 int32_t HELPER(conv_df2w)(CPUHexagonState *env, float64 RssV,
695 uint32_t pkt_need_commit)
696 {
697 int32_t RdV;
698 arch_fpop_start(env);
699 /* Hexagon returns -1 for NaN */
700 if (float64_is_any_nan(RssV)) {
701 float_raise(float_flag_invalid, &env->fp_status);
702 RdV = -1;
703 } else {
704 RdV = float64_to_int32(RssV, &env->fp_status);
705 }
706 arch_fpop_end(env, pkt_need_commit);
707 return RdV;
708 }
709
710 uint64_t HELPER(conv_df2ud)(CPUHexagonState *env, float64 RssV,
711 uint32_t pkt_need_commit)
712 {
713 uint64_t RddV;
714 arch_fpop_start(env);
715 /* Hexagon checks the sign before rounding */
716 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
717 float_raise(float_flag_invalid, &env->fp_status);
718 RddV = 0;
719 } else {
720 RddV = float64_to_uint64(RssV, &env->fp_status);
721 }
722 arch_fpop_end(env, pkt_need_commit);
723 return RddV;
724 }
725
726 int64_t HELPER(conv_df2d)(CPUHexagonState *env, float64 RssV,
727 uint32_t pkt_need_commit)
728 {
729 int64_t RddV;
730 arch_fpop_start(env);
731 /* Hexagon returns -1 for NaN */
732 if (float64_is_any_nan(RssV)) {
733 float_raise(float_flag_invalid, &env->fp_status);
734 RddV = -1;
735 } else {
736 RddV = float64_to_int64(RssV, &env->fp_status);
737 }
738 arch_fpop_end(env, pkt_need_commit);
739 return RddV;
740 }
741
742 uint32_t HELPER(conv_sf2uw_chop)(CPUHexagonState *env, float32 RsV,
743 uint32_t pkt_need_commit)
744 {
745 uint32_t RdV;
746 arch_fpop_start(env);
747 /* Hexagon checks the sign before rounding */
748 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
749 float_raise(float_flag_invalid, &env->fp_status);
750 RdV = 0;
751 } else {
752 RdV = float32_to_uint32_round_to_zero(RsV, &env->fp_status);
753 }
754 arch_fpop_end(env, pkt_need_commit);
755 return RdV;
756 }
757
758 int32_t HELPER(conv_sf2w_chop)(CPUHexagonState *env, float32 RsV,
759 uint32_t pkt_need_commit)
760 {
761 int32_t RdV;
762 arch_fpop_start(env);
763 /* Hexagon returns -1 for NaN */
764 if (float32_is_any_nan(RsV)) {
765 float_raise(float_flag_invalid, &env->fp_status);
766 RdV = -1;
767 } else {
768 RdV = float32_to_int32_round_to_zero(RsV, &env->fp_status);
769 }
770 arch_fpop_end(env, pkt_need_commit);
771 return RdV;
772 }
773
774 uint64_t HELPER(conv_sf2ud_chop)(CPUHexagonState *env, float32 RsV,
775 uint32_t pkt_need_commit)
776 {
777 uint64_t RddV;
778 arch_fpop_start(env);
779 /* Hexagon checks the sign before rounding */
780 if (float32_is_neg(RsV) && !float32_is_any_nan(RsV) && !float32_is_zero(RsV)) {
781 float_raise(float_flag_invalid, &env->fp_status);
782 RddV = 0;
783 } else {
784 RddV = float32_to_uint64_round_to_zero(RsV, &env->fp_status);
785 }
786 arch_fpop_end(env, pkt_need_commit);
787 return RddV;
788 }
789
790 int64_t HELPER(conv_sf2d_chop)(CPUHexagonState *env, float32 RsV,
791 uint32_t pkt_need_commit)
792 {
793 int64_t RddV;
794 arch_fpop_start(env);
795 /* Hexagon returns -1 for NaN */
796 if (float32_is_any_nan(RsV)) {
797 float_raise(float_flag_invalid, &env->fp_status);
798 RddV = -1;
799 } else {
800 RddV = float32_to_int64_round_to_zero(RsV, &env->fp_status);
801 }
802 arch_fpop_end(env, pkt_need_commit);
803 return RddV;
804 }
805
806 uint32_t HELPER(conv_df2uw_chop)(CPUHexagonState *env, float64 RssV,
807 uint32_t pkt_need_commit)
808 {
809 uint32_t RdV;
810 arch_fpop_start(env);
811 /* Hexagon checks the sign before rounding */
812 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
813 float_raise(float_flag_invalid, &env->fp_status);
814 RdV = 0;
815 } else {
816 RdV = float64_to_uint32_round_to_zero(RssV, &env->fp_status);
817 }
818 arch_fpop_end(env, pkt_need_commit);
819 return RdV;
820 }
821
822 int32_t HELPER(conv_df2w_chop)(CPUHexagonState *env, float64 RssV,
823 uint32_t pkt_need_commit)
824 {
825 int32_t RdV;
826 arch_fpop_start(env);
827 /* Hexagon returns -1 for NaN */
828 if (float64_is_any_nan(RssV)) {
829 float_raise(float_flag_invalid, &env->fp_status);
830 RdV = -1;
831 } else {
832 RdV = float64_to_int32_round_to_zero(RssV, &env->fp_status);
833 }
834 arch_fpop_end(env, pkt_need_commit);
835 return RdV;
836 }
837
838 uint64_t HELPER(conv_df2ud_chop)(CPUHexagonState *env, float64 RssV,
839 uint32_t pkt_need_commit)
840 {
841 uint64_t RddV;
842 arch_fpop_start(env);
843 /* Hexagon checks the sign before rounding */
844 if (float64_is_neg(RssV) && !float64_is_any_nan(RssV) && !float64_is_zero(RssV)) {
845 float_raise(float_flag_invalid, &env->fp_status);
846 RddV = 0;
847 } else {
848 RddV = float64_to_uint64_round_to_zero(RssV, &env->fp_status);
849 }
850 arch_fpop_end(env, pkt_need_commit);
851 return RddV;
852 }
853
854 int64_t HELPER(conv_df2d_chop)(CPUHexagonState *env, float64 RssV,
855 uint32_t pkt_need_commit)
856 {
857 int64_t RddV;
858 arch_fpop_start(env);
859 /* Hexagon returns -1 for NaN */
860 if (float64_is_any_nan(RssV)) {
861 float_raise(float_flag_invalid, &env->fp_status);
862 RddV = -1;
863 } else {
864 RddV = float64_to_int64_round_to_zero(RssV, &env->fp_status);
865 }
866 arch_fpop_end(env, pkt_need_commit);
867 return RddV;
868 }
869
870 float32 HELPER(sfadd)(CPUHexagonState *env, float32 RsV, float32 RtV,
871 uint32_t pkt_need_commit)
872 {
873 float32 RdV;
874 arch_fpop_start(env);
875 RdV = float32_add(RsV, RtV, &env->fp_status);
876 arch_fpop_end(env, pkt_need_commit);
877 return RdV;
878 }
879
880 float32 HELPER(sfsub)(CPUHexagonState *env, float32 RsV, float32 RtV,
881 uint32_t pkt_need_commit)
882 {
883 float32 RdV;
884 arch_fpop_start(env);
885 RdV = float32_sub(RsV, RtV, &env->fp_status);
886 arch_fpop_end(env, pkt_need_commit);
887 return RdV;
888 }
889
890 int32_t HELPER(sfcmpeq)(CPUHexagonState *env, float32 RsV, float32 RtV,
891 uint32_t pkt_need_commit)
892 {
893 int32_t PdV;
894 arch_fpop_start(env);
895 PdV = f8BITSOF(float32_eq_quiet(RsV, RtV, &env->fp_status));
896 arch_fpop_end(env, pkt_need_commit);
897 return PdV;
898 }
899
900 int32_t HELPER(sfcmpgt)(CPUHexagonState *env, float32 RsV, float32 RtV,
901 uint32_t pkt_need_commit)
902 {
903 int cmp;
904 int32_t PdV;
905 arch_fpop_start(env);
906 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status);
907 PdV = f8BITSOF(cmp == float_relation_greater);
908 arch_fpop_end(env, pkt_need_commit);
909 return PdV;
910 }
911
912 int32_t HELPER(sfcmpge)(CPUHexagonState *env, float32 RsV, float32 RtV,
913 uint32_t pkt_need_commit)
914 {
915 int cmp;
916 int32_t PdV;
917 arch_fpop_start(env);
918 cmp = float32_compare_quiet(RsV, RtV, &env->fp_status);
919 PdV = f8BITSOF(cmp == float_relation_greater ||
920 cmp == float_relation_equal);
921 arch_fpop_end(env, pkt_need_commit);
922 return PdV;
923 }
924
925 int32_t HELPER(sfcmpuo)(CPUHexagonState *env, float32 RsV, float32 RtV,
926 uint32_t pkt_need_commit)
927 {
928 int32_t PdV;
929 arch_fpop_start(env);
930 PdV = f8BITSOF(float32_unordered_quiet(RsV, RtV, &env->fp_status));
931 arch_fpop_end(env, pkt_need_commit);
932 return PdV;
933 }
934
935 float32 HELPER(sfmax)(CPUHexagonState *env, float32 RsV, float32 RtV,
936 uint32_t pkt_need_commit)
937 {
938 float32 RdV;
939 arch_fpop_start(env);
940 RdV = float32_maximum_number(RsV, RtV, &env->fp_status);
941 arch_fpop_end(env, pkt_need_commit);
942 return RdV;
943 }
944
945 float32 HELPER(sfmin)(CPUHexagonState *env, float32 RsV, float32 RtV,
946 uint32_t pkt_need_commit)
947 {
948 float32 RdV;
949 arch_fpop_start(env);
950 RdV = float32_minimum_number(RsV, RtV, &env->fp_status);
951 arch_fpop_end(env, pkt_need_commit);
952 return RdV;
953 }
954
955 int32_t HELPER(sfclass)(CPUHexagonState *env, float32 RsV, int32_t uiV,
956 uint32_t pkt_need_commit)
957 {
958 int32_t PdV = 0;
959 arch_fpop_start(env);
960 if (fGETBIT(0, uiV) && float32_is_zero(RsV)) {
961 PdV = 0xff;
962 }
963 if (fGETBIT(1, uiV) && float32_is_normal(RsV)) {
964 PdV = 0xff;
965 }
966 if (fGETBIT(2, uiV) && float32_is_denormal(RsV)) {
967 PdV = 0xff;
968 }
969 if (fGETBIT(3, uiV) && float32_is_infinity(RsV)) {
970 PdV = 0xff;
971 }
972 if (fGETBIT(4, uiV) && float32_is_any_nan(RsV)) {
973 PdV = 0xff;
974 }
975 set_float_exception_flags(0, &env->fp_status);
976 arch_fpop_end(env, pkt_need_commit);
977 return PdV;
978 }
979
980 float32 HELPER(sffixupn)(CPUHexagonState *env, float32 RsV, float32 RtV,
981 uint32_t pkt_need_commit)
982 {
983 float32 RdV = 0;
984 int adjust;
985 arch_fpop_start(env);
986 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status);
987 RdV = RsV;
988 arch_fpop_end(env, pkt_need_commit);
989 return RdV;
990 }
991
992 float32 HELPER(sffixupd)(CPUHexagonState *env, float32 RsV, float32 RtV,
993 uint32_t pkt_need_commit)
994 {
995 float32 RdV = 0;
996 int adjust;
997 arch_fpop_start(env);
998 arch_sf_recip_common(&RsV, &RtV, &RdV, &adjust, &env->fp_status);
999 RdV = RtV;
1000 arch_fpop_end(env, pkt_need_commit);
1001 return RdV;
1002 }
1003
1004 float32 HELPER(sffixupr)(CPUHexagonState *env, float32 RsV,
1005 uint32_t pkt_need_commit)
1006 {
1007 float32 RdV = 0;
1008 int adjust;
1009 arch_fpop_start(env);
1010 arch_sf_invsqrt_common(&RsV, &RdV, &adjust, &env->fp_status);
1011 RdV = RsV;
1012 arch_fpop_end(env, pkt_need_commit);
1013 return RdV;
1014 }
1015
1016 float64 HELPER(dfadd)(CPUHexagonState *env, float64 RssV, float64 RttV,
1017 uint32_t pkt_need_commit)
1018 {
1019 float64 RddV;
1020 arch_fpop_start(env);
1021 RddV = float64_add(RssV, RttV, &env->fp_status);
1022 arch_fpop_end(env, pkt_need_commit);
1023 return RddV;
1024 }
1025
1026 float64 HELPER(dfsub)(CPUHexagonState *env, float64 RssV, float64 RttV,
1027 uint32_t pkt_need_commit)
1028 {
1029 float64 RddV;
1030 arch_fpop_start(env);
1031 RddV = float64_sub(RssV, RttV, &env->fp_status);
1032 arch_fpop_end(env, pkt_need_commit);
1033 return RddV;
1034 }
1035
1036 float64 HELPER(dfmax)(CPUHexagonState *env, float64 RssV, float64 RttV,
1037 uint32_t pkt_need_commit)
1038 {
1039 float64 RddV;
1040 arch_fpop_start(env);
1041 RddV = float64_maximum_number(RssV, RttV, &env->fp_status);
1042 arch_fpop_end(env, pkt_need_commit);
1043 return RddV;
1044 }
1045
1046 float64 HELPER(dfmin)(CPUHexagonState *env, float64 RssV, float64 RttV,
1047 uint32_t pkt_need_commit)
1048 {
1049 float64 RddV;
1050 arch_fpop_start(env);
1051 RddV = float64_minimum_number(RssV, RttV, &env->fp_status);
1052 arch_fpop_end(env, pkt_need_commit);
1053 return RddV;
1054 }
1055
1056 int32_t HELPER(dfcmpeq)(CPUHexagonState *env, float64 RssV, float64 RttV,
1057 uint32_t pkt_need_commit)
1058 {
1059 int32_t PdV;
1060 arch_fpop_start(env);
1061 PdV = f8BITSOF(float64_eq_quiet(RssV, RttV, &env->fp_status));
1062 arch_fpop_end(env, pkt_need_commit);
1063 return PdV;
1064 }
1065
1066 int32_t HELPER(dfcmpgt)(CPUHexagonState *env, float64 RssV, float64 RttV,
1067 uint32_t pkt_need_commit)
1068 {
1069 int cmp;
1070 int32_t PdV;
1071 arch_fpop_start(env);
1072 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status);
1073 PdV = f8BITSOF(cmp == float_relation_greater);
1074 arch_fpop_end(env, pkt_need_commit);
1075 return PdV;
1076 }
1077
1078 int32_t HELPER(dfcmpge)(CPUHexagonState *env, float64 RssV, float64 RttV,
1079 uint32_t pkt_need_commit)
1080 {
1081 int cmp;
1082 int32_t PdV;
1083 arch_fpop_start(env);
1084 cmp = float64_compare_quiet(RssV, RttV, &env->fp_status);
1085 PdV = f8BITSOF(cmp == float_relation_greater ||
1086 cmp == float_relation_equal);
1087 arch_fpop_end(env, pkt_need_commit);
1088 return PdV;
1089 }
1090
1091 int32_t HELPER(dfcmpuo)(CPUHexagonState *env, float64 RssV, float64 RttV,
1092 uint32_t pkt_need_commit)
1093 {
1094 int32_t PdV;
1095 arch_fpop_start(env);
1096 PdV = f8BITSOF(float64_unordered_quiet(RssV, RttV, &env->fp_status));
1097 arch_fpop_end(env, pkt_need_commit);
1098 return PdV;
1099 }
1100
1101 int32_t HELPER(dfclass)(CPUHexagonState *env, float64 RssV, int32_t uiV,
1102 uint32_t pkt_need_commit)
1103 {
1104 int32_t PdV = 0;
1105 arch_fpop_start(env);
1106 if (fGETBIT(0, uiV) && float64_is_zero(RssV)) {
1107 PdV = 0xff;
1108 }
1109 if (fGETBIT(1, uiV) && float64_is_normal(RssV)) {
1110 PdV = 0xff;
1111 }
1112 if (fGETBIT(2, uiV) && float64_is_denormal(RssV)) {
1113 PdV = 0xff;
1114 }
1115 if (fGETBIT(3, uiV) && float64_is_infinity(RssV)) {
1116 PdV = 0xff;
1117 }
1118 if (fGETBIT(4, uiV) && float64_is_any_nan(RssV)) {
1119 PdV = 0xff;
1120 }
1121 set_float_exception_flags(0, &env->fp_status);
1122 arch_fpop_end(env, pkt_need_commit);
1123 return PdV;
1124 }
1125
1126 float32 HELPER(sfmpy)(CPUHexagonState *env, float32 RsV, float32 RtV,
1127 uint32_t pkt_need_commit)
1128 {
1129 float32 RdV;
1130 arch_fpop_start(env);
1131 RdV = float32_mul(RsV, RtV, &env->fp_status);
1132 arch_fpop_end(env, pkt_need_commit);
1133 return RdV;
1134 }
1135
1136 float32 HELPER(sffma)(CPUHexagonState *env, float32 RxV,
1137 float32 RsV, float32 RtV,
1138 uint32_t pkt_need_commit)
1139 {
1140 arch_fpop_start(env);
1141 RxV = float32_muladd(RsV, RtV, RxV, 0, &env->fp_status);
1142 arch_fpop_end(env, pkt_need_commit);
1143 return RxV;
1144 }
1145
1146 float32 HELPER(sffma_sc)(CPUHexagonState *env, float32 RxV,
1147 float32 RsV, float32 RtV, float32 PuV,
1148 uint32_t pkt_need_commit)
1149 {
1150 arch_fpop_start(env);
1151 RxV = float32_muladd_scalbn(RsV, RtV, RxV, fSXTN(8, 64, PuV),
1152 float_muladd_suppress_add_product_zero,
1153 &env->fp_status);
1154 arch_fpop_end(env, pkt_need_commit);
1155 return RxV;
1156 }
1157
1158 float32 HELPER(sffms)(CPUHexagonState *env, float32 RxV,
1159 float32 RsV, float32 RtV, uint32_t pkt_need_commit)
1160 {
1161 arch_fpop_start(env);
1162 RxV = float32_muladd(RsV, RtV, RxV, float_muladd_negate_product,
1163 &env->fp_status);
1164 arch_fpop_end(env, pkt_need_commit);
1165 return RxV;
1166 }
1167
1168 static float32 do_sffma_lib(CPUHexagonState *env, float32 RxV,
1169 float32 RsV, float32 RtV, int negate,
1170 uint32_t pkt_need_commit)
1171 {
1172 int flags;
1173
1174 arch_fpop_start(env);
1175
1176 set_float_rounding_mode(float_round_nearest_even_max, &env->fp_status);
1177 RxV = float32_muladd(RsV, RtV, RxV,
1178 negate | float_muladd_suppress_add_product_zero,
1179 &env->fp_status);
1180
1181 flags = get_float_exception_flags(&env->fp_status);
1182 if (flags) {
1183 /* Flags are suppressed by this instruction. */
1184 set_float_exception_flags(0, &env->fp_status);
1185
1186 /* Return 0 for Inf - Inf. */
1187 if (flags & float_flag_invalid_isi) {
1188 RxV = 0;
1189 }
1190 }
1191
1192 arch_fpop_end(env, pkt_need_commit);
1193 return RxV;
1194 }
1195
1196 float32 HELPER(sffma_lib)(CPUHexagonState *env, float32 RxV,
1197 float32 RsV, float32 RtV, uint32_t pkt_need_commit)
1198 {
1199 return do_sffma_lib(env, RxV, RsV, RtV, 0, pkt_need_commit);
1200 }
1201
1202 float32 HELPER(sffms_lib)(CPUHexagonState *env, float32 RxV,
1203 float32 RsV, float32 RtV, uint32_t pkt_need_commit)
1204 {
1205 return do_sffma_lib(env, RxV, RsV, RtV, float_muladd_negate_product,
1206 pkt_need_commit);
1207 }
1208
1209 float64 HELPER(dfmpyfix)(CPUHexagonState *env, float64 RssV, float64 RttV,
1210 uint32_t pkt_need_commit)
1211 {
1212 int64_t RddV;
1213 arch_fpop_start(env);
1214 if (float64_is_denormal(RssV) &&
1215 (float64_getexp(RttV) >= 512) &&
1216 float64_is_normal(RttV)) {
1217 RddV = float64_mul(RssV, make_float64(0x4330000000000000),
1218 &env->fp_status);
1219 } else if (float64_is_denormal(RttV) &&
1220 (float64_getexp(RssV) >= 512) &&
1221 float64_is_normal(RssV)) {
1222 RddV = float64_mul(RssV, make_float64(0x3cb0000000000000),
1223 &env->fp_status);
1224 } else {
1225 RddV = RssV;
1226 }
1227 arch_fpop_end(env, pkt_need_commit);
1228 return RddV;
1229 }
1230
1231 float64 HELPER(dfmpyhh)(CPUHexagonState *env, float64 RxxV,
1232 float64 RssV, float64 RttV, uint32_t pkt_need_commit)
1233 {
1234 arch_fpop_start(env);
1235 RxxV = internal_mpyhh(RssV, RttV, RxxV, &env->fp_status);
1236 arch_fpop_end(env, pkt_need_commit);
1237 return RxxV;
1238 }
1239
1240 #ifndef CONFIG_USER_ONLY
1241 void HELPER(modify_ssr)(CPUHexagonState *env, uint32_t new, uint32_t old)
1242 {
1243 BQL_LOCK_GUARD();
1244 hexagon_modify_ssr(env, new, old);
1245 }
1246
1247 static void hex_k0_lock(CPUHexagonState *env)
1248 {
1249 HexagonCPU *cpu = env_archcpu(env);
1250 CPUState *cs = env_cpu(env);
1251 target_ulong syscfg;
1252
1253 BQL_LOCK_GUARD();
1254 g_assert((env->k0_lock_count == 0) || (env->k0_lock_count == 1));
1255
1256 syscfg = cpu->globalregs ?
1257 hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
1258 env->threadId) : 0;
1259 if (GET_SYSCFG_FIELD(SYSCFG_K0LOCK, syscfg)) {
1260 if (env->k0_lock_state == HEX_LOCK_QUEUED) {
1261 env->next_PC += 4;
1262 env->k0_lock_count++;
1263 env->k0_lock_state = HEX_LOCK_OWNER;
1264 SET_SYSCFG_FIELD(env, SYSCFG_K0LOCK, 1);
1265 return;
1266 }
1267 if (env->k0_lock_state == HEX_LOCK_OWNER) {
1268 qemu_log_mask(LOG_GUEST_ERROR,
1269 "Double k0lock at PC: 0x%" PRIx32
1270 ", thread may hang\n",
1271 env->next_PC);
1272 env->next_PC += 4;
1273 cpu_interrupt(cs, CPU_INTERRUPT_HALT);
1274 cpu_loop_exit(cs);
1275 return;
1276 }
1277 env->k0_lock_state = HEX_LOCK_WAITING;
1278 cpu_interrupt(cs, CPU_INTERRUPT_HALT);
1279 cpu_loop_exit(cs);
1280 } else {
1281 env->next_PC += 4;
1282 env->k0_lock_count++;
1283 env->k0_lock_state = HEX_LOCK_OWNER;
1284 SET_SYSCFG_FIELD(env, SYSCFG_K0LOCK, 1);
1285 }
1286 }
1287
1288 static void hex_k0_unlock(CPUHexagonState *env)
1289 {
1290 HexagonCPU *cpu = env_archcpu(env);
1291 unsigned int this_threadId = env->threadId;
1292 CPUHexagonState *unlock_thread = NULL;
1293 CPUState *cs;
1294 target_ulong syscfg;
1295
1296 BQL_LOCK_GUARD();
1297 g_assert((env->k0_lock_count == 0) || (env->k0_lock_count == 1));
1298
1299 /* Nothing to do if the k0 isn't locked by this thread */
1300 syscfg = cpu->globalregs ?
1301 hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SYSCFG,
1302 env->threadId) : 0;
1303 if ((GET_SYSCFG_FIELD(SYSCFG_K0LOCK, syscfg) == 0) ||
1304 (env->k0_lock_state != HEX_LOCK_OWNER)) {
1305 qemu_log_mask(LOG_GUEST_ERROR,
1306 "thread %" PRIu32 " attempted to unlock k0 without"
1307 " having the lock, k0_lock state = %u,"
1308 " syscfg:k0 = %" PRIu32 "\n",
1309 env->threadId, (unsigned)env->k0_lock_state,
1310 (uint32_t)GET_SYSCFG_FIELD(SYSCFG_K0LOCK, syscfg));
1311 g_assert(env->k0_lock_state != HEX_LOCK_WAITING);
1312 return;
1313 }
1314
1315 env->k0_lock_count--;
1316 env->k0_lock_state = HEX_LOCK_UNLOCKED;
1317 SET_SYSCFG_FIELD(env, SYSCFG_K0LOCK, 0);
1318
1319 /* Look for a thread to unlock */
1320 CPU_FOREACH(cs) {
1321 CPUHexagonState *thread = cpu_env(cs);
1322
1323 /*
1324 * The hardware implements round-robin fairness, so we look for threads
1325 * starting at env->threadId + 1 and incrementing modulo the number of
1326 * threads.
1327 *
1328 * To implement this, we check if thread is a earlier in the modulo
1329 * sequence than unlock_thread.
1330 * if unlock thread is higher than this thread
1331 * thread must be between this thread and unlock_thread
1332 * else
1333 * thread higher than this thread is ahead of unlock_thread
1334 * thread must be lower then unlock thread
1335 */
1336 if (thread->k0_lock_state == HEX_LOCK_WAITING) {
1337 if (!unlock_thread) {
1338 unlock_thread = thread;
1339 } else if (unlock_thread->threadId > this_threadId) {
1340 if (this_threadId < thread->threadId &&
1341 thread->threadId < unlock_thread->threadId) {
1342 unlock_thread = thread;
1343 }
1344 } else {
1345 if (thread->threadId > this_threadId) {
1346 unlock_thread = thread;
1347 }
1348 if (thread->threadId < unlock_thread->threadId) {
1349 unlock_thread = thread;
1350 }
1351 }
1352 }
1353 }
1354 if (unlock_thread) {
1355 cs = env_cpu(unlock_thread);
1356 unlock_thread->k0_lock_state = HEX_LOCK_QUEUED;
1357 SET_SYSCFG_FIELD(unlock_thread, SYSCFG_K0LOCK, 1);
1358 cpu_interrupt(cs, CPU_INTERRUPT_K0_UNLOCK);
1359 }
1360
1361 }
1362 #endif
1363
1364
1365 /* Histogram instructions */
1366
1367 void HELPER(vhist)(CPUHexagonState *env)
1368 {
1369 MMVector *input = &env->tmp_VRegs[0];
1370
1371 for (int lane = 0; lane < 8; lane++) {
1372 for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
1373 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
1374 unsigned char regno = value >> 3;
1375 unsigned char element = value & 7;
1376
1377 env->VRegs[regno].uh[(sizeof(MMVector) / 16) * lane + element]++;
1378 }
1379 }
1380 }
1381
1382 void HELPER(vhistq)(CPUHexagonState *env)
1383 {
1384 MMVector *input = &env->tmp_VRegs[0];
1385
1386 for (int lane = 0; lane < 8; lane++) {
1387 for (int i = 0; i < sizeof(MMVector) / 8; ++i) {
1388 unsigned char value = input->ub[(sizeof(MMVector) / 8) * lane + i];
1389 unsigned char regno = value >> 3;
1390 unsigned char element = value & 7;
1391
1392 if (fGETQBIT(env->qtmp, sizeof(MMVector) / 8 * lane + i)) {
1393 env->VRegs[regno].uh[
1394 (sizeof(MMVector) / 16) * lane + element]++;
1395 }
1396 }
1397 }
1398 }
1399
1400 void HELPER(vwhist256)(CPUHexagonState *env)
1401 {
1402 MMVector *input = &env->tmp_VRegs[0];
1403
1404 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1405 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1406 unsigned int weight = fGETUBYTE(1, input->h[i]);
1407 unsigned int vindex = (bucket >> 3) & 0x1F;
1408 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1409
1410 env->VRegs[vindex].uh[elindex] =
1411 env->VRegs[vindex].uh[elindex] + weight;
1412 }
1413 }
1414
1415 void HELPER(vwhist256q)(CPUHexagonState *env)
1416 {
1417 MMVector *input = &env->tmp_VRegs[0];
1418
1419 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1420 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1421 unsigned int weight = fGETUBYTE(1, input->h[i]);
1422 unsigned int vindex = (bucket >> 3) & 0x1F;
1423 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1424
1425 if (fGETQBIT(env->qtmp, 2 * i)) {
1426 env->VRegs[vindex].uh[elindex] =
1427 env->VRegs[vindex].uh[elindex] + weight;
1428 }
1429 }
1430 }
1431
1432 void HELPER(vwhist256_sat)(CPUHexagonState *env)
1433 {
1434 MMVector *input = &env->tmp_VRegs[0];
1435
1436 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1437 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1438 unsigned int weight = fGETUBYTE(1, input->h[i]);
1439 unsigned int vindex = (bucket >> 3) & 0x1F;
1440 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1441
1442 env->VRegs[vindex].uh[elindex] =
1443 fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
1444 }
1445 }
1446
1447 void HELPER(vwhist256q_sat)(CPUHexagonState *env)
1448 {
1449 MMVector *input = &env->tmp_VRegs[0];
1450
1451 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1452 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1453 unsigned int weight = fGETUBYTE(1, input->h[i]);
1454 unsigned int vindex = (bucket >> 3) & 0x1F;
1455 unsigned int elindex = ((i >> 0) & (~7)) | ((bucket >> 0) & 7);
1456
1457 if (fGETQBIT(env->qtmp, 2 * i)) {
1458 env->VRegs[vindex].uh[elindex] =
1459 fVSATUH(env->VRegs[vindex].uh[elindex] + weight);
1460 }
1461 }
1462 }
1463
1464 void HELPER(vwhist128)(CPUHexagonState *env)
1465 {
1466 MMVector *input = &env->tmp_VRegs[0];
1467
1468 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1469 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1470 unsigned int weight = fGETUBYTE(1, input->h[i]);
1471 unsigned int vindex = (bucket >> 3) & 0x1F;
1472 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1473
1474 env->VRegs[vindex].uw[elindex] =
1475 env->VRegs[vindex].uw[elindex] + weight;
1476 }
1477 }
1478
1479 void HELPER(vwhist128q)(CPUHexagonState *env)
1480 {
1481 MMVector *input = &env->tmp_VRegs[0];
1482
1483 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1484 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1485 unsigned int weight = fGETUBYTE(1, input->h[i]);
1486 unsigned int vindex = (bucket >> 3) & 0x1F;
1487 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1488
1489 if (fGETQBIT(env->qtmp, 2 * i)) {
1490 env->VRegs[vindex].uw[elindex] =
1491 env->VRegs[vindex].uw[elindex] + weight;
1492 }
1493 }
1494 }
1495
1496 void HELPER(vwhist128m)(CPUHexagonState *env, int32_t uiV)
1497 {
1498 MMVector *input = &env->tmp_VRegs[0];
1499
1500 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1501 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1502 unsigned int weight = fGETUBYTE(1, input->h[i]);
1503 unsigned int vindex = (bucket >> 3) & 0x1F;
1504 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1505
1506 if ((bucket & 1) == uiV) {
1507 env->VRegs[vindex].uw[elindex] =
1508 env->VRegs[vindex].uw[elindex] + weight;
1509 }
1510 }
1511 }
1512
1513 void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV)
1514 {
1515 MMVector *input = &env->tmp_VRegs[0];
1516
1517 for (int i = 0; i < (sizeof(MMVector) / 2); i++) {
1518 unsigned int bucket = fGETUBYTE(0, input->h[i]);
1519 unsigned int weight = fGETUBYTE(1, input->h[i]);
1520 unsigned int vindex = (bucket >> 3) & 0x1F;
1521 unsigned int elindex = ((i >> 1) & (~3)) | ((bucket >> 1) & 3);
1522
1523 if (((bucket & 1) == uiV) && fGETQBIT(env->qtmp, 2 * i)) {
1524 env->VRegs[vindex].uw[elindex] =
1525 env->VRegs[vindex].uw[elindex] + weight;
1526 }
1527 }
1528 }
1529
1530 #ifndef CONFIG_USER_ONLY
1531 void HELPER(raise_stack_overflow)(CPUHexagonState *env, uint32_t slot,
1532 uint32_t badva)
1533 {
1534 /*
1535 * Per section 7.3.1 of the V67 Programmer's Reference,
1536 * stack limit exception isn't raised in monitor mode.
1537 */
1538 uint32_t ssr = env->t_sreg[HEX_SREG_SSR];
1539 CPUState *cs;
1540
1541 if (GET_SSR_FIELD(SSR_EX, ssr) ||
1542 !GET_SSR_FIELD(SSR_UM, ssr)) {
1543 return;
1544 }
1545
1546 cs = env_cpu(env);
1547 cs->exception_index = HEX_EVENT_PRECISE;
1548 env->cause_code = HEX_CAUSE_STACK_LIMIT;
1549 ASSERT_DIRECT_TO_GUEST_UNSET(env, cs->exception_index);
1550
1551 if (slot == 0) {
1552 env->t_sreg[HEX_SREG_BADVA0] = badva;
1553 SET_SSR_FIELD(env, SSR_V0, 1);
1554 SET_SSR_FIELD(env, SSR_V1, 0);
1555 SET_SSR_FIELD(env, SSR_BVS, 0);
1556 } else if (slot == 1) {
1557 env->t_sreg[HEX_SREG_BADVA1] = badva;
1558 SET_SSR_FIELD(env, SSR_V0, 0);
1559 SET_SSR_FIELD(env, SSR_V1, 1);
1560 SET_SSR_FIELD(env, SSR_BVS, 1);
1561 } else {
1562 g_assert_not_reached();
1563 }
1564 cpu_loop_exit_restore(cs, 0);
1565 }
1566
1567 void HELPER(ciad)(CPUHexagonState *env, uint32_t mask)
1568 {
1569 uint32_t ipendad;
1570 uint32_t iad;
1571 HexagonCPU *cpu;
1572
1573 BQL_LOCK_GUARD();
1574 cpu = env_archcpu(env);
1575 ipendad = hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
1576 env->threadId);
1577 iad = fGET_FIELD(ipendad, IPENDAD_IAD);
1578 fSET_FIELD(ipendad, IPENDAD_IAD, iad & ~(mask));
1579 hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
1580 ipendad, env->threadId);
1581 l2vic_clear_interrupt(cpu->l2vic);
1582 hex_interrupt_update(env);
1583 }
1584
1585 void HELPER(siad)(CPUHexagonState *env, uint32_t mask)
1586 {
1587 uint32_t ipendad;
1588 uint32_t iad;
1589 HexagonCPU *cpu;
1590
1591 BQL_LOCK_GUARD();
1592 cpu = env_archcpu(env);
1593 ipendad = cpu->globalregs ?
1594 hexagon_globalreg_read(cpu->globalregs, HEX_SREG_IPENDAD,
1595 env->threadId) : 0;
1596 iad = fGET_FIELD(ipendad, IPENDAD_IAD);
1597 fSET_FIELD(ipendad, IPENDAD_IAD, iad | mask);
1598 if (cpu->globalregs) {
1599 hexagon_globalreg_write(cpu->globalregs, HEX_SREG_IPENDAD,
1600 ipendad, env->threadId);
1601 }
1602 hex_interrupt_update(env);
1603 }
1604
1605 void HELPER(swi)(CPUHexagonState *env, uint32_t mask)
1606 {
1607 BQL_LOCK_GUARD();
1608 hex_raise_interrupts(env, mask, CPU_INTERRUPT_SWI);
1609 }
1610
1611 void HELPER(cswi)(CPUHexagonState *env, uint32_t mask)
1612 {
1613 BQL_LOCK_GUARD();
1614 hex_clear_interrupts(env, mask, CPU_INTERRUPT_SWI);
1615 }
1616
1617 void HELPER(iassignw)(CPUHexagonState *env, uint32_t src)
1618 {
1619 uint32_t modectl;
1620 uint32_t thread_enabled_mask;
1621 CPUState *cpu;
1622 HexagonCPU *hex_cpu;
1623
1624 BQL_LOCK_GUARD();
1625 hex_cpu = env_archcpu(env);
1626 modectl = hex_cpu->globalregs ?
1627 hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL,
1628 env->threadId) : 0;
1629 thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
1630
1631 CPU_FOREACH(cpu) {
1632 CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env);
1633 uint32_t thread_id_mask = 0x1 << thread_env->threadId;
1634 if (thread_enabled_mask & thread_id_mask) {
1635 uint32_t imask = thread_env->t_sreg[HEX_SREG_IMASK];
1636 uint32_t intbitpos = (src >> 16) & 0xF;
1637 uint32_t val = (src >> thread_env->threadId) & 0x1;
1638 imask = deposit32(imask, intbitpos, 1, val);
1639 thread_env->t_sreg[HEX_SREG_IMASK] = imask;
1640
1641 qemu_log_mask(CPU_LOG_INT, "%s: thread " TARGET_FMT_ld
1642 ", new imask 0x%" PRIx32 "\n", __func__,
1643 thread_env->threadId, imask);
1644 }
1645 }
1646 hex_interrupt_update(env);
1647 }
1648
1649 uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src)
1650 {
1651 uint32_t modectl;
1652 uint32_t thread_enabled_mask;
1653 uint32_t intbitpos;
1654 uint32_t dest_reg;
1655 CPUState *cpu;
1656 HexagonCPU *hex_cpu;
1657
1658 BQL_LOCK_GUARD();
1659 hex_cpu = env_archcpu(env);
1660 modectl = hex_cpu->globalregs ?
1661 hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL,
1662 env->threadId) : 0;
1663 thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
1664 /* src fields are in same position as modectl, but mean different things */
1665 intbitpos = GET_FIELD(MODECTL_W, src);
1666 dest_reg = 0;
1667 CPU_FOREACH(cpu) {
1668 CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env);
1669 uint32_t thread_id_mask = 0x1 << thread_env->threadId;
1670 if (thread_enabled_mask & thread_id_mask) {
1671 uint32_t imask = thread_env->t_sreg[HEX_SREG_IMASK];
1672 dest_reg |= ((imask >> intbitpos) & 0x1) << thread_env->threadId;
1673 }
1674 }
1675
1676 return dest_reg;
1677 }
1678
1679 void HELPER(start)(CPUHexagonState *env, uint32_t imask)
1680 {
1681 hexagon_start_threads(env, imask);
1682 }
1683
1684 void HELPER(stop)(CPUHexagonState *env)
1685 {
1686 hexagon_stop_thread(env);
1687 }
1688
1689 static void set_wait_mode(CPUHexagonState *env)
1690 {
1691 HexagonCPU *cpu;
1692 uint32_t modectl;
1693 uint32_t thread_wait_mask;
1694
1695 g_assert(bql_locked());
1696
1697 cpu = env_archcpu(env);
1698 if (!cpu->globalregs) {
1699 return;
1700 }
1701 modectl =
1702 hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
1703 env->threadId);
1704 thread_wait_mask = GET_FIELD(MODECTL_W, modectl);
1705 thread_wait_mask |= 0x1 << env->threadId;
1706 SET_SYSTEM_FIELD(env, HEX_SREG_MODECTL, MODECTL_W, thread_wait_mask);
1707 }
1708
1709 static void hexagon_wait_thread(CPUHexagonState *env, uint32_t PC)
1710 {
1711 CPUState *cs;
1712
1713 g_assert(bql_locked());
1714
1715 if (qemu_loglevel_mask(LOG_GUEST_ERROR) &&
1716 (env->k0_lock_state != HEX_LOCK_UNLOCKED ||
1717 env->tlb_lock_state != HEX_LOCK_UNLOCKED)) {
1718 qemu_log("WARNING: executing wait() with acquired lock"
1719 "may lead to deadlock\n");
1720 }
1721 g_assert(get_exe_mode(env) != HEX_EXE_MODE_WAIT);
1722
1723 cs = env_cpu(env);
1724 /*
1725 * The addtion of cpu_has_work is borrowed from arm's wfi helper
1726 * and is critical for our stability
1727 */
1728 if ((cs->exception_index != HEX_EVENT_NONE) ||
1729 (cpu_has_work(cs))) {
1730 qemu_log_mask(CPU_LOG_INT,
1731 "%s: thread %" PRIu32 " skipping WAIT mode, have some work\n",
1732 __func__, env->threadId);
1733 return;
1734 }
1735 set_wait_mode(env);
1736 env->wait_next_pc = PC + 4;
1737
1738 cpu_interrupt(cs, CPU_INTERRUPT_HALT);
1739 }
1740
1741 static inline QEMU_ALWAYS_INLINE void resched(CPUHexagonState *env)
1742 {
1743 uint32_t schedcfg;
1744 uint32_t schedcfg_en;
1745 int int_number;
1746 CPUState *cs;
1747 uint32_t lowest_th_prio = 0; /* 0 is highest prio */
1748 uint32_t bestwait_reg;
1749 uint32_t best_prio;
1750 HexagonCPU *cpu;
1751
1752 BQL_LOCK_GUARD();
1753 qemu_log_mask(CPU_LOG_INT, "%s: check resched\n", __func__);
1754 cpu = env_archcpu(env);
1755 schedcfg = cpu->globalregs ?
1756 hexagon_globalreg_read(cpu->globalregs, HEX_SREG_SCHEDCFG,
1757 env->threadId) : 0;
1758 schedcfg_en = GET_FIELD(SCHEDCFG_EN, schedcfg);
1759 int_number = GET_FIELD(SCHEDCFG_INTNO, schedcfg);
1760
1761 if (!schedcfg_en) {
1762 return;
1763 }
1764
1765 CPU_FOREACH(cs) {
1766 HexagonCPU *thread = HEXAGON_CPU(cs);
1767 CPUHexagonState *thread_env = &(thread->env);
1768 uint32_t th_prio = GET_FIELD(
1769 STID_PRIO, thread_env->t_sreg[HEX_SREG_STID]);
1770 if (!hexagon_thread_is_enabled(thread_env)) {
1771 continue;
1772 }
1773
1774 lowest_th_prio = (lowest_th_prio > th_prio)
1775 ? lowest_th_prio
1776 : th_prio;
1777 }
1778
1779 bestwait_reg = cpu->globalregs ?
1780 hexagon_globalreg_read(cpu->globalregs, HEX_SREG_BESTWAIT,
1781 env->threadId) : 0;
1782 best_prio = GET_FIELD(BESTWAIT_PRIO, bestwait_reg);
1783
1784 /*
1785 * If the lowest priority thread is lower priority than the
1786 * value in the BESTWAIT register, we must raise the reschedule
1787 * interrupt on the lowest priority thread.
1788 */
1789 if (lowest_th_prio > best_prio) {
1790 qemu_log_mask(CPU_LOG_INT,
1791 "%s: raising resched int %u,"
1792 " cur PC 0x%" PRIx32 "\n",
1793 __func__, (unsigned)int_number, env->gpr[HEX_REG_PC]);
1794 SET_SYSTEM_FIELD(env, HEX_SREG_BESTWAIT, BESTWAIT_PRIO, ~0);
1795 hex_raise_interrupts(env, 1 << int_number, CPU_INTERRUPT_SWI);
1796 }
1797 }
1798
1799 void HELPER(resched)(CPUHexagonState *env)
1800 {
1801 resched(env);
1802 }
1803
1804 void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
1805 {
1806 BQL_LOCK_GUARD();
1807
1808 if (!fIN_DEBUG_MODE(env->threadId)) {
1809 hexagon_wait_thread(env, PC);
1810 }
1811 }
1812
1813 void HELPER(resume)(CPUHexagonState *env, uint32_t mask)
1814 {
1815 BQL_LOCK_GUARD();
1816 hexagon_resume_threads(env, mask);
1817 }
1818
1819 uint32_t HELPER(getimask)(CPUHexagonState *env, uint32_t tid)
1820 {
1821 CPUState *cs;
1822 BQL_LOCK_GUARD();
1823 CPU_FOREACH(cs) {
1824 HexagonCPU *found_cpu = HEXAGON_CPU(cs);
1825 CPUHexagonState *found_env = &found_cpu->env;
1826 if (found_env->threadId == tid) {
1827 uint32_t imask = found_env->t_sreg[HEX_SREG_IMASK];
1828 qemu_log_mask(CPU_LOG_INT, "%s: tid " TARGET_FMT_lx
1829 " imask = 0x%" PRIx32 "\n", __func__,
1830 env->threadId,
1831 (uint32_t)GET_FIELD(IMASK_MASK, imask));
1832 return GET_FIELD(IMASK_MASK, imask);
1833 }
1834 }
1835 return 0;
1836 }
1837
1838 void HELPER(setimask)(CPUHexagonState *env, uint32_t tid, uint32_t imask)
1839 {
1840 CPUState *cs;
1841
1842 BQL_LOCK_GUARD();
1843 CPU_FOREACH(cs) {
1844 HexagonCPU *found_cpu = HEXAGON_CPU(cs);
1845 CPUHexagonState *found_env = &found_cpu->env;
1846
1847 if (tid == found_env->threadId) {
1848 SET_SYSTEM_FIELD(found_env, HEX_SREG_IMASK, IMASK_MASK, imask);
1849 qemu_log_mask(CPU_LOG_INT, "%s: tid " TARGET_FMT_lx
1850 " imask 0x%" PRIx32 "\n",
1851 __func__, found_env->threadId, imask);
1852 hex_interrupt_update(found_env);
1853 return;
1854 }
1855 }
1856 qemu_log_mask(LOG_GUEST_ERROR,
1857 "setimask used with an invalid tid near PC: 0x%"
1858 PRIx32 "\n", env->next_PC);
1859 }
1860
1861 void HELPER(sreg_write_masked)(CPUHexagonState *env, uint32_t reg, uint32_t val)
1862 {
1863 BQL_LOCK_GUARD();
1864 if (reg < HEX_SREG_GLB_START) {
1865 env->t_sreg[reg] = val;
1866 } else {
1867 HexagonCPU *cpu = env_archcpu(env);
1868 if (cpu->globalregs) {
1869 hexagon_globalreg_write_masked(cpu->globalregs, reg, val);
1870 }
1871 }
1872 }
1873
1874 static inline QEMU_ALWAYS_INLINE uint32_t sreg_read(CPUHexagonState *env,
1875 uint32_t reg)
1876 {
1877 HexagonCPU *cpu;
1878
1879 g_assert(bql_locked());
1880 if (reg < HEX_SREG_GLB_START) {
1881 return env->t_sreg[reg];
1882 }
1883 cpu = env_archcpu(env);
1884 return cpu->globalregs ?
1885 hexagon_globalreg_read(cpu->globalregs, reg, env->threadId) : 0;
1886 }
1887
1888 uint32_t HELPER(sreg_read)(CPUHexagonState *env, uint32_t reg)
1889 {
1890 BQL_LOCK_GUARD();
1891 return sreg_read(env, reg);
1892 }
1893
1894 uint64_t HELPER(sreg_read_pair)(CPUHexagonState *env, uint32_t reg)
1895 {
1896 BQL_LOCK_GUARD();
1897
1898 return deposit64((uint64_t) sreg_read(env, reg), 32, 32,
1899 sreg_read(env, reg + 1));
1900 }
1901
1902 uint32_t HELPER(greg_read)(CPUHexagonState *env, uint32_t reg)
1903
1904 {
1905 return hexagon_greg_read(env, reg);
1906 }
1907
1908 uint64_t HELPER(greg_read_pair)(CPUHexagonState *env, uint32_t reg)
1909
1910 {
1911 if (reg == HEX_GREG_G0 || reg == HEX_GREG_G2) {
1912 return (uint64_t)(env->greg[reg]) |
1913 (((uint64_t)(env->greg[reg + 1])) << 32);
1914 }
1915 switch (reg) {
1916 case HEX_GREG_GPCYCLELO:
1917 return hexagon_get_sys_pcycle_count(env);
1918 default:
1919 return (uint64_t)hexagon_greg_read(env, reg) |
1920 ((uint64_t)(hexagon_greg_read(env, reg + 1)) << 32);
1921 }
1922 }
1923
1924 /*
1925 * setprio/resched - hardware-assisted scheduler helpers for managing
1926 * the run queue and interrupt steering.
1927 */
1928 void HELPER(setprio)(CPUHexagonState *env, uint32_t thread, uint32_t prio)
1929 {
1930 CPUState *cs;
1931
1932 BQL_LOCK_GUARD();
1933 CPU_FOREACH(cs) {
1934 HexagonCPU *found_cpu = HEXAGON_CPU(cs);
1935 CPUHexagonState *found_env = &found_cpu->env;
1936 if (thread == found_env->threadId) {
1937 SET_SYSTEM_FIELD(found_env, HEX_SREG_STID, STID_PRIO, prio);
1938 qemu_log_mask(CPU_LOG_INT,
1939 "%s: tid %" PRIu32 " prio = 0x%" PRIx32 "\n",
1940 __func__, found_env->threadId, prio);
1941 resched(env);
1942 return;
1943 }
1944 }
1945 g_assert_not_reached();
1946 }
1947
1948
1949 void HELPER(pending_interrupt)(CPUHexagonState *env)
1950 {
1951 BQL_LOCK_GUARD();
1952 hex_interrupt_update(env);
1953 }
1954 #endif
1955
1956
1957 /* These macros can be referenced in the generated helper functions */
1958 #define warn(...) /* Nothing */
1959 #define fatal(...) g_assert_not_reached();
1960
1961 #define BOGUS_HELPER(tag) \
1962 printf("ERROR: bogus helper: " #tag "\n")
1963
1964 #include "helper_funcs_generated.c.inc"
1965
1966 #define DO_ABSDIFF(NAME, TYPE, UTYPE) \
1967 void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
1968 { \
1969 intptr_t i, oprsz = simd_oprsz(desc); \
1970 UTYPE *d = vd; \
1971 TYPE *n = vn, *m = vm; \
1972 \
1973 for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
1974 d[i] = n[i] < m[i] ? (UTYPE)m[i] - (UTYPE)n[i] \
1975 : (UTYPE)n[i] - (UTYPE)m[i]; \
1976 } \
1977 }
1978
1979 DO_ABSDIFF(gvec_sabsdiff_h, int16_t, uint16_t)
1980 DO_ABSDIFF(gvec_sabsdiff_w, int32_t, uint32_t)
1981 DO_ABSDIFF(gvec_uabsdiff_b, uint8_t, uint8_t)
1982 DO_ABSDIFF(gvec_uabsdiff_h, uint16_t, uint16_t)
1983
1984 #undef DO_ABSDIFF