Patchwork [01/13] alpha: Implement missing MVI instructions.

login
register
mail settings
Submitter Richard Henderson
Date Dec. 10, 2009, 8:04 p.m.
Message ID <dcbd0b481da9de83a82f86e6117438688b09e1ba.1260580414.git.rth@twiddle.net>
Download mbox | patch
Permalink /patch/40935/
State New
Headers show

Comments

Richard Henderson - Dec. 10, 2009, 8:04 p.m.
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-alpha/helper.h    |   14 ++++
 target-alpha/op_helper.c |  168 ++++++++++++++++++++++++++++++++++++++++++++++
 target-alpha/translate.c |   79 +++++++++++++--------
 3 files changed, 231 insertions(+), 30 deletions(-)

Patch

diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 9c60be1..850ba0d 100644
--- a/target-alpha/helper.h
+++ b/target-alpha/helper.h
@@ -36,6 +36,20 @@  DEF_HELPER_2(insqh, i64, i64, i64)
 
 DEF_HELPER_2(cmpbge, i64, i64, i64)
 
+DEF_HELPER_2(minub8, i64, i64, i64)
+DEF_HELPER_2(minsb8, i64, i64, i64)
+DEF_HELPER_2(minuw4, i64, i64, i64)
+DEF_HELPER_2(minsw4, i64, i64, i64)
+DEF_HELPER_2(maxub8, i64, i64, i64)
+DEF_HELPER_2(maxsb8, i64, i64, i64)
+DEF_HELPER_2(maxuw4, i64, i64, i64)
+DEF_HELPER_2(maxsw4, i64, i64, i64)
+DEF_HELPER_2(perr, i64, i64, i64)
+DEF_HELPER_1(pklb, i64, i64)
+DEF_HELPER_1(pkwb, i64, i64)
+DEF_HELPER_1(unpkbl, i64, i64)
+DEF_HELPER_1(unpkbw, i64, i64)
+
 DEF_HELPER_0(load_fpcr, i64)
 DEF_HELPER_1(store_fpcr, void, i64)
 
diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c
index 999a8ab..08d5924 100644
--- a/target-alpha/op_helper.c
+++ b/target-alpha/op_helper.c
@@ -277,6 +277,174 @@  uint64_t helper_cmpbge (uint64_t op1, uint64_t op2)
     return res;
 }
 
+uint64_t helper_minub8 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_minsb8 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int8_t opa, opb;
+    uint8_t opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_minuw4 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint16_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_minsw4 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int16_t opa, opb;
+    uint16_t opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa < opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_maxub8 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int8_t opa, opb;
+    uint8_t opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 8);
+    }
+    return res;
+}
+
+uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint16_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    int16_t opa, opb;
+    uint16_t opr;
+    int i;
+
+    for (i = 0; i < 4; ++i) {
+        opa = op1 >> (i * 16);
+        opb = op2 >> (i * 16);
+        opr = opa > opb ? opa : opb;
+        res |= (uint64_t)opr << (i * 16);
+    }
+    return res;
+}
+
+uint64_t helper_perr (uint64_t op1, uint64_t op2)
+{
+    uint64_t res = 0;
+    uint8_t opa, opb, opr;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        opa = op1 >> (i * 8);
+        opb = op2 >> (i * 8);
+        if (opa >= opb)
+            opr = opa - opb;
+        else
+            opr = opb - opa;
+        res += opr;
+    }
+    return res;
+}
+
+uint64_t helper_pklb (uint64_t op1)
+{
+    return (op1 & 0xff) | ((op1 >> 24) & 0xff00);
+}
+
+uint64_t helper_pkwb (uint64_t op1)
+{
+    return ((op1 & 0xff)
+            | ((op1 >> 8) & 0xff00)
+            | ((op1 >> 16) & 0xff0000)
+            | ((op1 >> 24) & 0xff000000));
+}
+
+uint64_t helper_unpkbl (uint64_t op1)
+{
+    return (op1 & 0xff) | ((op1 & 0xff00) << 24);
+}
+
+uint64_t helper_unpkbw (uint64_t op1)
+{
+    return ((op1 & 0xff)
+            | ((op1 & 0xff00) << 8)
+            | ((op1 & 0xff0000) << 16)
+            | ((op1 & 0xff000000) << 24));
+}
+
 /* Floating point helpers */
 
 /* F floating (VAX) */
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 3f8d1b2..851eb50 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -611,6 +611,30 @@  ARITH3(insqh)
 ARITH3(umulh)
 ARITH3(mullv)
 ARITH3(mulqv)
+ARITH3(minub8)
+ARITH3(minsb8)
+ARITH3(minuw4)
+ARITH3(minsw4)
+ARITH3(maxub8)
+ARITH3(maxsb8)
+ARITH3(maxuw4)
+ARITH3(maxsw4)
+ARITH3(perr)
+
+#define MVIOP2(name)                                    \
+static inline void glue(gen_, name)(int rb, int rc)     \
+{                                                       \
+    if (unlikely(rc == 31))                             \
+        return;                                         \
+    if (unlikely(rb == 31))                             \
+        tcg_gen_movi_i64(cpu_ir[rc], 0);                \
+    else                                                \
+        gen_helper_ ## name (cpu_ir[rc], cpu_ir[rb]);   \
+}
+MVIOP2(pklb)
+MVIOP2(pkwb)
+MVIOP2(unpkbl)
+MVIOP2(unpkbw)
 
 static inline void gen_cmp(TCGCond cond, int ra, int rb, int rc, int islit,
                            uint8_t lit)
@@ -619,7 +643,7 @@  static inline void gen_cmp(TCGCond cond, int ra, int rb, int rc, int islit,
     TCGv tmp;
 
     if (unlikely(rc == 31))
-    return;
+        return;
 
     l1 = gen_new_label();
     l2 = gen_new_label();
@@ -646,7 +670,7 @@  static inline int translate_one(DisasContext *ctx, uint32_t insn)
     uint32_t palcode;
     int32_t disp21, disp16, disp12;
     uint16_t fn11, fn16;
-    uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit;
+    uint8_t opc, ra, rb, rc, sbz, fpfn, fn7, fn2, islit, real_islit;
     uint8_t lit;
     int ret;
 
@@ -656,7 +680,7 @@  static inline int translate_one(DisasContext *ctx, uint32_t insn)
     rb = (insn >> 16) & 0x1F;
     rc = insn & 0x1F;
     sbz = (insn >> 13) & 0x07;
-    islit = (insn >> 12) & 1;
+    real_islit = islit = (insn >> 12) & 1;
     if (rb == 31 && !islit) {
         islit = 1;
         lit = 0;
@@ -1913,8 +1937,7 @@  static inline int translate_one(DisasContext *ctx, uint32_t insn)
             /* PERR */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_perr(ra, rb, rc, islit, lit);
             break;
         case 0x32:
             /* CTLZ */
@@ -1942,85 +1965,81 @@  static inline int translate_one(DisasContext *ctx, uint32_t insn)
             /* UNPKBW */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            if (real_islit || ra != 31)
+                goto invalid_opc;
+            gen_unpkbw (rb, rc);
             break;
         case 0x35:
-            /* UNPKWL */
+            /* UNPKBL */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            if (real_islit || ra != 31)
+                goto invalid_opc;
+            gen_unpkbl (rb, rc);
             break;
         case 0x36:
             /* PKWB */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            if (real_islit || ra != 31)
+                goto invalid_opc;
+            gen_pkwb (rb, rc);
             break;
         case 0x37:
             /* PKLB */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            if (real_islit || ra != 31)
+                goto invalid_opc;
+            gen_pklb (rb, rc);
             break;
         case 0x38:
             /* MINSB8 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_minsb8 (ra, rb, rc, islit, lit);
             break;
         case 0x39:
             /* MINSW4 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_minsw4 (ra, rb, rc, islit, lit);
             break;
         case 0x3A:
             /* MINUB8 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_minub8 (ra, rb, rc, islit, lit);
             break;
         case 0x3B:
             /* MINUW4 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_minuw4 (ra, rb, rc, islit, lit);
             break;
         case 0x3C:
             /* MAXUB8 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_maxub8 (ra, rb, rc, islit, lit);
             break;
         case 0x3D:
             /* MAXUW4 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_maxuw4 (ra, rb, rc, islit, lit);
             break;
         case 0x3E:
             /* MAXSB8 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_maxsb8 (ra, rb, rc, islit, lit);
             break;
         case 0x3F:
             /* MAXSW4 */
             if (!(ctx->amask & AMASK_MVI))
                 goto invalid_opc;
-            /* XXX: TODO */
-            goto invalid_opc;
+            gen_maxsw4 (ra, rb, rc, islit, lit);
             break;
         case 0x70:
             /* FTOIT */