qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH 02/21] target-mips: signal RI Exception on instr


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH 02/21] target-mips: signal RI Exception on instructions removed in R6
Date: Fri, 30 May 2014 18:43:48 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

On Fri, May 30, 2014 at 03:47:40PM +0100, Leon Alrae wrote:
> 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 <address@hidden>
> ---
>  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 05f82d2..2ac8023 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);

Reviewed-by: Aurelien Jarno <address@hidden>

Just a comment, not related to QEMU: while it looks at a first glance to
build a binary that runs on both pre-R6 and R6 by not using the removed
instructions, I do wonder how the transition would be done for unaligned
load/stores. On pre-R6, unaligned load/stores are not supported so 
LDR/LDL must be used, while on R6 LDR/LDL are not supported, so
unaligned load/stores should be used instead...

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
address@hidden                 http://www.aurel32.net



reply via email to

[Prev in Thread] Current Thread [Next in Thread]