From 4368b29a26ebd13db95325b3511c0157ea9826f0 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Fri, 27 Jun 2014 08:49:01 +0100 Subject: [PATCH] target-mips: move LL and SC instructions The encoding of LL and SC instruction has changed in MIPS32 Release 6. Signed-off-by: Leon Alrae Reviewed-by: Aurelien Jarno Reviewed-by: James Hogan --- disas/mips.c | 9 ++++++++- target-mips/translate.c | 28 ++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/disas/mips.c b/disas/mips.c index b950e539e8..f0efa8b29c 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -119,6 +119,8 @@ see . */ #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, 0xfc00007f, LDD|RD_b|WR_t, 0, I32R6}, +{"sc", "t,o(b)", 0x7c000026, 0xfc00007f, 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 ba9daac32b..8606f32499 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -347,6 +347,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 */ @@ -1775,6 +1779,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); @@ -1868,6 +1873,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"; @@ -14804,6 +14810,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); @@ -15108,6 +15118,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: @@ -15123,7 +15146,7 @@ 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(ctx, INSN_LOONGSON2E); gen_loongson_integer(ctx, op1, rd, rs, rt); break; @@ -15512,10 +15535,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: @@ -15526,6 +15549,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: