Commit 582fef0f authored by Max Filippov's avatar Max Filippov
Browse files

target/xtensa: extract test for cpdisabled exception



- add XtensaOpcodeOps::coprocessor with bitmask of coprocessors used by
  the instruction;
- replace coprocessor id parameter of gen_check_cpenable with the
  bitmask of used coprocessors;
- collect coprocessor IDs used by an instruction in the disassembly
  loop;
- put test for coprocessor disabled exception after the alloca test;

Signed-off-by: default avatarMax Filippov <jcmvbkbc@gmail.com>
parent 90d6494d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -381,6 +381,7 @@ typedef struct XtensaOpcodeOps {
    const uint32_t *par;
    uint32_t op_flags;
    uint32_t windowed_register_op;
    uint32_t coprocessor;
} XtensaOpcodeOps;

typedef struct XtensaOpcodeTranslators {
+122 −108
Original line number Diff line number Diff line
@@ -351,11 +351,12 @@ static bool gen_check_privilege(DisasContext *dc)
    return false;
}

static bool gen_check_cpenable(DisasContext *dc, unsigned cp)
static bool gen_check_cpenable(DisasContext *dc, uint32_t cp_mask)
{
    if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) &&
            !(dc->cpenable & (1 << cp))) {
        gen_exception_cause(dc, COPROCESSOR0_DISABLED + cp);
    cp_mask &= ~dc->cpenable;

    if (option_enabled(dc, XTENSA_OPTION_COPROCESSOR) && cp_mask) {
        gen_exception_cause(dc, COPROCESSOR0_DISABLED + ctz32(cp_mask));
        dc->base.is_jmp = DISAS_NORETURN;
        return false;
    }
@@ -953,6 +954,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
    } slot_prop[MAX_INSN_SLOTS];
    uint32_t debug_cause = 0;
    uint32_t windowed_register = 0;
    uint32_t coprocessor = 0;

    if (len == XTENSA_UNDEFINED) {
        qemu_log_mask(LOG_GUEST_ERROR,
@@ -1050,6 +1052,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
                reg_opnd ^= 1 << i;
            }
        }
        coprocessor |= ops->coprocessor;
    }

    if ((op_flags & XTENSA_OP_PRIVILEGED) &&
@@ -1085,6 +1088,10 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
        tcg_temp_free(tmp);
    }

    if (coprocessor && !gen_check_cpenable(dc, coprocessor)) {
        return;
    }

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

@@ -4084,11 +4091,13 @@ static const XtensaOpcodeOps core_ops[] = {
        .translate = translate_rur,
        .par = (const uint32_t[]){FCR},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "rur.fsr",
        .translate = translate_rur,
        .par = (const uint32_t[]){FSR},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "rur.threadptr",
        .translate = translate_rur,
@@ -4805,11 +4814,13 @@ static const XtensaOpcodeOps core_ops[] = {
        .translate = translate_wur,
        .par = (const uint32_t[]){FCR},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "wur.fsr",
        .translate = translate_wur,
        .par = (const uint32_t[]){FSR},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "wur.threadptr",
        .translate = translate_wur,
@@ -5354,19 +5365,15 @@ const XtensaOpcodeTranslators xtensa_core_opcodes = {
static void translate_abs_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_abs_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
}
}

static void translate_add_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_add_s(cpu_FR[arg[0]], cpu_env,
                     cpu_FR[arg[1]], cpu_FR[arg[2]]);
}
}

enum {
    COMPARE_UN,
@@ -5391,19 +5398,15 @@ static void translate_compare_s(DisasContext *dc, const uint32_t arg[],
        [COMPARE_OLE] = gen_helper_ole_s,
        [COMPARE_ULE] = gen_helper_ule_s,
    };

    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 bit = tcg_const_i32(1 << arg[0]);

    helper[par[0]](cpu_env, bit, cpu_FR[arg[1]], cpu_FR[arg[2]]);
    tcg_temp_free(bit);
}
}

static void translate_float_s(DisasContext *dc, const uint32_t arg[],
                              const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 scale = tcg_const_i32(-arg[2]);

    if (par[0]) {
@@ -5413,12 +5416,10 @@ static void translate_float_s(DisasContext *dc, const uint32_t arg[],
    }
    tcg_temp_free(scale);
}
}

static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[],
                             const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 rounding_mode = tcg_const_i32(par[0]);
    TCGv_i32 scale = tcg_const_i32(arg[2]);

@@ -5432,12 +5433,10 @@ static void translate_ftoi_s(DisasContext *dc, const uint32_t arg[],
    tcg_temp_free(rounding_mode);
    tcg_temp_free(scale);
}
}

static void translate_ldsti(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 addr = tcg_temp_new_i32();

    tcg_gen_addi_i32(addr, cpu_R[arg[1]], arg[2]);
@@ -5452,12 +5451,10 @@ static void translate_ldsti(DisasContext *dc, const uint32_t arg[],
    }
    tcg_temp_free(addr);
}
}

static void translate_ldstx(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 addr = tcg_temp_new_i32();

    tcg_gen_add_i32(addr, cpu_R[arg[1]], cpu_R[arg[2]]);
@@ -5472,29 +5469,23 @@ static void translate_ldstx(DisasContext *dc, const uint32_t arg[],
    }
    tcg_temp_free(addr);
}
}

static void translate_madd_s(DisasContext *dc, const uint32_t arg[],
                             const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_madd_s(cpu_FR[arg[0]], cpu_env,
                      cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
}
}

static void translate_mov_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_FR[arg[1]]);
}
}

static void translate_movcond_s(DisasContext *dc, const uint32_t arg[],
                                const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 zero = tcg_const_i32(0);

    tcg_gen_movcond_i32(par[0], cpu_FR[arg[0]],
@@ -5502,12 +5493,10 @@ static void translate_movcond_s(DisasContext *dc, const uint32_t arg[],
                        cpu_FR[arg[1]], cpu_FR[arg[0]]);
    tcg_temp_free(zero);
}
}

static void translate_movp_s(DisasContext *dc, const uint32_t arg[],
                             const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    TCGv_i32 zero = tcg_const_i32(0);
    TCGv_i32 tmp = tcg_temp_new_i32();

@@ -5518,223 +5507,248 @@ static void translate_movp_s(DisasContext *dc, const uint32_t arg[],
    tcg_temp_free(tmp);
    tcg_temp_free(zero);
}
}

static void translate_mul_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_mul_s(cpu_FR[arg[0]], cpu_env,
                     cpu_FR[arg[1]], cpu_FR[arg[2]]);
}
}

static void translate_msub_s(DisasContext *dc, const uint32_t arg[],
                             const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_msub_s(cpu_FR[arg[0]], cpu_env,
                      cpu_FR[arg[0]], cpu_FR[arg[1]], cpu_FR[arg[2]]);
}
}

static void translate_neg_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_neg_s(cpu_FR[arg[0]], cpu_FR[arg[1]]);
}
}

static void translate_rfr_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    tcg_gen_mov_i32(cpu_R[arg[0]], cpu_FR[arg[1]]);
}
}

static void translate_sub_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    gen_helper_sub_s(cpu_FR[arg[0]], cpu_env,
                     cpu_FR[arg[1]], cpu_FR[arg[2]]);
}
}

static void translate_wfr_s(DisasContext *dc, const uint32_t arg[],
                            const uint32_t par[])
{
    if (gen_check_cpenable(dc, 0)) {
    tcg_gen_mov_i32(cpu_FR[arg[0]], cpu_R[arg[1]]);
}
}

static const XtensaOpcodeOps fpu2000_ops[] = {
    {
        .name = "abs.s",
        .translate = translate_abs_s,
        .coprocessor = 0x1,
    }, {
        .name = "add.s",
        .translate = translate_add_s,
        .coprocessor = 0x1,
    }, {
        .name = "ceil.s",
        .translate = translate_ftoi_s,
        .par = (const uint32_t[]){float_round_up, false},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "float.s",
        .translate = translate_float_s,
        .par = (const uint32_t[]){false},
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    }, {
        .name = "floor.s",
        .translate = translate_ftoi_s,
        .par = (const uint32_t[]){float_round_down, false},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "lsi",
        .translate = translate_ldsti,
        .par = (const uint32_t[]){false, false},
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    }, {
        .name = "lsiu",
        .translate = translate_ldsti,
        .par = (const uint32_t[]){false, true},
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    }, {
        .name = "lsx",
        .translate = translate_ldstx,
        .par = (const uint32_t[]){false, false},
        .windowed_register_op = 0x6,
        .coprocessor = 0x1,
    }, {
        .name = "lsxu",
        .translate = translate_ldstx,
        .par = (const uint32_t[]){false, true},
        .windowed_register_op = 0x6,
        .coprocessor = 0x1,
    }, {
        .name = "madd.s",
        .translate = translate_madd_s,
        .coprocessor = 0x1,
    }, {
        .name = "mov.s",
        .translate = translate_mov_s,
        .coprocessor = 0x1,
    }, {
        .name = "moveqz.s",
        .translate = translate_movcond_s,
        .par = (const uint32_t[]){TCG_COND_EQ},
        .windowed_register_op = 0x4,
        .coprocessor = 0x1,
    }, {
        .name = "movf.s",
        .translate = translate_movp_s,
        .par = (const uint32_t[]){TCG_COND_EQ},
        .coprocessor = 0x1,
    }, {
        .name = "movgez.s",
        .translate = translate_movcond_s,
        .par = (const uint32_t[]){TCG_COND_GE},
        .windowed_register_op = 0x4,
        .coprocessor = 0x1,
    }, {
        .name = "movltz.s",
        .translate = translate_movcond_s,
        .par = (const uint32_t[]){TCG_COND_LT},
        .windowed_register_op = 0x4,
        .coprocessor = 0x1,
    }, {
        .name = "movnez.s",
        .translate = translate_movcond_s,
        .par = (const uint32_t[]){TCG_COND_NE},
        .windowed_register_op = 0x4,
        .coprocessor = 0x1,
    }, {
        .name = "movt.s",
        .translate = translate_movp_s,
        .par = (const uint32_t[]){TCG_COND_NE},
        .coprocessor = 0x1,
    }, {
        .name = "msub.s",
        .translate = translate_msub_s,
        .coprocessor = 0x1,
    }, {
        .name = "mul.s",
        .translate = translate_mul_s,
        .coprocessor = 0x1,
    }, {
        .name = "neg.s",
        .translate = translate_neg_s,
        .coprocessor = 0x1,
    }, {
        .name = "oeq.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_OEQ},
        .coprocessor = 0x1,
    }, {
        .name = "ole.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_OLE},
        .coprocessor = 0x1,
    }, {
        .name = "olt.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_OLT},
        .coprocessor = 0x1,
    }, {
        .name = "rfr",
        .translate = translate_rfr_s,
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "round.s",
        .translate = translate_ftoi_s,
        .par = (const uint32_t[]){float_round_nearest_even, false},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "ssi",
        .translate = translate_ldsti,
        .par = (const uint32_t[]){true, false},
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    }, {
        .name = "ssiu",
        .translate = translate_ldsti,
        .par = (const uint32_t[]){true, true},
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    }, {
        .name = "ssx",
        .translate = translate_ldstx,
        .par = (const uint32_t[]){true, false},
        .windowed_register_op = 0x6,
        .coprocessor = 0x1,
    }, {
        .name = "ssxu",
        .translate = translate_ldstx,
        .par = (const uint32_t[]){true, true},
        .windowed_register_op = 0x6,
        .coprocessor = 0x1,
    }, {
        .name = "sub.s",
        .translate = translate_sub_s,
        .coprocessor = 0x1,
    }, {
        .name = "trunc.s",
        .translate = translate_ftoi_s,
        .par = (const uint32_t[]){float_round_to_zero, false},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "ueq.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_UEQ},
        .coprocessor = 0x1,
    }, {
        .name = "ufloat.s",
        .translate = translate_float_s,
        .par = (const uint32_t[]){true},
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    }, {
        .name = "ule.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_ULE},
        .coprocessor = 0x1,
    }, {
        .name = "ult.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_ULT},
        .coprocessor = 0x1,
    }, {
        .name = "un.s",
        .translate = translate_compare_s,
        .par = (const uint32_t[]){COMPARE_UN},
        .coprocessor = 0x1,
    }, {
        .name = "utrunc.s",
        .translate = translate_ftoi_s,
        .par = (const uint32_t[]){float_round_to_zero, true},
        .windowed_register_op = 0x1,
        .coprocessor = 0x1,
    }, {
        .name = "wfr",
        .translate = translate_wfr_s,
        .windowed_register_op = 0x2,
        .coprocessor = 0x1,
    },
};