mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 17:35:33 +00:00
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:
parent
38f2640a34
commit
7e0342c9f6
|
@ -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};
|
||||||
|
|
Loading…
Reference in a new issue