target-mips: Add ASE DSP accumulator instructions

Add MIPS ASE DSP Accumulator and DSPControl Access instructions.

Signed-off-by: Jia Liu <proljc@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Jia Liu 2012-10-24 22:17:11 +08:00 committed by Aurelien Jarno
parent 2669056024
commit b53371ed5d
3 changed files with 995 additions and 0 deletions

View file

@ -352,6 +352,11 @@ enum {
OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
#if defined(TARGET_MIPS64)
OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
#endif
/* MIPS DSP Accumulator and DSPControl Access Sub-class */
OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
#if defined(TARGET_MIPS64)
OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
#endif
};
@ -564,6 +569,30 @@ enum {
OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
};
#define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Accumulator and DSPControl Access Sub-class */
OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
};
#if defined(TARGET_MIPS64)
#define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
@ -676,6 +705,32 @@ enum {
#endif
#if defined(TARGET_MIPS64)
#define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* MIPS DSP Accumulator and DSPControl Access Sub-class */
OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
};
#define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
enum {
/* DSP Bit/Manipulation Sub-class */
@ -14077,6 +14132,236 @@ static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
MIPS_DEBUG("%s", opn);
}
static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
int ret, int v1, int v2, int check_ret)
{
const char *opn = "mipsdsp accumulator";
TCGv t0;
TCGv t1;
TCGv v1_t;
TCGv v2_t;
int16_t imm;
if ((ret == 0) && (check_ret == 1)) {
/* Treat as NOP. */
MIPS_DEBUG("NOP");
return;
}
t0 = tcg_temp_new();
t1 = tcg_temp_new();
v1_t = tcg_temp_new();
v2_t = tcg_temp_new();
gen_load_gpr(v1_t, v1);
gen_load_gpr(v2_t, v2);
switch (op1) {
case OPC_EXTR_W_DSP:
check_dsp(ctx);
switch (op2) {
case OPC_EXTR_W:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_EXTR_R_W:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_EXTR_RS_W:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_EXTR_S_H:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_EXTRV_S_H:
tcg_gen_movi_tl(t0, v2);
gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_EXTRV_W:
tcg_gen_movi_tl(t0, v2);
gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_EXTRV_R_W:
tcg_gen_movi_tl(t0, v2);
gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_EXTRV_RS_W:
tcg_gen_movi_tl(t0, v2);
gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_EXTP:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_EXTPV:
tcg_gen_movi_tl(t0, v2);
gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_EXTPDP:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_EXTPDPV:
tcg_gen_movi_tl(t0, v2);
gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_SHILO:
imm = (ctx->opcode >> 20) & 0x3F;
tcg_gen_movi_tl(t0, ret);
tcg_gen_movi_tl(t1, imm);
gen_helper_shilo(t0, t1, cpu_env);
break;
case OPC_SHILOV:
tcg_gen_movi_tl(t0, ret);
gen_helper_shilo(t0, v1_t, cpu_env);
break;
case OPC_MTHLIP:
tcg_gen_movi_tl(t0, ret);
gen_helper_mthlip(t0, v1_t, cpu_env);
break;
case OPC_WRDSP:
imm = (ctx->opcode >> 11) & 0x3FF;
tcg_gen_movi_tl(t0, imm);
gen_helper_wrdsp(v1_t, t0, cpu_env);
break;
case OPC_RDDSP:
imm = (ctx->opcode >> 16) & 0x03FF;
tcg_gen_movi_tl(t0, imm);
gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
break;
}
break;
#ifdef TARGET_MIPS64
case OPC_DEXTR_W_DSP:
check_dsp(ctx);
switch (op2) {
case OPC_DMTHLIP:
tcg_gen_movi_tl(t0, ret);
gen_helper_dmthlip(v1_t, t0, cpu_env);
break;
case OPC_DSHILO:
{
int shift = (ctx->opcode >> 19) & 0x7F;
int ac = (ctx->opcode >> 11) & 0x03;
tcg_gen_movi_tl(t0, shift);
tcg_gen_movi_tl(t1, ac);
gen_helper_dshilo(t0, t1, cpu_env);
break;
}
case OPC_DSHILOV:
{
int ac = (ctx->opcode >> 11) & 0x03;
tcg_gen_movi_tl(t0, ac);
gen_helper_dshilo(v1_t, t0, cpu_env);
break;
}
case OPC_DEXTP:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTPV:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTPDP:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTPDPV:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTR_L:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTR_R_L:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTR_RS_L:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTR_W:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTR_R_W:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTR_RS_W:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTR_S_H:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTRV_S_H:
tcg_gen_movi_tl(t0, v2);
tcg_gen_movi_tl(t1, v1);
gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
break;
case OPC_DEXTRV_L:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTRV_R_L:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTRV_RS_L:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTRV_W:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTRV_R_W:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
case OPC_DEXTRV_RS_W:
tcg_gen_movi_tl(t0, v2);
gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
break;
}
break;
#endif
}
tcg_temp_free(t0);
tcg_temp_free(t1);
tcg_temp_free(v1_t);
tcg_temp_free(v2_t);
(void)opn; /* avoid a compiler warning */
MIPS_DEBUG("%s", opn);
}
/* End MIPSDSP functions. */
static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
@ -14665,6 +14950,38 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
op2 = MASK_APPEND(ctx->opcode);
gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
break;
case OPC_EXTR_W_DSP:
op2 = MASK_EXTR_W(ctx->opcode);
switch (op2) {
case OPC_EXTR_W:
case OPC_EXTR_R_W:
case OPC_EXTR_RS_W:
case OPC_EXTR_S_H:
case OPC_EXTRV_S_H:
case OPC_EXTRV_W:
case OPC_EXTRV_R_W:
case OPC_EXTRV_RS_W:
case OPC_EXTP:
case OPC_EXTPV:
case OPC_EXTPDP:
case OPC_EXTPDPV:
gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
break;
case OPC_RDDSP:
gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
break;
case OPC_SHILO:
case OPC_SHILOV:
case OPC_MTHLIP:
case OPC_WRDSP:
gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
break;
default: /* Invalid */
MIPS_INVAL("MASK EXTR.W");
generate_exception(ctx, EXCP_RI);
break;
}
break;
#if defined(TARGET_MIPS64)
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
@ -14809,6 +15126,40 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
op2 = MASK_DAPPEND(ctx->opcode);
gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rt, rs, rd, 1);
break;
case OPC_DEXTR_W_DSP:
op2 = MASK_DEXTR_W(ctx->opcode);
switch (op2) {
case OPC_DEXTP:
case OPC_DEXTPDP:
case OPC_DEXTPDPV:
case OPC_DEXTPV:
case OPC_DEXTR_L:
case OPC_DEXTR_R_L:
case OPC_DEXTR_RS_L:
case OPC_DEXTR_W:
case OPC_DEXTR_R_W:
case OPC_DEXTR_RS_W:
case OPC_DEXTR_S_H:
case OPC_DEXTRV_L:
case OPC_DEXTRV_R_L:
case OPC_DEXTRV_RS_L:
case OPC_DEXTRV_S_H:
case OPC_DEXTRV_W:
case OPC_DEXTRV_R_W:
case OPC_DEXTRV_RS_W:
gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
break;
case OPC_DMTHLIP:
case OPC_DSHILO:
case OPC_DSHILOV:
gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
break;
default: /* Invalid */
MIPS_INVAL("MASK EXTR.W");
generate_exception(ctx, EXCP_RI);
break;
}
break;
case OPC_DPAQ_W_QH_DSP:
op2 = MASK_DPAQ_W_QH(ctx->opcode);
switch (op2) {