@samitouri / QOSamiQemu / commits / 77d6422390

target/hexagon: Implement iassign{r,w} helpers

iassign{r,w} are the "Interrupt to thread assignment {read,write}" instructions. 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 77d6422390b05e53ae56c805be7498f53ea11c56
1 file changed +54 -2
target/hexagon/op_helper.c
+54 -2
@@ -1417,12 +1417,64 @@ void HELPER(cswi)(CPUHexagonState *env, uint32_t mask)
1417
1418 void HELPER(iassignw)(CPUHexagonState *env, uint32_t src)
1419 {
1420 - g_assert_not_reached();
1420 + uint32_t modectl;
1421 + uint32_t thread_enabled_mask;
1422 + CPUState *cpu;
1423 + HexagonCPU *hex_cpu;
1424 +
1425 + BQL_LOCK_GUARD();
1426 + hex_cpu = env_archcpu(env);
1427 + modectl = hex_cpu->globalregs ?
1428 + hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL,
1429 + env->threadId) : 0;
1430 + thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
1431 +
1432 + CPU_FOREACH(cpu) {
1433 + CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env);
1434 + uint32_t thread_id_mask = 0x1 << thread_env->threadId;
1435 + if (thread_enabled_mask & thread_id_mask) {
1436 + uint32_t imask = thread_env->t_sreg[HEX_SREG_IMASK];
1437 + uint32_t intbitpos = (src >> 16) & 0xF;
1438 + uint32_t val = (src >> thread_env->threadId) & 0x1;
1439 + imask = deposit32(imask, intbitpos, 1, val);
1440 + thread_env->t_sreg[HEX_SREG_IMASK] = imask;
1441 +
1442 + qemu_log_mask(CPU_LOG_INT, "%s: thread " TARGET_FMT_ld
1443 + ", new imask 0x%" PRIx32 "\n", __func__,
1444 + thread_env->threadId, imask);
1445 + }
1446 + }
1447 + hex_interrupt_update(env);
1448 }
1449
1450 uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src)
1451 {
1425 - g_assert_not_reached();
1452 + uint32_t modectl;
1453 + uint32_t thread_enabled_mask;
1454 + uint32_t intbitpos;
1455 + uint32_t dest_reg;
1456 + CPUState *cpu;
1457 + HexagonCPU *hex_cpu;
1458 +
1459 + BQL_LOCK_GUARD();
1460 + hex_cpu = env_archcpu(env);
1461 + modectl = hex_cpu->globalregs ?
1462 + hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL,
1463 + env->threadId) : 0;
1464 + thread_enabled_mask = GET_FIELD(MODECTL_E, modectl);
1465 + /* src fields are in same position as modectl, but mean different things */
1466 + intbitpos = GET_FIELD(MODECTL_W, src);
1467 + dest_reg = 0;
1468 + CPU_FOREACH(cpu) {
1469 + CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env);
1470 + uint32_t thread_id_mask = 0x1 << thread_env->threadId;
1471 + if (thread_enabled_mask & thread_id_mask) {
1472 + uint32_t imask = thread_env->t_sreg[HEX_SREG_IMASK];
1473 + dest_reg |= ((imask >> intbitpos) & 0x1) << thread_env->threadId;
1474 + }
1475 + }
1476 +
1477 + return dest_reg;
1478 }
1479
1480 void HELPER(start)(CPUHexagonState *env, uint32_t imask)