From: Brian Cain <[email protected]> iassign{r,w} are the "Interrupt to thread assignment {read,write}" instructions.
Reviewed-by: Taylor Simpson <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- target/hexagon/op_helper.c | 54 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index 712638defcf..6ae07cc68e5 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -1416,12 +1416,62 @@ void HELPER(cswi)(CPUHexagonState *env, uint32_t mask) void HELPER(iassignw)(CPUHexagonState *env, uint32_t src) { - g_assert_not_reached(); + uint32_t modectl; + uint32_t thread_enabled_mask; + CPUState *cpu; + + BQL_LOCK_GUARD(); + HexagonCPU *hex_cpu = env_archcpu(env); + modectl = hex_cpu->globalregs ? + hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL, + env->threadId) : 0; + thread_enabled_mask = GET_FIELD(MODECTL_E, modectl); + + CPU_FOREACH(cpu) { + CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env); + uint32_t thread_id_mask = 0x1 << thread_env->threadId; + if (thread_enabled_mask & thread_id_mask) { + uint32_t imask = thread_env->t_sreg[HEX_SREG_IMASK]; + uint32_t intbitpos = (src >> 16) & 0xF; + uint32_t val = (src >> thread_env->threadId) & 0x1; + imask = deposit32(imask, intbitpos, 1, val); + thread_env->t_sreg[HEX_SREG_IMASK] = imask; + + qemu_log_mask(CPU_LOG_INT, "%s: thread " TARGET_FMT_ld + ", new imask 0x%" PRIx32 "\n", __func__, + thread_env->threadId, imask); + } + } + hex_interrupt_update(env); } uint32_t HELPER(iassignr)(CPUHexagonState *env, uint32_t src) { - g_assert_not_reached(); + uint32_t modectl; + uint32_t thread_enabled_mask; + uint32_t intbitpos; + uint32_t dest_reg; + CPUState *cpu; + + BQL_LOCK_GUARD(); + HexagonCPU *hex_cpu = env_archcpu(env); + modectl = hex_cpu->globalregs ? + hexagon_globalreg_read(hex_cpu->globalregs, HEX_SREG_MODECTL, + env->threadId) : 0; + thread_enabled_mask = GET_FIELD(MODECTL_E, modectl); + /* src fields are in same position as modectl, but mean different things */ + intbitpos = GET_FIELD(MODECTL_W, src); + dest_reg = 0; + CPU_FOREACH(cpu) { + CPUHexagonState *thread_env = &(HEXAGON_CPU(cpu)->env); + uint32_t thread_id_mask = 0x1 << thread_env->threadId; + if (thread_enabled_mask & thread_id_mask) { + uint32_t imask = thread_env->t_sreg[HEX_SREG_IMASK]; + dest_reg |= ((imask >> intbitpos) & 0x1) << thread_env->threadId; + } + } + + return dest_reg; } void HELPER(start)(CPUHexagonState *env, uint32_t imask) -- 2.34.1
