target/mips: Decode microMIPS EVA load & store instructions

Implement decoding of microMIPS EVA load and store instruction groups in
the POOL31C pool. These use the same gen_ld(), gen_st(), gen_st_cond()
helpers as the MIPS32 decoding, passing the equivalent MIPS32 opcodes as
opc.

Backports commit 8fffc64696783b1ff1d17262d098976479895660 from qemu
This commit is contained in:
James Hogan 2018-03-04 00:37:32 -05:00 committed by Lioncash
parent 8fadc55db3
commit 54b349aee5
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -12636,19 +12636,45 @@ enum {
LWR = 0x1,
SWR = 0x9,
PREF = 0x2,
/* 0xa is reserved */
ST_EVA = 0xa,
LL = 0x3,
SC = 0xb,
LDL = 0x4,
SDL = 0xc,
LDR = 0x5,
SDR = 0xd,
/* 0x6 is reserved */
LD_EVA = 0x6,
LWU = 0xe,
LLD = 0x7,
SCD = 0xf
};
/* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
enum {
LBUE = 0x0,
LHUE = 0x1,
LWLE = 0x2,
LWRE = 0x3,
LBE = 0x4,
LHE = 0x5,
LLE = 0x6,
LWE = 0x7,
};
/* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
enum {
SWLE = 0x0,
SWRE = 0x1,
PREFE = 0x2,
CACHEE = 0x3,
SBE = 0x4,
SHE = 0x5,
SCE = 0x6,
SWE = 0x7,
};
/* POOL32F encoding of minor opcode field (bits 5..0) */
enum {
@ -13950,7 +13976,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
uint16_t insn;
int rt, rs, rd, rr;
int16_t imm;
uint32_t op, minor, mips32_op;
uint32_t op, minor, minor2, mips32_op;
uint32_t cond, fmt, cc;
insn = cpu_lduw_code(env, ctx->pc + 2);
@ -14895,7 +14921,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
gen_ld(ctx, mips32_op, rt, rs, offset);
break;
do_st_lr:
gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
gen_st(ctx, mips32_op, rt, rs, offset);
break;
case SC:
gen_st_cond(ctx, OPC_SC, rt, rs, offset);
@ -14907,6 +14933,91 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
gen_st_cond(ctx, OPC_SCD, rt, rs, offset);
break;
#endif
case LD_EVA:
if (!ctx->eva) {
MIPS_INVAL("pool32c ld-eva");
generate_exception_end(ctx, EXCP_RI);
break;
}
check_cp0_enabled(ctx);
minor2 = (ctx->opcode >> 9) & 0x7;
offset = sextract32(ctx->opcode, 0, 9);
switch (minor2) {
case LBUE:
mips32_op = OPC_LBUE;
goto do_ld_lr;
case LHUE:
mips32_op = OPC_LHUE;
goto do_ld_lr;
case LWLE:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
mips32_op = OPC_LWLE;
goto do_ld_lr;
case LWRE:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
mips32_op = OPC_LWRE;
goto do_ld_lr;
case LBE:
mips32_op = OPC_LBE;
goto do_ld_lr;
case LHE:
mips32_op = OPC_LHE;
goto do_ld_lr;
case LLE:
mips32_op = OPC_LLE;
goto do_ld_lr;
case LWE:
mips32_op = OPC_LWE;
goto do_ld_lr;
};
break;
case ST_EVA:
if (!ctx->eva) {
MIPS_INVAL("pool32c st-eva");
generate_exception_end(ctx, EXCP_RI);
break;
}
check_cp0_enabled(ctx);
minor2 = (ctx->opcode >> 9) & 0x7;
offset = sextract32(ctx->opcode, 0, 9);
switch (minor2) {
case SWLE:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
mips32_op = OPC_SWLE;
goto do_st_lr;
case SWRE:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
mips32_op = OPC_SWRE;
goto do_st_lr;
case PREFE:
/* Treat as no-op */
if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {
/* hint codes 24-31 are reserved and signal RI */
generate_exception(ctx, EXCP_RI);
}
break;
case CACHEE:
/* Treat as no-op */
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
gen_cache_operation(ctx, rt, rs, offset);
}
break;
case SBE:
mips32_op = OPC_SBE;
goto do_st_lr;
case SHE:
mips32_op = OPC_SHE;
goto do_st_lr;
case SCE:
gen_st_cond(ctx, OPC_SCE, rt, rs, offset);
break;
case SWE:
mips32_op = OPC_SWE;
goto do_st_lr;
};
break;
case PREF:
/* Treat as no-op */
if ((ctx->insn_flags & ISA_MIPS32R6) && (rt >= 24)) {