target-mips: implement DSP (d)append sub-class with TCG
DSP instruction from the (d)append sub-class can be implemented with TCG. Use a different function for these instructions are they are quite different from compare-pick sub-class. Fix BALIGN instruction for negative value, where the value should be zero-extended before being shift to the right. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
		
							parent
							
								
									0a16c79cc4
								
							
						
					
					
						commit
						df6126a7f2
					
				| 
						 | 
				
			
			@ -3111,73 +3111,6 @@ PICK_INSN(pick_pw, 2, MIPSDSP_LLO, 32, 0);
 | 
			
		|||
#endif
 | 
			
		||||
#undef PICK_INSN
 | 
			
		||||
 | 
			
		||||
#define APPEND_INSN(name, ret_32) \
 | 
			
		||||
target_ulong helper_##name(target_ulong rt, target_ulong rs, uint32_t sa) \
 | 
			
		||||
{                                                                         \
 | 
			
		||||
    target_ulong temp;                                                    \
 | 
			
		||||
                                                                          \
 | 
			
		||||
    if (ret_32) {                                                         \
 | 
			
		||||
        temp = ((rt & MIPSDSP_LLO) << sa) |                               \
 | 
			
		||||
               ((rs & MIPSDSP_LLO) & ((0x01 << sa) - 1));                 \
 | 
			
		||||
        temp = (target_long)(int32_t)(temp & MIPSDSP_LLO);                \
 | 
			
		||||
    } else {                                                              \
 | 
			
		||||
        temp = (rt << sa) | (rs & ((0x01 << sa) - 1));                    \
 | 
			
		||||
    }                                                                     \
 | 
			
		||||
                                                                          \
 | 
			
		||||
    return temp;                                                          \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
APPEND_INSN(append, 1);
 | 
			
		||||
#ifdef TARGET_MIPS64
 | 
			
		||||
APPEND_INSN(dappend, 0);
 | 
			
		||||
#endif
 | 
			
		||||
#undef APPEND_INSN
 | 
			
		||||
 | 
			
		||||
#define PREPEND_INSN(name, or_val, ret_32)                    \
 | 
			
		||||
target_ulong helper_##name(target_ulong rs, target_ulong rt,  \
 | 
			
		||||
                           uint32_t sa)                       \
 | 
			
		||||
{                                                             \
 | 
			
		||||
    sa |= or_val;                                             \
 | 
			
		||||
                                                              \
 | 
			
		||||
    if (1) {                                                  \
 | 
			
		||||
        return (target_long)(int32_t)(uint32_t)               \
 | 
			
		||||
            (((rs & MIPSDSP_LLO) << (32 - sa)) |              \
 | 
			
		||||
             ((rt & MIPSDSP_LLO) >> sa));                     \
 | 
			
		||||
    } else {                                                  \
 | 
			
		||||
        return (rs << (64 - sa)) | (rt >> sa);                \
 | 
			
		||||
    }                                                         \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PREPEND_INSN(prepend, 0, 1);
 | 
			
		||||
#ifdef TARGET_MIPS64
 | 
			
		||||
PREPEND_INSN(prependw, 0, 0);
 | 
			
		||||
PREPEND_INSN(prependd, 0x20, 0);
 | 
			
		||||
#endif
 | 
			
		||||
#undef PREPEND_INSN
 | 
			
		||||
 | 
			
		||||
#define BALIGN_INSN(name, filter, ret32) \
 | 
			
		||||
target_ulong helper_##name(target_ulong rs, target_ulong rt, uint32_t bp) \
 | 
			
		||||
{                                                                         \
 | 
			
		||||
    bp = bp & 0x03;                                                       \
 | 
			
		||||
                                                                          \
 | 
			
		||||
    if ((bp & 1) == 0) {                                                  \
 | 
			
		||||
        return rt;                                                        \
 | 
			
		||||
    } else {                                                              \
 | 
			
		||||
        if (ret32) {                                                      \
 | 
			
		||||
            return (target_long)(int32_t)((rt << (8 * bp)) |              \
 | 
			
		||||
                                          (rs >> (8 * (4 - bp))));        \
 | 
			
		||||
        } else {                                                          \
 | 
			
		||||
            return (rt << (8 * bp)) | (rs >> (8 * (8 - bp)));             \
 | 
			
		||||
        }                                                                 \
 | 
			
		||||
    }                                                                     \
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BALIGN_INSN(balign, 0x03, 1);
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
BALIGN_INSN(dbalign, 0x07, 0);
 | 
			
		||||
#endif
 | 
			
		||||
#undef BALIGN_INSN
 | 
			
		||||
 | 
			
		||||
target_ulong helper_packrl_ph(target_ulong rs, target_ulong rt)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t rsl, rth;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -654,19 +654,6 @@ DEF_HELPER_FLAGS_3(pick_ob, 0, tl, tl, tl, env)
 | 
			
		|||
DEF_HELPER_FLAGS_3(pick_qh, 0, tl, tl, tl, env)
 | 
			
		||||
DEF_HELPER_FLAGS_3(pick_pw, 0, tl, tl, tl, env)
 | 
			
		||||
#endif
 | 
			
		||||
DEF_HELPER_FLAGS_3(append, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
DEF_HELPER_FLAGS_3(dappend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
#endif
 | 
			
		||||
DEF_HELPER_FLAGS_3(prepend, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
DEF_HELPER_FLAGS_3(prependd, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
DEF_HELPER_FLAGS_3(prependw, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
#endif
 | 
			
		||||
DEF_HELPER_FLAGS_3(balign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
DEF_HELPER_FLAGS_3(dbalign, TCG_CALL_NO_RWG_SE, tl, tl, tl, i32)
 | 
			
		||||
#endif
 | 
			
		||||
DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 | 
			
		||||
#if defined(TARGET_MIPS64)
 | 
			
		||||
DEF_HELPER_FLAGS_2(packrl_pw, TCG_CALL_NO_RWG_SE, tl, tl, tl)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -336,7 +336,7 @@ enum {
 | 
			
		|||
    /* DSP Bit/Manipulation Sub-class */
 | 
			
		||||
    OPC_INSV_DSP       = 0x0C | OPC_SPECIAL3,
 | 
			
		||||
    OPC_DINSV_DSP      = 0x0D | OPC_SPECIAL3,
 | 
			
		||||
    /* MIPS DSP Compare-Pick Sub-class */
 | 
			
		||||
    /* MIPS DSP Append Sub-class */
 | 
			
		||||
    OPC_APPEND_DSP     = 0x31 | OPC_SPECIAL3,
 | 
			
		||||
    OPC_DAPPEND_DSP    = 0x35 | OPC_SPECIAL3,
 | 
			
		||||
    /* MIPS DSP Accumulator and DSPControl Access Sub-class */
 | 
			
		||||
| 
						 | 
				
			
			@ -543,7 +543,7 @@ enum {
 | 
			
		|||
 | 
			
		||||
#define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 | 
			
		||||
enum {
 | 
			
		||||
    /* MIPS DSP Compare-Pick Sub-class */
 | 
			
		||||
    /* MIPS DSP Append Sub-class */
 | 
			
		||||
    OPC_APPEND  = (0x00 << 6) | OPC_APPEND_DSP,
 | 
			
		||||
    OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
 | 
			
		||||
    OPC_BALIGN  = (0x10 << 6) | OPC_APPEND_DSP,
 | 
			
		||||
| 
						 | 
				
			
			@ -667,7 +667,7 @@ enum {
 | 
			
		|||
 | 
			
		||||
#define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
 | 
			
		||||
enum {
 | 
			
		||||
    /* DSP Compare-Pick Sub-class */
 | 
			
		||||
    /* DSP Append Sub-class */
 | 
			
		||||
    OPC_DAPPEND  = (0x00 << 6) | OPC_DAPPEND_DSP,
 | 
			
		||||
    OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
 | 
			
		||||
    OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
 | 
			
		||||
| 
						 | 
				
			
			@ -13868,7 +13868,6 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
 | 
			
		|||
                                     int ret, int v1, int v2, int check_ret)
 | 
			
		||||
{
 | 
			
		||||
    const char *opn = "mipsdsp add compare pick";
 | 
			
		||||
    TCGv_i32 t0;
 | 
			
		||||
    TCGv t1;
 | 
			
		||||
    TCGv v1_t;
 | 
			
		||||
    TCGv v2_t;
 | 
			
		||||
| 
						 | 
				
			
			@ -13879,7 +13878,6 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
 | 
			
		|||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    t0 = tcg_temp_new_i32();
 | 
			
		||||
    t1 = tcg_temp_new();
 | 
			
		||||
    v1_t = tcg_temp_new();
 | 
			
		||||
    v2_t = tcg_temp_new();
 | 
			
		||||
| 
						 | 
				
			
			@ -13888,26 +13886,6 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
 | 
			
		|||
    gen_load_gpr(v2_t, v2);
 | 
			
		||||
 | 
			
		||||
    switch (op1) {
 | 
			
		||||
    case OPC_APPEND_DSP:
 | 
			
		||||
        switch (op2) {
 | 
			
		||||
        case OPC_APPEND:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_append(cpu_gpr[ret], cpu_gpr[ret], v1_t, t0);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_PREPEND:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_prepend(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_BALIGN:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_balign(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
 | 
			
		||||
            break;
 | 
			
		||||
        default:            /* Invid */
 | 
			
		||||
            MIPS_INVAL("MASK APPEND");
 | 
			
		||||
            generate_exception(ctx, EXCP_RI);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    case OPC_CMPU_EQ_QB_DSP:
 | 
			
		||||
        switch (op2) {
 | 
			
		||||
        case OPC_CMPU_EQ_QB:
 | 
			
		||||
| 
						 | 
				
			
			@ -14065,23 +14043,95 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
 | 
			
		|||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tcg_temp_free(t1);
 | 
			
		||||
    tcg_temp_free(v1_t);
 | 
			
		||||
    tcg_temp_free(v2_t);
 | 
			
		||||
 | 
			
		||||
    (void)opn; /* avoid a compiler warning */
 | 
			
		||||
    MIPS_DEBUG("%s", opn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
 | 
			
		||||
                               uint32_t op1, int rt, int rs, int sa)
 | 
			
		||||
{
 | 
			
		||||
    const char *opn = "mipsdsp append/dappend";
 | 
			
		||||
    TCGv t0;
 | 
			
		||||
 | 
			
		||||
    check_dspr2(ctx);
 | 
			
		||||
 | 
			
		||||
    if (rt == 0) {
 | 
			
		||||
        /* Treat as NOP. */
 | 
			
		||||
        MIPS_DEBUG("NOP");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    t0 = tcg_temp_new();
 | 
			
		||||
    gen_load_gpr(t0, rs);
 | 
			
		||||
 | 
			
		||||
    switch (op1) {
 | 
			
		||||
    case OPC_APPEND_DSP:
 | 
			
		||||
        switch (MASK_APPEND(ctx->opcode)) {
 | 
			
		||||
        case OPC_APPEND:
 | 
			
		||||
            if (sa != 0) {
 | 
			
		||||
                tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
 | 
			
		||||
            }
 | 
			
		||||
            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_PREPEND:
 | 
			
		||||
            if (sa != 0) {
 | 
			
		||||
                tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
 | 
			
		||||
                tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
 | 
			
		||||
                tcg_gen_shli_tl(t0, t0, 32 - sa);
 | 
			
		||||
                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
 | 
			
		||||
            }
 | 
			
		||||
            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_BALIGN:
 | 
			
		||||
            sa &= 3;
 | 
			
		||||
            if (sa != 0 && sa != 2) {
 | 
			
		||||
                tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
 | 
			
		||||
                tcg_gen_ext32u_tl(t0, t0);
 | 
			
		||||
                tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
 | 
			
		||||
                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
 | 
			
		||||
            }
 | 
			
		||||
            tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
 | 
			
		||||
            break;
 | 
			
		||||
        default:            /* Invalid */
 | 
			
		||||
            MIPS_INVAL("MASK APPEND");
 | 
			
		||||
            generate_exception(ctx, EXCP_RI);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
#ifdef TARGET_MIPS64
 | 
			
		||||
    case OPC_DAPPEND_DSP:
 | 
			
		||||
        switch (op2) {
 | 
			
		||||
        switch (MASK_DAPPEND(ctx->opcode)) {
 | 
			
		||||
        case OPC_DAPPEND:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_dappend(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
 | 
			
		||||
            if (sa != 0) {
 | 
			
		||||
                tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_PREPENDD:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_prependd(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
 | 
			
		||||
            tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
 | 
			
		||||
            tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
 | 
			
		||||
            tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_PREPENDW:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_prependw(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
 | 
			
		||||
            if (sa != 0) {
 | 
			
		||||
                tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
 | 
			
		||||
                tcg_gen_shli_tl(t0, t0, 64 - sa);
 | 
			
		||||
                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_DBALIGN:
 | 
			
		||||
            tcg_gen_movi_i32(t0, v2);
 | 
			
		||||
            gen_helper_dbalign(cpu_gpr[ret], v1_t, cpu_gpr[ret], t0);
 | 
			
		||||
            sa &= 7;
 | 
			
		||||
            if (sa != 0 && sa != 2 && sa != 4) {
 | 
			
		||||
                tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
 | 
			
		||||
                tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
 | 
			
		||||
                tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        default:            /* Invalid */
 | 
			
		||||
            MIPS_INVAL("MASK DAPPEND");
 | 
			
		||||
| 
						 | 
				
			
			@ -14091,12 +14141,7 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
 | 
			
		|||
        break;
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    tcg_temp_free_i32(t0);
 | 
			
		||||
    tcg_temp_free(t1);
 | 
			
		||||
    tcg_temp_free(v1_t);
 | 
			
		||||
    tcg_temp_free(v2_t);
 | 
			
		||||
 | 
			
		||||
    tcg_temp_free(t0);
 | 
			
		||||
    (void)opn; /* avoid a compiler warning */
 | 
			
		||||
    MIPS_DEBUG("%s", opn);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -14915,9 +14960,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 | 
			
		|||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_APPEND_DSP:
 | 
			
		||||
            check_dspr2(ctx);
 | 
			
		||||
            op2 = MASK_APPEND(ctx->opcode);
 | 
			
		||||
            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
 | 
			
		||||
            gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_EXTR_W_DSP:
 | 
			
		||||
            op2 = MASK_EXTR_W(ctx->opcode);
 | 
			
		||||
| 
						 | 
				
			
			@ -15091,9 +15134,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
 | 
			
		|||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_DAPPEND_DSP:
 | 
			
		||||
            check_dspr2(ctx);
 | 
			
		||||
            op2 = MASK_DAPPEND(ctx->opcode);
 | 
			
		||||
            gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
 | 
			
		||||
            gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
 | 
			
		||||
            break;
 | 
			
		||||
        case OPC_DEXTR_W_DSP:
 | 
			
		||||
            op2 = MASK_DEXTR_W(ctx->opcode);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue