aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2009-12-10 12:04:42 -0800
committerAurelien Jarno <aurelien@aurel32.net>2009-12-13 21:26:26 +0100
commit13e4df99ce5a2fde4b8ac9a21c3d98db4c629b7c (patch)
tree632ba4d631f685975d035b375ee77af6c9694db7
parent91a759352623e4a3da969fa66626cc99241e9da2 (diff)
target-alpha: Implement missing MVI instructions.
Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--target-alpha/helper.h14
-rw-r--r--target-alpha/op_helper.c168
-rw-r--r--target-alpha/translate.c79
3 files changed, 231 insertions, 30 deletions
diff --git a/target-alpha/helper.h b/target-alpha/helper.h
index 9c60be1ea2..850ba0d3fc 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 999a8ab46c..08d5924b3b 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 3f8d1b2d19..851eb50609 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 */