qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v2 09/20] target-mips: add MSA branch instructio


From: James Hogan
Subject: Re: [Qemu-devel] [PATCH v2 09/20] target-mips: add MSA branch instructions
Date: Wed, 29 Oct 2014 11:19:41 +0000
User-agent: Mutt/1.5.22 (2013-10-16)

On Wed, Oct 29, 2014 at 01:41:57AM +0000, Yongbok Kim wrote:
> add MSA branch instructions
> 
> Signed-off-by: Yongbok Kim <address@hidden>

Reviewed-by: James Hogan <address@hidden>

Cheers
James

> ---
>  target-mips/translate.c |  333 
> +++++++++++++++++++++++++++++++----------------
>  1 files changed, 219 insertions(+), 114 deletions(-)
> 
> diff --git a/target-mips/translate.c b/target-mips/translate.c
> index f1160aa..0df86cc 100644
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -17247,6 +17247,92 @@ static inline int check_msa_access(CPUMIPSState 
> *env, DisasContext *ctx)
>      return 1;
>  }
>  
> +static void gen_check_zero_element(TCGv tresult, uint8_t df, uint8_t wt)
> +{
> +    /* generates tcg ops to check if any element is 0 */
> +    /* Note this function only works with MSA_WRLEN = 128 */
> +    uint64_t eval_zero_or_big = 0;
> +    uint64_t eval_big = 0;
> +    TCGv_i64 t0 = tcg_temp_new_i64();
> +    TCGv_i64 t1 = tcg_temp_new_i64();
> +    switch (df) {
> +    case DF_BYTE:
> +        eval_zero_or_big = 0x0101010101010101ULL;
> +        eval_big = 0x8080808080808080ULL;
> +        break;
> +    case DF_HALF:
> +        eval_zero_or_big = 0x0001000100010001ULL;
> +        eval_big = 0x8000800080008000ULL;
> +        break;
> +    case DF_WORD:
> +        eval_zero_or_big = 0x0000000100000001ULL;
> +        eval_big = 0x8000000080000000ULL;
> +        break;
> +    case DF_DOUBLE:
> +        eval_zero_or_big = 0x0000000000000001ULL;
> +        eval_big = 0x8000000000000000ULL;
> +        break;
> +    }
> +    tcg_gen_subi_i64(t0, msa_wr_d[wt<<1], eval_zero_or_big);
> +    tcg_gen_andc_i64(t0, t0, msa_wr_d[wt<<1]);
> +    tcg_gen_andi_i64(t0, t0, eval_big);
> +    tcg_gen_subi_i64(t1, msa_wr_d[(wt<<1)+1], eval_zero_or_big);
> +    tcg_gen_andc_i64(t1, t1, msa_wr_d[(wt<<1)+1]);
> +    tcg_gen_andi_i64(t1, t1, eval_big);
> +    tcg_gen_or_i64(t0, t0, t1);
> +    /* if all bits are zero then all elements are not zero */
> +    /* if some bit is non-zero then some element is zero */
> +    tcg_gen_setcondi_i64(TCG_COND_NE, t0, t0, 0);
> +    tcg_gen_trunc_i64_tl(tresult, t0);
> +    tcg_temp_free_i64(t0);
> +    tcg_temp_free_i64(t1);
> +}
> +
> +static void gen_msa_branch(CPUMIPSState *env, DisasContext *ctx, uint32_t 
> op1)
> +{
> +    uint8_t df = (ctx->opcode >> 21) & 0x3;
> +    uint8_t wt = (ctx->opcode >> 16) & 0x1f;
> +    int64_t s16 = (int16_t)ctx->opcode;
> +
> +    check_msa_access(env, ctx);
> +
> +    if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) {
> +        MIPS_DEBUG("CTI in delay / forbidden slot");
> +        generate_exception(ctx, EXCP_RI);
> +        return;
> +    }
> +    switch (op1) {
> +    case OPC_BZ_V:
> +    case OPC_BNZ_V:
> +        {
> +            TCGv_i64 t0 = tcg_temp_new_i64();
> +            tcg_gen_or_i64(t0, msa_wr_d[wt<<1], msa_wr_d[(wt<<1)+1]);
> +            tcg_gen_setcondi_i64((op1 == OPC_BZ_V) ?
> +                    TCG_COND_EQ : TCG_COND_NE, t0, t0, 0);
> +            tcg_gen_trunc_i64_tl(bcond, t0);
> +            tcg_temp_free_i64(t0);
> +        }
> +        break;
> +    case OPC_BZ_B:
> +    case OPC_BZ_H:
> +    case OPC_BZ_W:
> +    case OPC_BZ_D:
> +        gen_check_zero_element(bcond, df, wt);
> +        break;
> +    case OPC_BNZ_B:
> +    case OPC_BNZ_H:
> +    case OPC_BNZ_W:
> +    case OPC_BNZ_D:
> +        gen_check_zero_element(bcond, df, wt);
> +        tcg_gen_setcondi_tl(TCG_COND_EQ, bcond, bcond, 0);
> +        break;
> +    }
> +
> +    ctx->btarget = ctx->pc + (s16 << 2) + 4;
> +
> +    ctx->hflags |= MIPS_HFLAG_BC;
> +    ctx->hflags |= MIPS_HFLAG_BDS32;
> +}
>  static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
>  {
>      int32_t offset;
> @@ -17568,133 +17654,152 @@ static void decode_opc (CPUMIPSState *env, 
> DisasContext *ctx)
>          break;
>  
>      case OPC_CP1:
> -        if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
> +        op1 = MASK_CP1(ctx->opcode);
> +
> +        switch (op1) {
> +        case OPC_MFHC1:
> +        case OPC_MTHC1:
>              check_cp1_enabled(ctx);
> -            op1 = MASK_CP1(ctx->opcode);
> -            switch (op1) {
> -            case OPC_MFHC1:
> -            case OPC_MTHC1:
> -                check_insn(ctx, ISA_MIPS32R2);
> -            case OPC_MFC1:
> -            case OPC_CFC1:
> -            case OPC_MTC1:
> -            case OPC_CTC1:
> -                gen_cp1(ctx, op1, rt, rd);
> -                break;
> +            check_insn(ctx, ISA_MIPS32R2);
> +        case OPC_MFC1:
> +        case OPC_CFC1:
> +        case OPC_MTC1:
> +        case OPC_CTC1:
> +            check_cp1_enabled(ctx);
> +            gen_cp1(ctx, op1, rt, rd);
> +            break;
>  #if defined(TARGET_MIPS64)
> -            case OPC_DMFC1:
> -            case OPC_DMTC1:
> -                check_insn(ctx, ISA_MIPS3);
> -                gen_cp1(ctx, op1, rt, rd);
> -                break;
> +        case OPC_DMFC1:
> +        case OPC_DMTC1:
> +            check_cp1_enabled(ctx);
> +            check_insn(ctx, ISA_MIPS3);
> +            gen_cp1(ctx, op1, rt, rd);
> +            break;
>  #endif
> -            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);
> +        case OPC_BC1EQZ: /* OPC_BC1ANY2 */
> +            check_cp1_enabled(ctx);
> +            if (ctx->insn_flags & ISA_MIPS32R6) {
> +                /* OPC_BC1EQZ */
>                  gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
>                                  rt, imm << 2);
> -                break;
> -            case OPC_BC1ANY4:
> -                check_insn_opc_removed(ctx, ISA_MIPS32R6);
> +            } else {
> +                /* OPC_BC1ANY2 */
>                  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:
> -                gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
> -                           (imm >> 8) & 0x7);
> -                break;
> -            case OPC_W_FMT:
> -            case OPC_L_FMT:
> -            {
> -                int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
> -                if (ctx->insn_flags & ISA_MIPS32R6) {
> -                    switch (r6_op) {
> -                    case R6_OPC_CMP_AF_S:
> -                    case R6_OPC_CMP_UN_S:
> -                    case R6_OPC_CMP_EQ_S:
> -                    case R6_OPC_CMP_UEQ_S:
> -                    case R6_OPC_CMP_LT_S:
> -                    case R6_OPC_CMP_ULT_S:
> -                    case R6_OPC_CMP_LE_S:
> -                    case R6_OPC_CMP_ULE_S:
> -                    case R6_OPC_CMP_SAF_S:
> -                    case R6_OPC_CMP_SUN_S:
> -                    case R6_OPC_CMP_SEQ_S:
> -                    case R6_OPC_CMP_SEUQ_S:
> -                    case R6_OPC_CMP_SLT_S:
> -                    case R6_OPC_CMP_SULT_S:
> -                    case R6_OPC_CMP_SLE_S:
> -                    case R6_OPC_CMP_SULE_S:
> -                    case R6_OPC_CMP_OR_S:
> -                    case R6_OPC_CMP_UNE_S:
> -                    case R6_OPC_CMP_NE_S:
> -                    case R6_OPC_CMP_SOR_S:
> -                    case R6_OPC_CMP_SUNE_S:
> -                    case R6_OPC_CMP_SNE_S:
> -                        gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
> -                        break;
> -                    case R6_OPC_CMP_AF_D:
> -                    case R6_OPC_CMP_UN_D:
> -                    case R6_OPC_CMP_EQ_D:
> -                    case R6_OPC_CMP_UEQ_D:
> -                    case R6_OPC_CMP_LT_D:
> -                    case R6_OPC_CMP_ULT_D:
> -                    case R6_OPC_CMP_LE_D:
> -                    case R6_OPC_CMP_ULE_D:
> -                    case R6_OPC_CMP_SAF_D:
> -                    case R6_OPC_CMP_SUN_D:
> -                    case R6_OPC_CMP_SEQ_D:
> -                    case R6_OPC_CMP_SEUQ_D:
> -                    case R6_OPC_CMP_SLT_D:
> -                    case R6_OPC_CMP_SULT_D:
> -                    case R6_OPC_CMP_SLE_D:
> -                    case R6_OPC_CMP_SULE_D:
> -                    case R6_OPC_CMP_OR_D:
> -                    case R6_OPC_CMP_UNE_D:
> -                    case R6_OPC_CMP_NE_D:
> -                    case R6_OPC_CMP_SOR_D:
> -                    case R6_OPC_CMP_SUNE_D:
> -                    case R6_OPC_CMP_SNE_D:
> -                        gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
> -                        break;
> -                    default:
> -                        gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, 
> rd, sa,
> -                                                       (imm >> 8) & 0x7);
> -                        break;
> -                    }
> -                } else {
> +            }
> +            break;
> +        case OPC_BC1NEZ:
> +            check_cp1_enabled(ctx);
> +            check_insn(ctx, ISA_MIPS32R6);
> +            gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
> +                            rt, imm << 2);
> +            break;
> +        case OPC_BC1ANY4:
> +            check_cp1_enabled(ctx);
> +            check_insn_opc_removed(ctx, ISA_MIPS32R6);
> +            check_cop1x(ctx);
> +            check_insn(ctx, ASE_MIPS3D);
> +            /* fall through */
> +        case OPC_BC1:
> +            check_cp1_enabled(ctx);
> +            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_cp1_enabled(ctx);
> +            check_insn_opc_removed(ctx, ISA_MIPS32R6);
> +        case OPC_S_FMT:
> +        case OPC_D_FMT:
> +            check_cp1_enabled(ctx);
> +            gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
> +                       (imm >> 8) & 0x7);
> +            break;
> +        case OPC_W_FMT:
> +        case OPC_L_FMT:
> +        {
> +            int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
> +            check_cp1_enabled(ctx);
> +            if (ctx->insn_flags & ISA_MIPS32R6) {
> +                switch (r6_op) {
> +                case R6_OPC_CMP_AF_S:
> +                case R6_OPC_CMP_UN_S:
> +                case R6_OPC_CMP_EQ_S:
> +                case R6_OPC_CMP_UEQ_S:
> +                case R6_OPC_CMP_LT_S:
> +                case R6_OPC_CMP_ULT_S:
> +                case R6_OPC_CMP_LE_S:
> +                case R6_OPC_CMP_ULE_S:
> +                case R6_OPC_CMP_SAF_S:
> +                case R6_OPC_CMP_SUN_S:
> +                case R6_OPC_CMP_SEQ_S:
> +                case R6_OPC_CMP_SEUQ_S:
> +                case R6_OPC_CMP_SLT_S:
> +                case R6_OPC_CMP_SULT_S:
> +                case R6_OPC_CMP_SLE_S:
> +                case R6_OPC_CMP_SULE_S:
> +                case R6_OPC_CMP_OR_S:
> +                case R6_OPC_CMP_UNE_S:
> +                case R6_OPC_CMP_NE_S:
> +                case R6_OPC_CMP_SOR_S:
> +                case R6_OPC_CMP_SUNE_S:
> +                case R6_OPC_CMP_SNE_S:
> +                    gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
> +                    break;
> +                case R6_OPC_CMP_AF_D:
> +                case R6_OPC_CMP_UN_D:
> +                case R6_OPC_CMP_EQ_D:
> +                case R6_OPC_CMP_UEQ_D:
> +                case R6_OPC_CMP_LT_D:
> +                case R6_OPC_CMP_ULT_D:
> +                case R6_OPC_CMP_LE_D:
> +                case R6_OPC_CMP_ULE_D:
> +                case R6_OPC_CMP_SAF_D:
> +                case R6_OPC_CMP_SUN_D:
> +                case R6_OPC_CMP_SEQ_D:
> +                case R6_OPC_CMP_SEUQ_D:
> +                case R6_OPC_CMP_SLT_D:
> +                case R6_OPC_CMP_SULT_D:
> +                case R6_OPC_CMP_SLE_D:
> +                case R6_OPC_CMP_SULE_D:
> +                case R6_OPC_CMP_OR_D:
> +                case R6_OPC_CMP_UNE_D:
> +                case R6_OPC_CMP_NE_D:
> +                case R6_OPC_CMP_SOR_D:
> +                case R6_OPC_CMP_SUNE_D:
> +                case R6_OPC_CMP_SNE_D:
> +                    gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
> +                    break;
> +                default:
>                      gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, 
> sa,
>                                 (imm >> 8) & 0x7);
> +                    break;
>                  }
> -                break;
> -            }
> -            default:
> -                MIPS_INVAL("cp1");
> -                generate_exception (ctx, EXCP_RI);
> -                break;
> +            } else {
> +                gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
> +                           (imm >> 8) & 0x7);
>              }
> -        } else {
> -            generate_exception_err(ctx, EXCP_CpU, 1);
> +            break;
> +        }
> +        case OPC_BZ_V:
> +        case OPC_BNZ_V:
> +        case OPC_BZ_B:
> +        case OPC_BZ_H:
> +        case OPC_BZ_W:
> +        case OPC_BZ_D:
> +        case OPC_BNZ_B:
> +        case OPC_BNZ_H:
> +        case OPC_BNZ_W:
> +        case OPC_BNZ_D:
> +            check_insn(ctx, ASE_MSA);
> +            gen_msa_branch(env, ctx, op1);
> +            break;
> +        default:
> +            MIPS_INVAL("cp1");
> +            generate_exception(ctx, EXCP_RI);
> +            break;
>          }
>          break;
>  
> -- 
> 1.7.4
> 
> 



reply via email to

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