Commit f473019a authored by Max Filippov's avatar Max Filippov
Browse files

target/xtensa: extract test for window underflow exception



- mark retw and retw.n instructions;
- extract window inderflow test from retw helper;
- put underflow exception check generation right after the overflow
  check;

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent 6416d16f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ DEF_HELPER_3(debug_exception, noreturn, env, i32, i32)
DEF_HELPER_2(wsr_windowbase, void, env, i32)
DEF_HELPER_4(entry, void, env, i32, i32, i32)
DEF_HELPER_2(test_ill_retw, void, env, i32)
DEF_HELPER_2(test_underflow_retw, void, env, i32)
DEF_HELPER_2(retw, i32, env, i32)
DEF_HELPER_2(rotw, void, env, i32)
DEF_HELPER_3(window_check, noreturn, env, i32, i32)
+15 −9
Original line number Diff line number Diff line
@@ -310,19 +310,15 @@ void HELPER(test_ill_retw)(CPUXtensaState *env, uint32_t pc)
    }
}

uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
void HELPER(test_underflow_retw)(CPUXtensaState *env, uint32_t pc)
{
    int n = (env->regs[0] >> 30) & 0x3;
    uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
    uint32_t windowstart = env->sregs[WINDOW_START];
    uint32_t ret_pc = 0;

    ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);
    if (!(env->sregs[WINDOW_START] &
          windowstart_bit(env->sregs[WINDOW_BASE] - n, env))) {
        uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);

        xtensa_rotate_window(env, -n);
    if (windowstart & windowstart_bit(env->sregs[WINDOW_BASE], env)) {
        env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
    } else {
        /* window underflow */
        env->sregs[PS] = (env->sregs[PS] & ~PS_OWB) |
            (windowbase << PS_OWB_SHIFT) | PS_EXCM;
@@ -336,6 +332,16 @@ uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
            HELPER(exception)(env, EXC_WINDOW_UNDERFLOW12);
        }
    }
}

uint32_t HELPER(retw)(CPUXtensaState *env, uint32_t pc)
{
    int n = (env->regs[0] >> 30) & 0x3;
    uint32_t windowbase = windowbase_bound(env->sregs[WINDOW_BASE], env);
    uint32_t ret_pc = (pc & 0xc0000000) | (env->regs[0] & 0x3fffffff);

    xtensa_rotate_window(env, -n);
    env->sregs[WINDOW_START] &= ~windowstart_bit(windowbase, env);
    return ret_pc;
}

+9 −0
Original line number Diff line number Diff line
@@ -1071,6 +1071,13 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
        return;
    }

    if (op_flags & XTENSA_OP_UNDERFLOW) {
        TCGv_i32 tmp = tcg_const_i32(dc->pc);

        gen_helper_test_underflow_retw(cpu_env, tmp);
        tcg_temp_free(tmp);
    }

    for (slot = 0; slot < slots; ++slot) {
        XtensaOpcodeOps *ops = slot_prop[slot].ops;

@@ -3485,10 +3492,12 @@ static const XtensaOpcodeOps core_ops[] = {
        .name = "retw",
        .translate = translate_retw,
        .test_ill = test_ill_retw,
        .op_flags = XTENSA_OP_UNDERFLOW,
    }, {
        .name = "retw.n",
        .translate = translate_retw,
        .test_ill = test_ill_retw,
        .op_flags = XTENSA_OP_UNDERFLOW,
    }, {
        .name = "rfdd",
        .op_flags = XTENSA_OP_ILL,