target/mips: Add availability control via bit NMS

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

Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com>
Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
This commit is contained in:
Dimitrije Nikolic 2018-08-20 18:51:45 +02:00 committed by Aleksandar Markovic
parent 0b591184a2
commit fb32f8c856
1 changed files with 45 additions and 2 deletions

View File

@ -1957,6 +1957,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
@ -16999,17 +17010,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:
@ -17034,6 +17049,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:
@ -17895,9 +17911,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:
@ -18100,6 +18118,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;
@ -18400,13 +18419,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(t0, t0, 1); tcg_gen_shli_tl(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(t0, t0, 2); tcg_gen_shli_tl(t0, t0, 2);
@ -18449,18 +18470,21 @@ static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
gen_store_gpr(t0, rd); gen_store_gpr(t0, rd);
break; break;
case NM_SBX: case NM_SBX:
check_nms(ctx);
gen_load_gpr(t1, rd); gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, tcg_gen_qemu_st_tl(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(t1, rd); gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, tcg_gen_qemu_st_tl(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(t1, rd); gen_load_gpr(t1, rd);
tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
MO_TEUL); MO_TEUL);
@ -19483,22 +19507,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(cpu_gpr[rt], addr_off); tcg_gen_movi_tl(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(cpu_gpr[rt], cpu_gpr[rt], addr_off); tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]); tcg_gen_ext32s_tl(cpu_gpr[rt], 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, cpu_gpr[rt], cpu_gpr[28], addr_off); gen_op_addr_addi(ctx, cpu_gpr[rt], 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);
@ -19507,6 +19535,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(); t0 = tcg_temp_new();
@ -19520,6 +19549,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(); t0 = tcg_temp_new();
@ -19640,6 +19670,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(); TCGv t0 = tcg_temp_new();
TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5)); TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
@ -19660,6 +19691,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_INS: case NM_INS:
check_nms(ctx);
gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5), gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
extract32(ctx->opcode, 6, 5)); extract32(ctx->opcode, 6, 5));
break; break;
@ -19672,6 +19704,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;
@ -19898,6 +19931,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(); TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new(); TCGv t1 = tcg_temp_new();
@ -19952,6 +19986,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;
@ -20000,6 +20035,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(); TCGv t0 = tcg_temp_new();
int32_t s = sextract32(ctx->opcode, 0, 1) << 21 | int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
@ -20047,6 +20083,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:
@ -20100,6 +20137,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:
@ -20272,9 +20310,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:
@ -20347,6 +20387,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) |
@ -20358,6 +20399,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) |
@ -20455,6 +20497,7 @@ static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
break; break;
case NM_MOVEP: case NM_MOVEP:
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};