All of lore.kernel.org
 help / color / mirror / Atom feed
From: Aurelien Jarno <aurelien@aurel32.net>
To: Leon Alrae <leon.alrae@imgtec.com>
Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com,
	qemu-devel@nongnu.org, rth@twiddle.net
Subject: Re: [Qemu-devel] [PATCH v2 13/22] target-mips: add Compact Branches
Date: Thu, 19 Jun 2014 23:06:46 +0200	[thread overview]
Message-ID: <20140619210646.GA14196@ohm.rr44.fr> (raw)
In-Reply-To: <1402499992-64851-14-git-send-email-leon.alrae@imgtec.com>

On Wed, Jun 11, 2014 at 04:19:43PM +0100, Leon Alrae wrote:
> From: Yongbok Kim <yongbok.kim@imgtec.com>
> 
> Introduce MIPS32R6 Compact Branch instructions which do not have delay slot -
> they have forbidden slot instead. However, current implementation does not
> support forbidden slot yet.
> 
> Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com>
> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
> ---
> v2:
> * rename "handle_delay_slot" to "gen_branch"
> * Compact branches generate branch straightaway
> * improve BOVC/BNVC, BC1EQZ, BC1NEZ implementation
> ---
>  disas/mips.c            |   67 +++++++-
>  target-mips/cpu.h       |    5 +-
>  target-mips/translate.c |  481 +++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 534 insertions(+), 19 deletions(-)
> 
> diff --git a/disas/mips.c b/disas/mips.c
> index 127a7d5..bee39d8 100644
> --- a/disas/mips.c
> +++ b/disas/mips.c
> @@ -1250,6 +1250,34 @@ const struct mips_opcode mips_builtin_opcodes[] =
>  {"dalign",  "d,v,t",    0x7c000224, 0xfc00063f, WR_d|RD_s|RD_t,       0, I64R6},
>  {"bitswap", "d,w",      0x7c000020, 0xffe007ff, WR_d|RD_t,            0, I32R6},
>  {"dbitswap","d,w",      0x7c000024, 0xffe007ff, WR_d|RD_t,            0, I64R6},
> +{"balc",    "+p",       0xe8000000, 0xfc000000, UBD|WR_31,            0, I32R6},
> +{"bc",      "+p",       0xc8000000, 0xfc000000, UBD|WR_31,            0, I32R6},
> +{"jic",     "t,o",      0xd8000000, 0xffe00000, UBD|RD_t,             0, I32R6},
> +{"beqzc",   "s,+p",     0xd8000000, 0xfc000000, CBD|RD_s,             0, I32R6},
> +{"jialc",   "t,o",      0xf8000000, 0xffe00000, UBD|RD_t,             0, I32R6},
> +{"bnezc",   "s,+p",     0xf8000000, 0xfc000000, CBD|RD_s,             0, I32R6},
> +{"beqzalc", "s,t,p",    0x20000000, 0xffe00000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bovc",    "s,t,p",    0x20000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"beqc",    "s,t,p",    0x20000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bnezalc", "s,t,p",    0x60000000, 0xffe00000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bnvc",    "s,t,p",    0x60000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bnec",    "s,t,p",    0x60000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"blezc",   "s,t,p",    0x58000000, 0xffe00000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bgezc",   "s,t,p",    0x58000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bgec",    "s,t,p",    0x58000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bgtzc",   "s,t,p",    0x5c000000, 0xffe00000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bltzc",   "s,t,p",    0x5c000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bltc",    "s,t,p",    0x5c000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"blezalc", "s,t,p",    0x18000000, 0xffe00000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bgezalc", "s,t,p",    0x18000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bgeuc",   "s,t,p",    0x18000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bgtzalc", "s,t,p",    0x1c000000, 0xffe00000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bltzalc", "s,t,p",    0x1c000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bltuc",   "s,t,p",    0x1c000000, 0xfc000000, CBD|RD_s|RD_t,        0, I32R6},
> +{"bc1eqz",  "T,p",      0x45200000, 0xffe00000, CBD|RD_T|FP_S|FP_D,   0, I32R6},
> +{"bc1nez",  "T,p",      0x45a00000, 0xffe00000, CBD|RD_T|FP_S|FP_D,   0, I32R6},
> +{"bc2eqz",  "E,p",      0x49200000, 0xffe00000, CBD|RD_C2,            0, I32R6},
> +{"bc2nez",  "E,p",      0x49a00000, 0xffe00000, CBD|RD_C2,            0, I32R6},
>  {"pref",    "k,o(b)",   0xcc000000, 0xfc000000, RD_b,           	0,		I4|I32|G3	},
>  {"prefx",   "h,t(b)",	0x4c00000f, 0xfc0007ff, RD_b|RD_t,		0,		I4|I33	},
>  {"nop",     "",         0x00000000, 0xffffffff, 0,              	INSN2_ALIAS,	I1      }, /* sll */
> @@ -3616,6 +3644,24 @@ print_insn_args (const char *d,
>  	      (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
>  	      break;
>  
> +            case 'o':
> +                delta = (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6;
> +                if (delta & 0x8000) {
> +                    delta |= ~0xffff;
> +                }
> +                (*info->fprintf_func) (info->stream, "%d", delta);
> +                break;
> +
> +            case 'p':
> +                /* Sign extend the displacement with 26 bits.  */
> +                delta = (l >> OP_SH_DELTA) & OP_MASK_TARGET;
> +                if (delta & 0x2000000) {
> +                    delta |= ~0x3FFFFFF;
> +                }
> +                info->target = (delta << 2) + pc + INSNLEN;
> +                (*info->print_address_func) (info->target, info);
> +                break;
> +
>  	    case 't': /* Coprocessor 0 reg name */
>  	      (*info->fprintf_func) (info->stream, "%s",
>  				     mips_cp0_names[(l >> OP_SH_RT) &
> @@ -3767,9 +3813,7 @@ print_insn_args (const char *d,
>  
>  	case 'j': /* Same as i, but sign-extended.  */
>  	case 'o':
> -            delta = (opp->membership == I32R6) ?
> -                (l >> OP_SH_DELTA_R6) & OP_MASK_DELTA_R6 :
> -                (l >> OP_SH_DELTA) & OP_MASK_DELTA;
> +            delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
>  
>  	  if (delta & 0x8000)
>  	    delta |= ~0xffff;
> @@ -4096,6 +4140,23 @@ print_insn_mips (bfd_vma memaddr,
>  		  && strcmp (op->name, "jalx"))
>  		continue;
>  
> +              if (strcmp(op->name, "bovc") == 0
> +                  || strcmp(op->name, "bnvc") == 0) {
> +                  if (((word >> OP_SH_RS) & OP_MASK_RS) <
> +                      ((word >> OP_SH_RT) & OP_MASK_RT)) {
> +                      continue;
> +                  }
> +              }
> +              if (strcmp(op->name, "bgezc") == 0
> +                  || strcmp(op->name, "bltzc") == 0
> +                  || strcmp(op->name, "bgezalc") == 0
> +                  || strcmp(op->name, "bltzalc") == 0) {
> +                  if (((word >> OP_SH_RS) & OP_MASK_RS) !=
> +                      ((word >> OP_SH_RT) & OP_MASK_RT)) {
> +                      continue;
> +                  }
> +              }
> +
>  	      /* Figure out instruction type and branch delay information.  */
>  	      if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
>  	        {
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 85ff529..d1e932e 100644
> --- a/target-mips/cpu.h
> +++ b/target-mips/cpu.h
> @@ -466,10 +466,13 @@ struct CPUMIPSState {
>  #define MIPS_HFLAG_BDS16  0x08000 /* branch requires 16-bit delay slot  */
>  #define MIPS_HFLAG_BDS32  0x10000 /* branch requires 32-bit delay slot  */
>  #define MIPS_HFLAG_BX     0x20000 /* branch exchanges execution mode    */
> -#define MIPS_HFLAG_BMASK  (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT)
> +#define MIPS_HFLAG_BMASK  (MIPS_HFLAG_BMASK_BASE | MIPS_HFLAG_BMASK_EXT | \
> +                           MIPS_HFLAG_CB)
>      /* MIPS DSP resources access. */
>  #define MIPS_HFLAG_DSP   0x40000  /* Enable access to MIPS DSP resources. */
>  #define MIPS_HFLAG_DSPR2 0x80000  /* Enable access to MIPS DSPR2 resources. */
> +
> +#define MIPS_HFLAG_CB    0x100000  /* Compact branch */
>      target_ulong btarget;        /* Jump / branch target               */
>      target_ulong bcond;          /* Branch condition (if needed)       */
>  
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index 270e7d3..1226f97 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -107,6 +107,31 @@ enum {
>      OPC_SWC2     = (0x3A << 26),
>      OPC_SDC1     = (0x3D << 26),
>      OPC_SDC2     = (0x3E << 26),
> +    /* Compact Branches */
> +    OPC_BLEZALC  = (0x06 << 26),
> +    OPC_BGEZALC  = (0x06 << 26),
> +    OPC_BGEUC    = (0x06 << 26),
> +    OPC_BGTZALC  = (0x07 << 26),
> +    OPC_BLTZALC  = (0x07 << 26),
> +    OPC_BLTUC    = (0x07 << 26),
> +    OPC_BOVC     = (0x08 << 26),
> +    OPC_BEQZALC  = (0x08 << 26),
> +    OPC_BEQC     = (0x08 << 26),
> +    OPC_BLEZC    = (0x16 << 26),
> +    OPC_BGEZC    = (0x16 << 26),
> +    OPC_BGEC     = (0x16 << 26),
> +    OPC_BGTZC    = (0x17 << 26),
> +    OPC_BLTZC    = (0x17 << 26),
> +    OPC_BLTC     = (0x17 << 26),
> +    OPC_BNVC     = (0x18 << 26),
> +    OPC_BNEZALC  = (0x18 << 26),
> +    OPC_BNEC     = (0x18 << 26),
> +    OPC_BC       = (0x32 << 26),
> +    OPC_BEQZC    = (0x36 << 26),
> +    OPC_JIC      = (0x36 << 26),
> +    OPC_BALC     = (0x3A << 26),
> +    OPC_BNEZC    = (0x3E << 26),
> +    OPC_JIALC    = (0x3E << 26),
>      /* MDMX ASE specific */
>      OPC_MDMX     = (0x1E << 26),
>      /* Cache and prefetch */
> @@ -895,6 +920,8 @@ enum {
>      OPC_W_FMT    = (FMT_W << 21) | OPC_CP1,
>      OPC_L_FMT    = (FMT_L << 21) | OPC_CP1,
>      OPC_PS_FMT   = (FMT_PS << 21) | OPC_CP1,
> +    OPC_BC1EQZ   = (0x09 << 21) | OPC_CP1,
> +    OPC_BC1NEZ   = (0x0D << 21) | OPC_CP1,
>  };
>  
>  #define MASK_CP1_FUNC(op)       MASK_CP1(op) | (op & 0x3F)
> @@ -929,6 +956,8 @@ enum {
>      OPC_CTC2    = (0x06 << 21) | OPC_CP2,
>      OPC_MTHC2   = (0x07 << 21) | OPC_CP2,
>      OPC_BC2     = (0x08 << 21) | OPC_CP2,
> +    OPC_BC2EQZ  = (0x09 << 21) | OPC_CP2,
> +    OPC_BC2NEZ  = (0x0D << 21) | OPC_CP2,
>  };
>  
>  #define MASK_LMI(op)  (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
> @@ -1391,6 +1420,20 @@ static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv
>  #endif
>  }
>  
> +/* Addresses computation (translation time) */
> +static target_long addr_add(DisasContext *ctx, target_long base,
> +                            target_long offset)
> +{
> +    target_long sum = base + offset;
> +
> +#if defined(TARGET_MIPS64)
> +    if (ctx->hflags & MIPS_HFLAG_AWRAP) {
> +        sum = (int32_t)sum;
> +    }
> +#endif
> +    return sum;
> +}
> +
>  static inline void check_cp0_enabled(DisasContext *ctx)
>  {
>      if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
> @@ -3907,7 +3950,13 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
>  
>      if (ctx->hflags & MIPS_HFLAG_BMASK) {
>  #ifdef MIPS_DEBUG_DISAS
> -        LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
> +        if (ctx->hflags & MIPS_HFLAG_CB) {
> +            LOG_DISAS("Branch in forbidden slot at PC 0x" TARGET_FMT_lx "\n",
> +                      ctx->pc);
> +        } else {
> +            LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
> +                      ctx->pc);
> +        }
>  #endif
>          generate_exception(ctx, EXCP_RI);
>          goto out;
> @@ -7390,6 +7439,45 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
>      tcg_temp_free_i32(t0);
>  }
>  
> +/* R6 CP1 Branches (before delay slot) */
> +static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
> +                                   int32_t ft, int32_t offset)
> +{
> +    target_ulong btarget;
> +    const char *opn = "cp1 cond branch";
> +
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +    gen_load_fpr64(ctx, t0, ft);
> +    tcg_gen_andi_i64(t0, t0, 1);
> +
> +    btarget = addr_add(ctx, ctx->pc + 4, offset);
> +
> +    switch (op) {
> +    case OPC_BC1EQZ:
> +        tcg_gen_xori_i64(t0, t0, 1);
> +        opn = "bc1eqz";
> +        ctx->hflags |= MIPS_HFLAG_BC;
> +        break;
> +    case OPC_BC1NEZ:
> +        tcg_gen_mov_i64(t0, t0);

I suggested that, though it's basically useless. This could simply be
removed.

> +        opn = "bc1nez";
> +        ctx->hflags |= MIPS_HFLAG_BC;
> +        break;
> +    default:
> +        MIPS_INVAL(opn);
> +        generate_exception(ctx, EXCP_RI);
> +        return;
> +    }
> +
> +    tcg_gen_trunc_i64_tl(bcond, t0);
> +    tcg_temp_free_i64(t0);
> +
> +    (void)opn; /* avoid a compiler warning */
> +    MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
> +               ctx->hflags, btarget);
> +    ctx->btarget = btarget;
> +}
> +
>  /* Coprocessor 1 (FPU) */
>  
>  #define FOP(func, fmt) (((fmt) << 21) | (func))
> @@ -9387,7 +9475,7 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
>      tcg_temp_free(t0);
>  }
>  
> -static void handle_delay_slot(DisasContext *ctx, int insn_bytes)
> +static void gen_branch(DisasContext *ctx, int insn_bytes)
>  {
>      if (ctx->hflags & MIPS_HFLAG_BMASK) {
>          int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
> @@ -14706,6 +14794,252 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
>  
>  /* End MIPSDSP functions. */
>  
> +/* Compact Branches */
> +static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
> +                                       int rs, int rt, int32_t offset)
> +{
> +    target_ulong btgt = -1;
> +    int blink = 0;
> +    int bcond_compute = 0;
> +    TCGv t0 = tcg_temp_new();
> +    TCGv t1 = tcg_temp_new();
> +
> +    if (ctx->hflags & MIPS_HFLAG_BMASK) {
> +#ifdef MIPS_DEBUG_DISAS
> +        if (ctx->hflags & MIPS_HFLAG_CB) {
> +            LOG_DISAS("Branch in forbidden slot at PC 0x" TARGET_FMT_lx "\n",
> +                      ctx->pc);
> +        } else {
> +            LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n",
> +                      ctx->pc);
> +        }
> +#endif
> +        generate_exception(ctx, EXCP_RI);
> +        goto out;
> +    }
> +
> +    /* Load needed operands */
> +    switch (opc) {
> +    /* compact branch */
> +    case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
> +    case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
> +        gen_load_gpr(t0, rs);
> +        gen_load_gpr(t1, rt);
> +        bcond_compute = 1;
> +        btgt = addr_add(ctx, ctx->pc + 4, offset);
> +        if (rs <= rt && rs == 0) {
> +            /* OPC_BEQZALC, OPC_BNEZALC */
> +            blink = 31;
> +        }
> +        break;
> +    case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
> +    case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
> +        gen_load_gpr(t0, rs);
> +        gen_load_gpr(t1, rt);
> +        bcond_compute = 1;
> +        btgt = addr_add(ctx, ctx->pc + 4, offset);
> +        break;
> +    case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
> +    case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
> +        if (rs == 0 || rs == rt) {
> +            /* OPC_BLEZALC, OPC_BGEZALC */
> +            /* OPC_BGTZALC, OPC_BLTZALC */
> +            blink = 31;
> +        }
> +        gen_load_gpr(t0, rs);
> +        gen_load_gpr(t1, rt);
> +        bcond_compute = 1;
> +        btgt = addr_add(ctx, ctx->pc + 4, offset);
> +        break;
> +    case OPC_BC:
> +    case OPC_BALC:
> +        btgt = addr_add(ctx, ctx->pc + 4, offset);
> +        break;
> +    case OPC_BEQZC:
> +    case OPC_BNEZC:
> +        if (rs != 0) {
> +            /* OPC_BEQZC, OPC_BNEZC */
> +            gen_load_gpr(t0, rs);
> +            bcond_compute = 1;
> +            btgt = addr_add(ctx, ctx->pc + 4, offset);
> +        } else {
> +            /* OPC_JIC, OPC_JIALC */
> +            TCGv tbase = tcg_temp_new();
> +            TCGv toffset = tcg_temp_new();
> +
> +            gen_load_gpr(tbase, rt);
> +            tcg_gen_movi_tl(toffset, offset);
> +            gen_op_addr_add(ctx, btarget, tbase, toffset);
> +            tcg_temp_free(tbase);
> +            tcg_temp_free(toffset);
> +        }
> +        break;
> +    default:
> +        MIPS_INVAL("branch/jump");
> +        generate_exception(ctx, EXCP_RI);
> +        goto out;
> +    }
> +
> +    ctx->hflags |= MIPS_HFLAG_CB;
> +
> +    if (bcond_compute == 0) {
> +        /* No condition to be computed */
> +        switch (opc) {
> +        /* compact branches */
> +        case OPC_JIALC:
> +            blink = 31;
> +            /* Fallthrough */
> +        case OPC_JIC:
> +            ctx->hflags |= MIPS_HFLAG_BR;
> +            break;
> +        case OPC_BALC:
> +            blink = 31;
> +            /* Fallthrough */
> +        case OPC_BC:
> +            ctx->hflags |= MIPS_HFLAG_B;
> +            /* Always take and link */
> +            break;
> +        default:
> +            MIPS_INVAL("branch/jump");
> +            generate_exception(ctx, EXCP_RI);
> +            goto out;
> +        }
> +    } else {
> +        ctx->hflags |= MIPS_HFLAG_BC;
> +
> +        switch (opc) {
> +        case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
> +            if (rs == 0 && rt != 0) {
> +                /* OPC_BLEZALC */
> +                tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t1, 0);
> +            } else if (rs != 0 && rt != 0 && rs == rt) {
> +                /* OPC_BGEZALC */
> +                tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t1, 0);
> +            } else {
> +                /* OPC_BGEUC */
> +                tcg_gen_setcond_tl(TCG_COND_GEU, bcond, t0, t1);
> +            }
> +            break;
> +        case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
> +            if (rs == 0 && rt != 0) {
> +                /* OPC_BGTZALC */
> +                tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t1, 0);
> +            } else if (rs != 0 && rt != 0 && rs == rt) {
> +                /* OPC_BLTZALC */
> +                tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t1, 0);
> +            } else {
> +                /* OPC_BLTUC */
> +                tcg_gen_setcond_tl(TCG_COND_LTU, bcond, t0, t1);
> +            }
> +            break;
> +        case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
> +            if (rs == 0 && rt != 0) {
> +                /* OPC_BLEZC */
> +                tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t1, 0);
> +            } else if (rs != 0 && rt != 0 && rs == rt) {
> +                /* OPC_BGEZC */
> +                tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t1, 0);
> +            } else {
> +                /* OPC_BGEC */
> +                tcg_gen_setcond_tl(TCG_COND_GE, bcond, t0, t1);
> +            }
> +            break;
> +        case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
> +            if (rs == 0 && rt != 0) {
> +                /* OPC_BGTZC */
> +                tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t1, 0);
> +            } else if (rs != 0 && rt != 0 && rs == rt) {
> +                /* OPC_BLTZC */
> +                tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t1, 0);
> +            } else {
> +                /* OPC_BLTC */
> +                tcg_gen_setcond_tl(TCG_COND_LT, bcond, t0, t1);
> +            }
> +            break;
> +        case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
> +        case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
> +            if (rs >= rt) {
> +                /* OPC_BOVC, OPC_BNVC */
> +                TCGv t2 = tcg_temp_new();
> +                TCGv t3 = tcg_temp_new();
> +                TCGv t4 = tcg_temp_new();
> +                TCGv input_overflow = tcg_temp_new();
> +
> +                gen_load_gpr(t0, rs);
> +                gen_load_gpr(t1, rt);
> +                tcg_gen_ext32s_tl(t2, t0);
> +                tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
> +                tcg_gen_ext32s_tl(t3, t1);
> +                tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
> +                tcg_gen_or_tl(input_overflow, input_overflow, t4);
> +
> +                tcg_gen_add_tl(t4, t2, t3);
> +                tcg_gen_ext32s_tl(t4, t4);
> +                tcg_gen_xor_tl(t2, t2, t3);
> +                tcg_gen_xor_tl(t3, t4, t3);
> +                tcg_gen_andc_tl(t2, t3, t2);
> +                tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
> +                if (opc == OPC_BOVC) {
> +                    /* OPC_BOVC */
> +                    tcg_gen_or_tl(bcond, t4, input_overflow);
> +                } else {
> +                    /* OPC_BNVC */
> +                    tcg_gen_or_tl(t4, t4, input_overflow);
> +                    tcg_gen_xori_tl(bcond, t4, 1);
> +                }
> +                tcg_temp_free(input_overflow);
> +                tcg_temp_free(t4);
> +                tcg_temp_free(t3);
> +                tcg_temp_free(t2);
> +            } else if (rs < rt && rs == 0) {
> +                /* OPC_BEQZALC, OPC_BNEZALC */
> +                if (opc == OPC_BEQZALC) {
> +                    /* OPC_BEQZALC */
> +                    tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, t1, 0);
> +                } else {
> +                    /* OPC_BNEZALC */
> +                    tcg_gen_setcondi_tl(TCG_COND_NE, bcond, t1, 0);
> +                }
> +            } else {
> +                /* OPC_BEQC, OPC_BNEC */
> +                if (opc == OPC_BEQC) {
> +                    /* OPC_BEQC */
> +                    tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
> +                } else {
> +                    /* OPC_BNEC */
> +                    tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
> +                }
> +            }
> +            break;
> +        case OPC_BEQZC:
> +            tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, t0, 0);
> +            break;
> +        case OPC_BNEZC:
> +            tcg_gen_setcondi_tl(TCG_COND_NE, bcond, t0, 0);
> +            break;
> +        default:
> +            MIPS_INVAL("conditional branch/jump");
> +            generate_exception(ctx, EXCP_RI);
> +            goto out;
> +        }
> +    }
> +    MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
> +                   blink, ctx->hflags, btgt);
> +
> +    ctx->btarget = btgt;
> +    if (blink > 0) {
> +        tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + 4);
> +    }
> +
> +    /* Compact branches don't have delay slot, thus generating branch here */
> +    /* TODO: implement forbidden slot */
> +    gen_branch(ctx, 4);
> +
> +out:
> +    tcg_temp_free(t0);
> +    tcg_temp_free(t1);
> +}
> +
>  static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
>  {
>      int rs, rt, rd, sa;
> @@ -16011,7 +16345,16 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
>              break;
>          }
>          break;
> -    case OPC_ADDI: /* Arithmetic with immediate opcode */
> +    case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        } else {
> +            /* OPC_ADDI */
> +            /* Arithmetic with immediate opcode */
> +            gen_arith_imm(ctx, op, rt, rs, imm);
> +        }
> +        break;
>      case OPC_ADDIU:
>           gen_arith_imm(ctx, op, rt, rs, imm);
>           break;
> @@ -16029,9 +16372,58 @@ 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_BEQL ... OPC_BGTZL:  /* Branch */
> +    /* Branch */
> +    case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            if (rt == 0) {
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        } else {
> +            /* OPC_BLEZL */
> +            gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
> +        }
> +        break;
> +    case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            if (rt == 0) {
> +                generate_exception(ctx, EXCP_RI);
> +                break;
> +            }
> +            /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        } else {
> +            /* OPC_BGTZL */
> +            gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
> +        }
> +        break;
> +    case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
> +        if (rt == 0) {
> +            /* OPC_BLEZ */
> +            gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
> +        } else {
> +            check_insn(ctx, ISA_MIPS32R6);
> +            /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        }
> +        break;
> +    case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
> +        if (rt == 0) {
> +            /* OPC_BGTZ */
> +            gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
> +        } else {
> +            check_insn(ctx, ISA_MIPS32R6);
> +            /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        }
> +        break;
> +    case OPC_BEQL:
> +    case OPC_BNEL:
>           check_insn_opc_removed(ctx, ISA_MIPS32R6);
> -    case OPC_BEQ ... OPC_BGTZ:
> +    case OPC_BEQ:
> +    case OPC_BNE:
>           gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
>           break;
>      case OPC_LWL: /* Load and stores */
> @@ -16094,7 +16486,24 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
>                  gen_cp1(ctx, op1, rt, rd);
>                  break;
>  #endif
> -            case OPC_BC1ANY2:
> +            case OPC_BC1EQZ: /* OPC_BC1ANY2 */
> +                if (ctx->insn_flags & ISA_MIPS32R6) {
> +                    /* OPC_BC1EQZ */
> +                    gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
> +                                    rt, imm << 2);
> +                } else {
> +                    /* OPC_BC1ANY2 */
> +                    check_cop1x(ctx);
> +                    check_insn(ctx, ASE_MIPS3D);
> +                    gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
> +                                    (rt >> 2) & 0x7, imm << 2);
> +                }
> +                break;
> +            case OPC_BC1NEZ:
> +                check_insn(ctx, ISA_MIPS32R6);
> +                gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
> +                                rt, imm << 2);
> +                break;
>              case OPC_BC1ANY4:
>                  check_insn_opc_removed(ctx, ISA_MIPS32R6);
>                  check_cop1x(ctx);
> @@ -16124,13 +16533,35 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
>          }
>          break;
>  
> -    /* COP2.  */
> -    case OPC_LWC2:
> -    case OPC_LDC2:
> -    case OPC_SWC2:
> -    case OPC_SDC2:
> -        /* COP2: Not implemented. */
> -        generate_exception_err(ctx, EXCP_CpU, 2);
> +    /* Compact branches [R6] and COP2 [non-R6] */
> +    case OPC_BC: /* OPC_LWC2 */
> +    case OPC_BALC: /* OPC_SWC2 */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            /* OPC_BC, OPC_BALC */
> +            gen_compute_compact_branch(ctx, op, 0, 0,
> +                                   SIMM((ctx->opcode & 0x3FFFFFF) << 2, 0, 28));
> +        } else {
> +            /* OPC_LWC2, OPC_SWC2 */
> +            /* COP2: Not implemented. */
> +            generate_exception_err(ctx, EXCP_CpU, 2);
> +        }
> +        break;
> +    case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
> +    case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            if (rs != 0) {
> +                /* OPC_BEQZC, OPC_BNEZC */
> +                gen_compute_compact_branch(ctx, op, rs, 0,
> +                                   SIMM((ctx->opcode & 0x1FFFFF) << 2, 0, 23));
> +            } else {
> +                /* OPC_JIC, OPC_JIALC */
> +                gen_compute_compact_branch(ctx, op, 0, rt, imm);
> +            }
> +        } else {
> +            /* OPC_LWC2, OPC_SWC2 */
> +            /* COP2: Not implemented. */
> +            generate_exception_err(ctx, EXCP_CpU, 2);
> +        }
>          break;
>      case OPC_CP2:
>          check_insn(ctx, INSN_LOONGSON2F);
> @@ -16204,12 +16635,31 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
>          check_mips_64(ctx);
>          gen_st_cond(ctx, op, rt, rs, imm);
>          break;
> -    case OPC_DADDI:
> +    case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        } else {
> +            /* OPC_DADDI */
> +            check_insn(ctx, ISA_MIPS3);
> +            check_mips_64(ctx);
> +            gen_arith_imm(ctx, op, rt, rs, imm);
> +        }
> +        break;
>      case OPC_DADDIU:
>          check_insn(ctx, ISA_MIPS3);
>          check_mips_64(ctx);
>          gen_arith_imm(ctx, op, rt, rs, imm);
>          break;
> +#else
> +    case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
> +        if (ctx->insn_flags & ISA_MIPS32R6) {
> +            gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
> +        } else {
> +            MIPS_INVAL("major opcode");
> +            generate_exception(ctx, EXCP_RI);
> +        }
> +        break;
>  #endif
>      case OPC_JALX:
>          check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
> @@ -16314,8 +16764,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
>              ctx.bstate = BS_STOP;
>              break;
>          }
> +
>          if (is_delay) {
> -            handle_delay_slot(&ctx, insn_bytes);
> +            gen_branch(&ctx, insn_bytes);
>          }
>          ctx.pc += insn_bytes;
>  
> -- 
> 1.7.5.4
> 
> 

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                 http://www.aurel32.net

  parent reply	other threads:[~2014-06-19 21:06 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-11 15:19 [Qemu-devel] [PATCH v2 00/22] target-mips: add MIPS64R6 Instruction Set support Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 01/22] target-mips: define ISA_MIPS64R6 Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 02/22] target-mips: signal RI Exception on instructions removed in R6 Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 03/22] target-mips: add SELEQZ and SELNEZ instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 04/22] target-mips: move LL and SC instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 05/22] target-mips: extract decode_opc_special* from decode_opc Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 06/22] target-mips: split decode_opc_special* into *_r6 and *_legacy Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 07/22] target-mips: signal RI Exception on DSP and Loongson instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 08/22] target-mips: move PREF, CACHE, LLD and SCD instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 09/22] target-mips: redefine Integer Multiply and Divide instructions Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 10/22] target-mips: move CLO, DCLO, CLZ, DCLZ, SDBBP and free special2 in R6 Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 11/22] target-mips: Status.UX/SX/KX enable 32-bit address wrapping Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 12/22] target-mips: add ALIGN, DALIGN, BITSWAP and DBITSWAP instructions Leon Alrae
2014-06-11 16:39   ` Richard Henderson
2014-06-12  8:35     ` Leon Alrae
2014-06-12 14:34       ` Richard Henderson
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 13/22] target-mips: add Compact Branches Leon Alrae
2014-06-11 16:52   ` Richard Henderson
2014-06-24 14:03     ` Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno [this message]
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 14/22] target-mips: add Addressing and PC-relative instructions Leon Alrae
2014-06-20 20:50   ` Aurelien Jarno
2014-06-24  9:50     ` Leon Alrae
2014-06-24 10:00       ` Peter Maydell
2014-06-24 14:24         ` Richard Henderson
2014-06-24 14:54           ` Peter Maydell
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 15/22] softfloat: add functions corresponding to IEEE-2008 min/maxNumMag Leon Alrae
2014-06-19 21:27   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 16/22] target-mips: add new Floating Point instructions Leon Alrae
2014-06-20 21:14   ` Aurelien Jarno
2014-06-24 12:10     ` Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 17/22] target-mips: add new Floating Point Comparison instructions Leon Alrae
2014-06-20 21:36   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 18/22] target-mips: do not allow Status.FR=0 mode in 64-bit FPU Leon Alrae
2014-06-19 21:27   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 19/22] target-mips: remove JR, BLTZAL, BGEZAL and add NAL, BAL instructions Leon Alrae
2014-06-19 22:22   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 20/22] mips_malta: update malta's pseudo-bootloader - replace JR with JALR Leon Alrae
2014-06-19 21:27   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 21/22] target-mips: use pointers referring to appropriate decoding function Leon Alrae
2014-06-19 22:18   ` Aurelien Jarno
2014-06-20  4:09     ` Richard Henderson
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 22/22] target-mips: define a new generic CPU supporting MIPS64R6 Leon Alrae
2014-06-19 22:16   ` Aurelien Jarno
2014-06-24 11:56     ` Leon Alrae

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140619210646.GA14196@ohm.rr44.fr \
    --to=aurelien@aurel32.net \
    --cc=cristian.cuna@imgtec.com \
    --cc=leon.alrae@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=yongbok.kim@imgtec.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.