target/hexagon: Implement wait helper
Reviewed-by: Taylor Simpson <ltaylorsimpson@gmail.com> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
Brian Cain committed
Jun 22, 2026 at 15:28 UTC
acd2b7a2f19ac04bd313e816e5f9e7f87adc9858
2 files changed
+59
-3
target/hexagon/gen_tcg_sys.h
+1
-1
@@ -80,7 +80,7 @@
80
#define fGEN_TCG_Y2_wait(SHORTCODE) \
81
do { \
82
RsV = RsV; \
83
- gen_helper_wait(tcg_env, tcg_constant_tl(ctx->pkt->pc)); \
83
+ gen_helper_wait(tcg_env, tcg_constant_tl(ctx->pkt.pc)); \
84
} while (0)
85
86
#define fGEN_TCG_Y2_resume(SHORTCODE) \
target/hexagon/op_helper.c
+58
-2
@@ -1487,9 +1487,65 @@ void HELPER(stop)(CPUHexagonState *env)
1487
hexagon_stop_thread(env);
1488
}
1489
1490
-void HELPER(wait)(CPUHexagonState *env, target_ulong PC)
1490
+static void set_wait_mode(CPUHexagonState *env)
1491
{
1492
- g_assert_not_reached();
1492
+ HexagonCPU *cpu;
1493
+ uint32_t modectl;
1494
+ uint32_t thread_wait_mask;
1495
+
1496
+ g_assert(bql_locked());
1497
+
1498
+ cpu = env_archcpu(env);
1499
+ if (!cpu->globalregs) {
1500
+ return;
1501
+ }
1502
+ modectl =
1503
+ hexagon_globalreg_read(cpu->globalregs, HEX_SREG_MODECTL,
1504
+ env->threadId);
1505
+ thread_wait_mask = GET_FIELD(MODECTL_W, modectl);
1506
+ thread_wait_mask |= 0x1 << env->threadId;
1507
+ SET_SYSTEM_FIELD(env, HEX_SREG_MODECTL, MODECTL_W, thread_wait_mask);
1508
+}
1509
+
1510
+static void hexagon_wait_thread(CPUHexagonState *env, uint32_t PC)
1511
+{
1512
+ CPUState *cs;
1513
+
1514
+ g_assert(bql_locked());
1515
+
1516
+ if (qemu_loglevel_mask(LOG_GUEST_ERROR) &&
1517
+ (env->k0_lock_state != HEX_LOCK_UNLOCKED ||
1518
+ env->tlb_lock_state != HEX_LOCK_UNLOCKED)) {
1519
+ qemu_log("WARNING: executing wait() with acquired lock"
1520
+ "may lead to deadlock\n");
1521
+ }
1522
+ g_assert(get_exe_mode(env) != HEX_EXE_MODE_WAIT);
1523
+
1524
+ cs = env_cpu(env);
1525
+ /*
1526
+ * The addtion of cpu_has_work is borrowed from arm's wfi helper
1527
+ * and is critical for our stability
1528
+ */
1529
+ if ((cs->exception_index != HEX_EVENT_NONE) ||
1530
+ (cpu_has_work(cs))) {
1531
+ qemu_log_mask(CPU_LOG_INT,
1532
+ "%s: thread %" PRIu32 " skipping WAIT mode, have some work\n",
1533
+ __func__, env->threadId);
1534
+ return;
1535
+ }
1536
+ set_wait_mode(env);
1537
+ env->wait_next_pc = PC + 4;
1538
+
1539
+ cpu_interrupt(cs, CPU_INTERRUPT_HALT);
1540
+}
1541
+
1542
+void HELPER(wait)(CPUHexagonState *env, uint32_t PC)
1543
+{
1544
+ BQL_LOCK_GUARD();
1545
+
1546
+ if (!fIN_DEBUG_MODE(env->threadId)) {
1547
+ hexagon_wait_thread(env, PC);
1548
+ }
1549
}
1550
1551
void HELPER(resume)(CPUHexagonState *env, uint32_t mask)