From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55239) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WukKf-0001Cx-Ti for qemu-devel@nongnu.org; Wed, 11 Jun 2014 11:21:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WukKa-00041x-NO for qemu-devel@nongnu.org; Wed, 11 Jun 2014 11:20:57 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:46625) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WukKa-00041f-FJ for qemu-devel@nongnu.org; Wed, 11 Jun 2014 11:20:52 -0400 From: Leon Alrae Date: Wed, 11 Jun 2014 16:19:32 +0100 Message-ID: <1402499992-64851-3-git-send-email-leon.alrae@imgtec.com> In-Reply-To: <1402499992-64851-1-git-send-email-leon.alrae@imgtec.com> References: <1402499992-64851-1-git-send-email-leon.alrae@imgtec.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH v2 02/22] target-mips: signal RI Exception on instructions removed in R6 List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com, leon.alrae@imgtec.com, aurelien@aurel32.net, rth@twiddle.net Signal Reserved Instruction Exception on instructions that do not exist in R6. In this commit the following groups of preR6 instructions are marked as deleted: - Floating Point Paired Single - Floating Point Compare - conditional moves / branches on FPU conditions - branch likelies - unaligned loads / stores - traps - legacy accumulator instructions - COP1X - MIPS-3D Signed-off-by: Leon Alrae Reviewed-by: Aurelien Jarno --- target-mips/translate.c | 64 +++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 56 insertions(+), 8 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 76deb7b..dbb3746 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1430,6 +1430,16 @@ static inline void check_insn(DisasContext *ctx, int flags) } } +/* This code generates a "reserved instruction" exception if the + CPU has corresponding flag set which indicates that the instruction + has been removed. */ +static inline void check_insn_opc_removed(DisasContext *ctx, int flags) +{ + if (unlikely(ctx->insn_flags & flags)) { + generate_exception(ctx, EXCP_RI); + } +} + /* This code generates a "reserved instruction" exception if 64-bit instructions are not enabled. */ static inline void check_mips_64(DisasContext *ctx) @@ -7667,10 +7677,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "floor.w.s"; break; case OPC_MOVCF_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.s"; break; case OPC_MOVZ_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i32 fp0; @@ -7687,6 +7699,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "movz.s"; break; case OPC_MOVN_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i32 fp0; @@ -7820,6 +7833,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "cvt.l.s"; break; case OPC_CVT_PS_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cp1_64bitmode(ctx); { TCGv_i64 fp64 = tcg_temp_new_i64(); @@ -7852,6 +7866,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, case OPC_CMP_NGE_S: case OPC_CMP_LE_S: case OPC_CMP_NGT_S: + check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & (1 << 6)) { gen_cmpabs_s(ctx, func-48, ft, fs, cc); opn = condnames_abs[func-48]; @@ -8076,10 +8091,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "floor.w.d"; break; case OPC_MOVCF_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1); opn = "movcf.d"; break; case OPC_MOVZ_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i64 fp0; @@ -8096,6 +8113,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "movz.d"; break; case OPC_MOVN_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); { int l1 = gen_new_label(); TCGv_i64 fp0; @@ -8205,6 +8223,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, case OPC_CMP_NGE_D: case OPC_CMP_LE_D: case OPC_CMP_NGT_D: + check_insn_opc_removed(ctx, ISA_MIPS32R6); if (ctx->opcode & (1 << 6)) { gen_cmpabs_d(ctx, func-48, ft, fs, cc); opn = condnames_abs[func-48]; @@ -8305,6 +8324,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1, opn = "cvt.d.l"; break; case OPC_CVT_PS_PW: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cp1_64bitmode(ctx); { TCGv_i64 fp0 = tcg_temp_new_i64(); @@ -14455,6 +14475,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_MOVN: /* Conditional move */ case OPC_MOVZ: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 | INSN_LOONGSON2E | INSN_LOONGSON2F); gen_cond_move(ctx, op1, rd, rs, rt); @@ -14515,10 +14536,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_MFHI: /* Move from HI/LO */ case OPC_MFLO: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_HILO(ctx, op1, rs & 3, rd); break; case OPC_MTHI: case OPC_MTLO: /* Move to HI/LO */ + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_HILO(ctx, op1, rd & 3, rs); break; case OPC_PMON: /* Pmon entry point, also R4010 selsl */ @@ -14551,6 +14574,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_MOVCI: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_insn(ctx, ISA_MIPS4 | ISA_MIPS32); if (env->CP0_Config1 & (1 << CP0C1_FP)) { check_cp1_enabled(ctx); @@ -14653,10 +14677,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) switch (op1) { case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */ case OPC_MSUB ... OPC_MSUBU: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_insn(ctx, ISA_MIPS32); gen_muldiv(ctx, op1, rd & 3, rs, rt); break; case OPC_MUL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_arith(ctx, op1, rd, rs, rt); break; case OPC_CLO: @@ -15271,12 +15297,20 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) case OPC_REGIMM: op1 = MASK_REGIMM(ctx->opcode); switch (op1) { - case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */ - case OPC_BLTZAL ... OPC_BGEZALL: + case OPC_BLTZL: /* REGIMM branches */ + case OPC_BGEZL: + case OPC_BLTZALL: + case OPC_BGEZALL: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_BLTZ: + case OPC_BGEZ: + case OPC_BLTZAL: + case OPC_BGEZAL: gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2); break; case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */ case OPC_TNEI: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_trap(ctx, op1, rs, -1, imm); break; case OPC_SYNCI: @@ -15401,16 +15435,24 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2; gen_compute_branch(ctx, op, 4, rs, rt, offset); break; - case OPC_BEQ ... OPC_BGTZ: /* Branch */ - case OPC_BEQL ... OPC_BGTZL: + case OPC_BEQL ... OPC_BGTZL: /* Branch */ + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_BEQ ... OPC_BGTZ: gen_compute_branch(ctx, op, 4, rs, rt, imm << 2); break; - case OPC_LB ... OPC_LWR: /* Load and stores */ + case OPC_LWL: /* Load and stores */ + case OPC_LWR: + 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_SB ... OPC_SW: + case OPC_SWL: case OPC_SWR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_SB ... OPC_SH: + case OPC_SW: gen_st(ctx, op, rt, rs, imm); break; case OPC_SC: @@ -15457,18 +15499,21 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) #endif case OPC_BC1ANY2: case OPC_BC1ANY4: + check_insn_opc_removed(ctx, ISA_MIPS32R6); check_cop1x(ctx); check_insn(ctx, ASE_MIPS3D); /* fall through */ case OPC_BC1: + check_insn_opc_removed(ctx, ISA_MIPS32R6); gen_compute_branch1(ctx, MASK_BC1(ctx->opcode), (rt >> 2) & 0x7, imm << 2); break; + case OPC_PS_FMT: + check_insn_opc_removed(ctx, ISA_MIPS32R6); case OPC_S_FMT: case OPC_D_FMT: case OPC_W_FMT: case OPC_L_FMT: - case OPC_PS_FMT: gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa, (imm >> 8) & 0x7); break; @@ -15497,6 +15542,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) break; case OPC_CP3: + check_insn_opc_removed(ctx, ISA_MIPS32R6); if (env->CP0_Config1 & (1 << CP0C1_FP)) { check_cp1_enabled(ctx); op1 = MASK_CP3(ctx->opcode); @@ -15539,8 +15585,9 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) #if defined(TARGET_MIPS64) /* MIPS64 opcodes */ - case OPC_LWU: case OPC_LDL ... OPC_LDR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); + case OPC_LWU: case OPC_LLD: case OPC_LD: check_insn(ctx, ISA_MIPS3); @@ -15548,6 +15595,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx) gen_ld(ctx, op, rt, rs, imm); break; case OPC_SDL ... OPC_SDR: + check_insn_opc_removed(ctx, ISA_MIPS32R6); case OPC_SD: check_insn(ctx, ISA_MIPS3); check_mips_64(ctx); -- 1.7.5.4