target/mips: Add availability control via bit NMS

A set of nanoMIPS instructions is not available if Config5 bit NMS
is set.

Backports commit fb32f8c8560be7ca4e323cee1b839701126401d1 from qemu
This commit is contained in:
Dimitrije Nikolic 2018-08-27 14:58:59 -04:00 committed by Lioncash
parent 38f2640a34
commit 7e0342c9f6
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7

View file

@ -1963,6 +1963,17 @@ static inline void check_cp0_mt(DisasContext *ctx)
} }
#endif #endif
/*
* This code generates a "reserved instruction" exception if the
* Config5 NMS bit is set.
*/
static inline void check_nms(DisasContext *ctx)
{
if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
generate_exception_end(ctx, EXCP_RI);
}
}
/* Define small wrappers for gen_load_fpr* so that we have a uniform /* Define small wrappers for gen_load_fpr* so that we have a uniform
calling interface for 32 and 64-bit FPRs. No sense in changing calling interface for 32 and 64-bit FPRs. No sense in changing
@ -17118,17 +17129,21 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
case NM_P_TRAP: case NM_P_TRAP:
switch (extract32(ctx->opcode, 10, 1)) { switch (extract32(ctx->opcode, 10, 1)) {
case NM_TEQ: case NM_TEQ:
check_nms(ctx);
gen_trap(ctx, OPC_TEQ, rs, rt, -1); gen_trap(ctx, OPC_TEQ, rs, rt, -1);
break; break;
case NM_TNE: case NM_TNE:
check_nms(ctx);
gen_trap(ctx, OPC_TNE, rs, rt, -1); gen_trap(ctx, OPC_TNE, rs, rt, -1);
break; break;
} }
break; break;
case NM_RDHWR: case NM_RDHWR:
check_nms(ctx);
gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3)); gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
break; break;
case NM_SEB: case NM_SEB:
check_nms(ctx);
gen_bshfl(ctx, OPC_SEB, rs, rt); gen_bshfl(ctx, OPC_SEB, rs, rt);
break; break;
case NM_SEH: case NM_SEH:
@ -17153,6 +17168,7 @@ static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
gen_arith(ctx, OPC_ADDU, rd, rs, rt); gen_arith(ctx, OPC_ADDU, rd, rs, rt);
break; break;
case NM_SUB: case NM_SUB:
check_nms(ctx);
gen_arith(ctx, OPC_SUB, rd, rs, rt); gen_arith(ctx, OPC_SUB, rd, rs, rt);
break; break;
case NM_SUBU: case NM_SUBU:
@ -18019,9 +18035,11 @@ static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
gen_bitswap(ctx, OPC_BITSWAP, ret, rs); gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
break; break;
case NM_CLO: case NM_CLO:
check_nms(ctx);
gen_cl(ctx, OPC_CLO, ret, rs); gen_cl(ctx, OPC_CLO, ret, rs);
break; break;
case NM_CLZ: case NM_CLZ:
check_nms(ctx);
gen_cl(ctx, OPC_CLZ, ret, rs); gen_cl(ctx, OPC_CLZ, ret, rs);
break; break;
case NM_WSBH: case NM_WSBH:
@ -18227,6 +18245,7 @@ static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
break; break;
case NM_BBEQZC: case NM_BBEQZC:
case NM_BBNEZC: case NM_BBNEZC:
check_nms(ctx);
if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) { if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
generate_exception_end(ctx, EXCP_RI); generate_exception_end(ctx, EXCP_RI);
goto out; goto out;
@ -18531,13 +18550,15 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
if ((extract32(ctx->opcode, 6, 1)) == 1) { if ((extract32(ctx->opcode, 6, 1)) == 1) {
/* PP.LSXS instructions require shifting */ /* PP.LSXS instructions require shifting */
switch (extract32(ctx->opcode, 7, 4)) { switch (extract32(ctx->opcode, 7, 4)) {
case NM_LHXS:
case NM_SHXS: case NM_SHXS:
check_nms(ctx);
case NM_LHXS:
case NM_LHUXS: case NM_LHUXS:
tcg_gen_shli_tl(tcg_ctx, t0, t0, 1); tcg_gen_shli_tl(tcg_ctx, t0, t0, 1);
break; break;
case NM_LWXS:
case NM_SWXS: case NM_SWXS:
check_nms(ctx);
case NM_LWXS:
case NM_LWC1XS: case NM_LWC1XS:
case NM_SWC1XS: case NM_SWC1XS:
tcg_gen_shli_tl(tcg_ctx, t0, t0, 2); tcg_gen_shli_tl(tcg_ctx, t0, t0, 2);
@ -18580,18 +18601,21 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
gen_store_gpr(tcg_ctx, t0, rd); gen_store_gpr(tcg_ctx, t0, rd);
break; break;
case NM_SBX: case NM_SBX:
check_nms(ctx);
gen_load_gpr(ctx, t1, rd); gen_load_gpr(ctx, t1, rd);
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx,
MO_8); MO_8);
break; break;
case NM_SHX: case NM_SHX:
/*case NM_SHXS:*/ /*case NM_SHXS:*/
check_nms(ctx);
gen_load_gpr(ctx, t1, rd); gen_load_gpr(ctx, t1, rd);
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx,
MO_TEUW); MO_TEUW);
break; break;
case NM_SWX: case NM_SWX:
/*case NM_SWXS:*/ /*case NM_SWXS:*/
check_nms(ctx);
gen_load_gpr(ctx, t1, rd); gen_load_gpr(ctx, t1, rd);
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx,
MO_TEUL); MO_TEUL);
@ -19617,22 +19641,26 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16; target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
switch (extract32(ctx->opcode, 16, 5)) { switch (extract32(ctx->opcode, 16, 5)) {
case NM_LI48: case NM_LI48:
check_nms(ctx);
if (rt != 0) { if (rt != 0) {
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_gpr[rt], addr_off); tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_gpr[rt], addr_off);
} }
break; break;
case NM_ADDIU48: case NM_ADDIU48:
check_nms(ctx);
if (rt != 0) { if (rt != 0) {
tcg_gen_addi_tl(tcg_ctx, tcg_ctx->cpu_gpr[rt], tcg_ctx->cpu_gpr[rt], addr_off); tcg_gen_addi_tl(tcg_ctx, tcg_ctx->cpu_gpr[rt], tcg_ctx->cpu_gpr[rt], addr_off);
tcg_gen_ext32s_tl(tcg_ctx, tcg_ctx->cpu_gpr[rt], tcg_ctx->cpu_gpr[rt]); tcg_gen_ext32s_tl(tcg_ctx, tcg_ctx->cpu_gpr[rt], tcg_ctx->cpu_gpr[rt]);
} }
break; break;
case NM_ADDIUGP48: case NM_ADDIUGP48:
check_nms(ctx);
if (rt != 0) { if (rt != 0) {
gen_op_addr_addi(ctx, tcg_ctx->cpu_gpr[rt], tcg_ctx->cpu_gpr[28], addr_off); gen_op_addr_addi(ctx, tcg_ctx->cpu_gpr[rt], tcg_ctx->cpu_gpr[28], addr_off);
} }
break; break;
case NM_ADDIUPC48: case NM_ADDIUPC48:
check_nms(ctx);
if (rt != 0) { if (rt != 0) {
target_long addr = addr_add(ctx, ctx->base.pc_next + 6, target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
addr_off); addr_off);
@ -19641,6 +19669,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
} }
break; break;
case NM_LWPC48: case NM_LWPC48:
check_nms(ctx);
if (rt != 0) { if (rt != 0) {
TCGv t0; TCGv t0;
t0 = tcg_temp_new(tcg_ctx); t0 = tcg_temp_new(tcg_ctx);
@ -19654,6 +19683,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
} }
break; break;
case NM_SWPC48: case NM_SWPC48:
check_nms(ctx);
{ {
TCGv t0, t1; TCGv t0, t1;
t0 = tcg_temp_new(tcg_ctx); t0 = tcg_temp_new(tcg_ctx);
@ -19774,6 +19804,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
} }
break; break;
case NM_P_ROTX: case NM_P_ROTX:
check_nms(ctx);
if (rt != 0) { if (rt != 0) {
TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t0 = tcg_temp_new(tcg_ctx);
TCGv_i32 shift = tcg_const_i32(tcg_ctx, extract32(ctx->opcode, 0, 5)); TCGv_i32 shift = tcg_const_i32(tcg_ctx, extract32(ctx->opcode, 0, 5));
@ -19791,6 +19822,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
} }
break; break;
case NM_P_INS: case NM_P_INS:
check_nms(ctx);
switch (((ctx->opcode >> 10) & 2) | switch (((ctx->opcode >> 10) & 2) |
(extract32(ctx->opcode, 5, 1))) { (extract32(ctx->opcode, 5, 1))) {
case NM_INS: case NM_INS:
@ -19806,6 +19838,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
switch (((ctx->opcode >> 10) & 2) | switch (((ctx->opcode >> 10) & 2) |
(extract32(ctx->opcode, 5, 1))) { (extract32(ctx->opcode, 5, 1))) {
case NM_EXT: case NM_EXT:
check_nms(ctx);
gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5), gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
extract32(ctx->opcode, 6, 5)); extract32(ctx->opcode, 6, 5));
break; break;
@ -20032,6 +20065,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
switch (extract32(ctx->opcode, 11, 4)) { switch (extract32(ctx->opcode, 11, 4)) {
case NM_UALH: case NM_UALH:
case NM_UASH: case NM_UASH:
check_nms(ctx);
{ {
TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t0 = tcg_temp_new(tcg_ctx);
TCGv t1 = tcg_temp_new(tcg_ctx); TCGv t1 = tcg_temp_new(tcg_ctx);
@ -20086,6 +20120,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
break; break;
case NM_P_LS_WM: case NM_P_LS_WM:
case NM_P_LS_UAWM: case NM_P_LS_UAWM:
check_nms(ctx);
{ {
int count = extract32(ctx->opcode, 12, 3); int count = extract32(ctx->opcode, 12, 3);
int counter = 0; int counter = 0;
@ -20134,6 +20169,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
} }
break; break;
case NM_MOVE_BALC: case NM_MOVE_BALC:
check_nms(ctx);
{ {
TCGv t0 = tcg_temp_new(tcg_ctx); TCGv t0 = tcg_temp_new(tcg_ctx);
int32_t s = sextract32(ctx->opcode, 0, 1) << 21 | int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
@ -20181,6 +20217,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
extract32(ctx->opcode, 1, 13) << 1; extract32(ctx->opcode, 1, 13) << 1;
switch (extract32(ctx->opcode, 14, 2)) { switch (extract32(ctx->opcode, 14, 2)) {
case NM_BEQC: case NM_BEQC:
check_nms(ctx);
gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s); gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
break; break;
case NM_P_BR3A: case NM_P_BR3A:
@ -20234,6 +20271,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
extract32(ctx->opcode, 1, 13) << 1; extract32(ctx->opcode, 1, 13) << 1;
switch (extract32(ctx->opcode, 14, 2)) { switch (extract32(ctx->opcode, 14, 2)) {
case NM_BNEC: case NM_BNEC:
check_nms(ctx);
gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s); gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
break; break;
case NM_BLTC: case NM_BLTC:
@ -20408,9 +20446,11 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
switch ((extract32(ctx->opcode, 7, 2) & 0x2) | switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
(extract32(ctx->opcode, 3, 1))) { (extract32(ctx->opcode, 3, 1))) {
case NM_ADDU4X4: case NM_ADDU4X4:
check_nms(ctx);
gen_arith(ctx, OPC_ADDU, rt, rs, rt); gen_arith(ctx, OPC_ADDU, rt, rs, rt);
break; break;
case NM_MUL4X4: case NM_MUL4X4:
check_nms(ctx);
gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt); gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
break; break;
default: default:
@ -20476,6 +20516,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
gen_ld(ctx, OPC_LW, rt, 29, offset); gen_ld(ctx, OPC_LW, rt, 29, offset);
break; break;
case NM_LW4X4: case NM_LW4X4:
check_nms(ctx);
rt = (extract32(ctx->opcode, 9, 1) << 3) | rt = (extract32(ctx->opcode, 9, 1) << 3) |
extract32(ctx->opcode, 5, 3); extract32(ctx->opcode, 5, 3);
rs = (extract32(ctx->opcode, 4, 1) << 3) | rs = (extract32(ctx->opcode, 4, 1) << 3) |
@ -20487,6 +20528,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
gen_ld(ctx, OPC_LW, rt, rs, offset); gen_ld(ctx, OPC_LW, rt, rs, offset);
break; break;
case NM_SW4X4: case NM_SW4X4:
check_nms(ctx);
rt = (extract32(ctx->opcode, 9, 1) << 3) | rt = (extract32(ctx->opcode, 9, 1) << 3) |
extract32(ctx->opcode, 5, 3); extract32(ctx->opcode, 5, 3);
rs = (extract32(ctx->opcode, 4, 1) << 3) | rs = (extract32(ctx->opcode, 4, 1) << 3) |
@ -20585,6 +20627,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
case NM_MOVEP: case NM_MOVEP:
break; break;
case NM_MOVEPREV: case NM_MOVEPREV:
check_nms(ctx);
{ {
static const int gpr2reg1[] = {4, 5, 6, 7}; static const int gpr2reg1[] = {4, 5, 6, 7};
static const int gpr2reg2[] = {5, 6, 7, 8}; static const int gpr2reg2[] = {5, 6, 7, 8};