summaryrefslogtreecommitdiffstats
path: root/target/mips/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/mips/translate.c')
-rw-r--r--target/mips/translate.c213
1 files changed, 189 insertions, 24 deletions
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 2caf4cba5a..9fad58ea2c 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -1046,7 +1046,7 @@ enum {
OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
};
-#define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
+#define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
enum {
OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
@@ -3421,7 +3421,8 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
TCGv t0, t1, t2;
int mem_idx = ctx->mem_idx;
- if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
+ if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
+ INSN_LOONGSON3A)) {
/*
* Loongson CPU uses a load to zero register for prefetch.
* We emulate it as a NOP. On other CPU we must perform the
@@ -5531,7 +5532,7 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
TCGv_i64 t0, t1;
TCGCond cond;
- opc = MASK_LMI(ctx->opcode);
+ opc = MASK_LMMI(ctx->opcode);
switch (opc) {
case OPC_ADD_CP2:
case OPC_SUB_CP2:
@@ -27161,7 +27162,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_MULTU_G_2F:
case OPC_MOD_G_2F:
case OPC_MODU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F);
+ check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
case OPC_CLO:
@@ -27194,7 +27195,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
case OPC_DDIVU_G_2F:
case OPC_DMOD_G_2F:
case OPC_DMODU_G_2F:
- check_insn(ctx, INSN_LOONGSON2F);
+ check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
#endif
@@ -29057,6 +29058,38 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
break;
}
break;
+ case OPC_MADDV_df:
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_maddv_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_maddv_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_maddv_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_maddv_d(cpu_env, twd, tws, twt);
+ break;
+ }
+ break;
+ case OPC_MSUBV_df:
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_msubv_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_msubv_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_msubv_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_msubv_d(cpu_env, twd, tws, twt);
+ break;
+ }
+ break;
case OPC_ASUB_S_df:
switch (df) {
case DF_BYTE:
@@ -29266,10 +29299,36 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
}
break;
case OPC_SUBS_S_df:
- gen_helper_msa_subs_s_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_subs_s_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_subs_s_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_subs_s_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_subs_s_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_MULV_df:
- gen_helper_msa_mulv_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_mulv_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_mulv_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_mulv_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_mulv_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_SLD_df:
gen_helper_msa_sld_df(cpu_env, tdf, twd, tws, twt);
@@ -29278,25 +29337,71 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
gen_helper_msa_vshf_df(cpu_env, tdf, twd, tws, twt);
break;
case OPC_SUBV_df:
- gen_helper_msa_subv_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_subv_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_subv_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_subv_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_subv_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_SUBS_U_df:
- gen_helper_msa_subs_u_df(cpu_env, tdf, twd, tws, twt);
- break;
- case OPC_MADDV_df:
- gen_helper_msa_maddv_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_subs_u_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_subs_u_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_subs_u_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_subs_u_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_SPLAT_df:
gen_helper_msa_splat_df(cpu_env, tdf, twd, tws, twt);
break;
case OPC_SUBSUS_U_df:
- gen_helper_msa_subsus_u_df(cpu_env, tdf, twd, tws, twt);
- break;
- case OPC_MSUBV_df:
- gen_helper_msa_msubv_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_subsus_u_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_subsus_u_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_subsus_u_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_subsus_u_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_SUBSUU_S_df:
- gen_helper_msa_subsuu_s_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_BYTE:
+ gen_helper_msa_subsuu_s_b(cpu_env, twd, tws, twt);
+ break;
+ case DF_HALF:
+ gen_helper_msa_subsuu_s_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_subsuu_s_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_subsuu_s_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_DOTP_S_df:
@@ -29367,22 +29472,82 @@ static void gen_msa_3r(CPUMIPSState *env, DisasContext *ctx)
}
break;
case OPC_DOTP_S_df:
- gen_helper_msa_dotp_s_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_HALF:
+ gen_helper_msa_dotp_s_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_dotp_s_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_dotp_s_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_DOTP_U_df:
- gen_helper_msa_dotp_u_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_HALF:
+ gen_helper_msa_dotp_u_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_dotp_u_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_dotp_u_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_DPADD_S_df:
- gen_helper_msa_dpadd_s_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_HALF:
+ gen_helper_msa_dpadd_s_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_dpadd_s_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_dpadd_s_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_DPADD_U_df:
- gen_helper_msa_dpadd_u_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_HALF:
+ gen_helper_msa_dpadd_u_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_dpadd_u_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_dpadd_u_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_DPSUB_S_df:
- gen_helper_msa_dpsub_s_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_HALF:
+ gen_helper_msa_dpsub_s_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_dpsub_s_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_dpsub_s_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
case OPC_DPSUB_U_df:
- gen_helper_msa_dpsub_u_df(cpu_env, tdf, twd, tws, twt);
+ switch (df) {
+ case DF_HALF:
+ gen_helper_msa_dpsub_u_h(cpu_env, twd, tws, twt);
+ break;
+ case DF_WORD:
+ gen_helper_msa_dpsub_u_w(cpu_env, twd, tws, twt);
+ break;
+ case DF_DOUBLE:
+ gen_helper_msa_dpsub_u_d(cpu_env, twd, tws, twt);
+ break;
+ }
break;
}
break;
@@ -30641,7 +30806,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
}
break;
case OPC_CP2:
- check_insn(ctx, INSN_LOONGSON2F);
+ check_insn(ctx, ASE_LMMI);
/* Note that these instructions use different fields. */
gen_loongson_multimedia(ctx, sa, rd, rt);
break;