summaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2013-01-01 18:02:24 +0100
committerAurelien Jarno <aurelien@aurel32.net>2013-01-31 23:30:19 +0100
commitdf6126a7f21a1a032e41b15899ca29777399d5a2 (patch)
treea92c5737b5ad5da198fe3b216cdca1c8052d05eb /target-mips
parent0a16c79cc4087838ae5f2bc9554d91db2cbb2503 (diff)
downloadqemu-df6126a7f21a1a032e41b15899ca29777399d5a2.tar.gz
qemu-df6126a7f21a1a032e41b15899ca29777399d5a2.tar.bz2
qemu-df6126a7f21a1a032e41b15899ca29777399d5a2.zip
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>
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/dsp_helper.c67
-rw-r--r--target-mips/helper.h13
-rw-r--r--target-mips/translate.c133
3 files changed, 87 insertions, 126 deletions
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index f5de2ca8e5..96cb0447e2 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -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;
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 9ea60ec1bb..cd48738ff9 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -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)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 99f3492de2..8722638678 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -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);