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)