The encoding of LL and SC instruction has changed in MIPS32 Release 6. Signed-off-by: Leon Alrae <leon.al...@imgtec.com> Reviewed-by: Aurelien Jarno <aurel...@aurel32.net> --- disas/mips.c | 9 ++++++++- target-mips/translate.c | 29 +++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/disas/mips.c b/disas/mips.c index b950e53..f41b89d 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -119,6 +119,8 @@ see <http://www.gnu.org/licenses/>. */ #define OP_SH_IMMEDIATE 0 #define OP_MASK_DELTA 0xffff #define OP_SH_DELTA 0 +#define OP_MASK_DELTA_R6 0x1ff +#define OP_SH_DELTA_R6 7 #define OP_MASK_FUNCT 0x3f #define OP_SH_FUNCT 0 #define OP_MASK_SPEC 0x3f @@ -1215,6 +1217,8 @@ const struct mips_opcode mips_builtin_opcodes[] = them first. The assemblers uses a hash table based on the instruction name anyhow. */ /* name, args, match, mask, pinfo, membership */ +{"ll", "t,o(b)", 0x7c000036, 0xfc00003f, LDD|RD_b|WR_t, 0, I32R6}, +{"sc", "t,o(b)", 0x7c000026, 0xfc00003f, LDD|RD_b|WR_t, 0, I32R6}, {"seleqz", "d,v,t", 0x00000035, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, {"selnez", "d,v,t", 0x00000037, 0xfc0007ff, WR_d|RD_s|RD_t, 0, I32R6}, {"pref", "k,o(b)", 0xcc000000, 0xfc000000, RD_b, 0, I4|I32|G3 }, @@ -3734,7 +3738,10 @@ print_insn_args (const char *d, case 'j': /* Same as i, but sign-extended. */ case 'o': - delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA; + delta = (opp->membership == I32R6) ? + (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6 : + (l >> OP_SH_DELTA) & OP_MASK_DELTA; + if (delta & 0x8000) delta |= ~0xffff; (*info->fprintf_func) (info->stream, "%d", diff --git a/target-mips/translate.c b/target-mips/translate.c index 4eb8a61..75b28e2 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -345,6 +345,10 @@ enum { /* MIPS DSP Accumulator and DSPControl Access Sub-class */ OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3, OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3, + + /* R6 */ + R6_OPC_LL = 0x36 | OPC_SPECIAL3, + R6_OPC_SC = 0x26 | OPC_SPECIAL3, }; /* BSHFL opcodes */ @@ -1771,6 +1775,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc, opn = "lwr"; break; case OPC_LL: + case R6_OPC_LL: save_cpu_state(ctx, 1); op_ld_ll(t0, t0, ctx); gen_store_gpr(t0, rt); @@ -1864,6 +1869,7 @@ static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt, break; #endif case OPC_SC: + case R6_OPC_SC: save_cpu_state(ctx, 1); op_st_sc(t1, t0, rt, ctx); opn = "sc"; @@ -14753,6 +14759,10 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) case OPC_SPECIAL3: op1 = MASK_SPECIAL3(ctx->opcode); switch (op1) { + case R6_OPC_LL: + check_insn(ctx, ISA_MIPS32R6); + gen_ld(ctx, op1, rt, rs, imm >> 7); + break; case OPC_EXT: case OPC_INS: check_insn(ctx, ISA_MIPS32R2); @@ -15057,6 +15067,19 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; } break; + case R6_OPC_SC: /* OPC_DMOD_G_2E */ + if (ctx->insn_flags & ISA_MIPS32R6) { + gen_st_cond(ctx, op1, rt, rs, imm >> 7); + } else { +#if defined(TARGET_MIPS64) + check_insn(ctx, INSN_LOONGSON2E); + gen_loongson_integer(ctx, op1, rd, rs, rt); +#else + /* Invalid in MIPS32 */ + generate_exception(ctx, EXCP_RI); +#endif + } + break; #if defined(TARGET_MIPS64) case OPC_DEXTM ... OPC_DEXT: case OPC_DINSM ... OPC_DINS: @@ -15072,7 +15095,8 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E: case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E: - case OPC_DMOD_G_2E ... OPC_DMODU_G_2E: + case OPC_DMODU_G_2E: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_insn(ctx, INSN_LOONGSON2E); gen_loongson_integer(ctx, op1, rd, rs, rt); break; @@ -15458,10 +15482,10 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_LWL: /* Load and stores */ case OPC_LWR: + case OPC_LL: check_insn_opc_removed(ctx, ISA_MIPS32R6); case OPC_LB ... OPC_LH: case OPC_LW ... OPC_LHU: - case OPC_LL: gen_ld(ctx, op, rt, rs, imm); break; case OPC_SWL: @@ -15472,6 +15496,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) gen_st(ctx, op, rt, rs, imm); break; case OPC_SC: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_st_cond(ctx, op, rt, rs, imm); break; case OPC_CACHE: -- 1.7.5.4