[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 2/4] add MIPS DSP helpers implement
From: |
Jia Liu |
Subject: |
[Qemu-devel] [PATCH 2/4] add MIPS DSP helpers implement |
Date: |
Mon, 12 Mar 2012 16:32:37 +0800 |
This patch is the helper implementation of MIPS ASE DSP.
Signed-off-by: Jia Liu <address@hidden>
---
target-mips/op_helper.c | 3936 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 3936 insertions(+), 0 deletions(-)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 87e9799..e6ff3c9 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -3409,3 +3409,3939 @@ FOP_COND_PS(le, float32_le(fst0, fst1,
&env->active_fpu.fp_status),
float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
FOP_COND_PS(ngt, float32_unordered(fst1, fst0, &env->active_fpu.fp_status)
|| float32_le(fst0, fst1, &env->active_fpu.fp_status),
float32_unordered(fsth1, fsth0, &env->active_fpu.fp_status)
|| float32_le(fsth0, fsth1, &env->active_fpu.fp_status))
+
+/* MIPS DSP functions begin */
+static inline void set_DSPControl_overflow_flag (uint32_t flag, int position)
+{
+ env->active_tc.DSPControl |= (target_ulong)flag << position;
+}
+
+static inline void set_DSPControl_carryflag (uint32_t flag)
+{
+ env->active_tc.DSPControl |= (target_ulong)flag << 13;
+}
+
+static inline uint32_t get_DSPControl_carryflag(void)
+{
+ uint32_t flag;
+
+ flag = (env->active_tc.DSPControl >> 13) & 0x01;
+
+ return flag;
+}
+
+static inline void set_DSPControl_24(uint32_t flag, int len)
+{
+ if(len == 2)
+ env->active_tc.DSPControl &= 0xFCFFFFFF;
+ else if(len == 4)
+ env->active_tc.DSPControl &= 0xF0FFFFFF;
+
+ env->active_tc.DSPControl |= (target_ulong)flag << 24;
+}
+
+static inline void set_DSPControl_pos(uint32_t pos)
+{
+ target_ulong dspc;
+
+ dspc = env->active_tc.DSPControl;
+ dspc = dspc & 0xFFFFFFC0;
+ dspc |= pos;
+ env->active_tc.DSPControl = dspc;
+}
+
+static inline uint32_t get_DSPControl_pos(void)
+{
+ target_ulong dspc;
+ uint32_t pos;
+
+ dspc = env->active_tc.DSPControl;
+ pos = dspc & 0x3F;
+
+ return pos;
+}
+
+static inline void set_DSPControl_efi(uint32_t flag)
+{
+ env->active_tc.DSPControl &= 0xFFFFBFFF;
+ env->active_tc.DSPControl |= (target_ulong)flag << 14;
+}
+
+/* get abs value */
+static inline int8_t mipsdsp_sat_abs_u8 (uint8_t a)
+{
+ int8_t temp;
+ temp = a;
+
+ if (a == 0x80) {
+ set_DSPControl_overflow_flag(1, 20);
+ temp = 0x7f;
+ } else {
+ if (0x80 == (a & 0x80))
+ temp = -temp;
+ }
+
+ return temp;
+}
+
+static inline int16_t mipsdsp_sat_abs_u16 (uint16_t a)
+{
+ int16_t temp;
+ temp = a;
+
+ if (0x8000 == a) {
+ set_DSPControl_overflow_flag(1, 20);
+ temp = 0x7fff;
+ } else {
+ if (0x8000 == (a & 0x8000))
+ temp = -temp;
+ }
+
+ return temp;
+}
+
+static inline int32_t mipsdsp_sat_abs_u32 (uint32_t a)
+{
+ int32_t temp;
+ temp = a;
+
+ if (a == 0x80000000) {
+ set_DSPControl_overflow_flag(1, 20);
+ temp = 0x7FFFFFFF;
+ } else {
+ if((a & 0x80000000) == 0x80000000)
+ temp = -temp;
+ }
+
+ return temp;
+}
+
+/* get sum value */
+static inline int16_t mipsdsp_add_i16 (int16_t a, int16_t b)
+{
+ int16_t tempS;
+ int32_t tempI, temp15, temp16;
+
+ tempS = a + b;
+ tempI = a + b;
+ temp15 = (tempI & 0x8000 ) >> 15;
+ temp16 = (tempI & 0x10000) >> 16;
+
+ if (temp15 != temp16)
+ set_DSPControl_overflow_flag(1, 20);
+
+ return tempS;
+}
+
+static inline int16_t mipsdsp_sat_add_i16 (int16_t a, int16_t b)
+{
+ int16_t tempS;
+ int32_t tempI, temp15, temp16;
+
+ tempS = a + b;
+ tempI = (int32_t)a + (int32_t)b;
+ temp15 = (tempI & 0x8000 ) >> 15;
+ temp16 = (tempI & 0x10000) >> 16;
+
+ if (temp15 != temp16) {
+ if(0 == temp16)
+ tempS = 0x7FFF;
+ else
+ tempS = 0x8000;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+
+ return tempS;
+}
+
+static inline int32_t mipsdsp_sat_add_i32 (int32_t a, int32_t b)
+{
+ int32_t tempI;
+ int64_t tempL, temp31, temp32;
+
+ tempI = a + b;
+ tempL = (int64_t)a + (int64_t)b;
+ temp31 = (tempL & 0x80000000 ) >> 31;
+ temp32 = (tempL & 0x100000000) >> 32;
+
+ if (temp31 != temp32) {
+ if(0 == temp32)
+ tempI = 0x7FFFFFFF;
+ else
+ tempI = 0x80000000;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+
+ return tempI;
+}
+
+static inline uint8_t mipsdsp_add_u8(uint8_t a, uint8_t b)
+{
+ uint8_t result;
+ uint16_t tempA, tempB, temp;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = temp & 0xFF;
+
+ if( 0x0100 == (temp & 0x0100))
+ set_DSPControl_overflow_flag(1, 20);
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_add_u16(uint16_t a, uint16_t b)
+{
+ uint16_t result;
+ uint32_t tempA, tempB, temp;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = temp & 0xFFFF;
+
+ if( 0x00010000 == (temp & 0x00010000))
+ set_DSPControl_overflow_flag(1, 20);
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_sat_add_u8(uint8_t a, uint8_t b)
+{
+ uint8_t result;
+ uint16_t tempA, tempB, temp;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = temp & 0xFF;
+
+ if(0x0100 == (0x0100 & temp)) {
+ result = 0xFF;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_sat_add_u16(uint16_t a, uint16_t b)
+{
+ uint16_t result;
+ uint32_t tempA, tempB, temp;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = temp & 0xFFFF;
+
+ if(0x00010000 == (0x00010000 & temp)) {
+ result = 0xFFFF;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+
+ return result;
+}
+
+static inline int32_t mipsdsp_sat32_acc_q31(int32_t acc, int32_t a)
+{
+ int64_t tempA, temp;
+ int32_t temp32, temp31, result;
+
+ temp = ((int64_t)env->active_tc.HI[acc] << 32) | \
+ ((int64_t)env->active_tc.LO[acc] & 0x00000000FFFFFFFF);
+ tempA = a;
+ temp += tempA;
+ temp32 = (temp >> 32) & 0x01;
+ temp31 = (temp >> 31) & 0x01;
+ result = temp & 0xFFFFFFFF;
+
+ if(temp32 != temp31) {
+ if(0 == temp32)
+ result = 0x80000000;
+ else
+ result = 0x7FFFFFFF;
+ set_DSPControl_overflow_flag(1, 16 + acc);
+ }
+
+ return result;
+}
+
+static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b)
+{
+ int32_t temp, tempA, tempB;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA * tempB;
+
+ if((temp > 0x7FFF) || (temp < 0xFFFF8000))
+ set_DSPControl_overflow_flag(1, 21);
+
+ return (temp & 0x0000FFFF);
+}
+
+static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b)
+{
+ int32_t temp, tempA, tempB;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA * tempB;
+
+ if(temp > 0x7FFF) {
+ temp = 0x00007FFF;
+ set_DSPControl_overflow_flag(1, 21);
+ } else if(temp < 0x00007FFF) {
+ temp = 0xFFFF8000;
+ set_DSPControl_overflow_flag(1, 21);
+ }
+
+ return (temp & 0x0000FFFF);
+}
+
+static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(uint16_t a, uint16_t
b)
+{
+ int16_t tempA, tempB;
+ int32_t temp;
+
+ tempA = a;
+ tempB = b;
+
+ if((0x8000 == a) && (0x8000 == b)) {
+ temp = 0x7FFFFFFF;
+ set_DSPControl_overflow_flag(1, 21);
+ } else
+ temp = ((int32_t)tempA * (int32_t)tempB) << 1;
+
+ return temp;
+}
+
+/* right shift */
+static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
+{
+ int32_t temp, tempA, tempB;
+ int16_t result;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = (temp >> 1) & 0xFFFF;
+
+ return result;
+}
+
+/* round right shift */
+static inline int16_t mipsdsp_rrshift1_add_q16(int16_t a, int16_t b)
+{
+ int32_t temp, tempA, tempB;
+ int16_t result;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ temp += 1;
+ result = (temp >> 1) & 0xFFFF;
+
+ return result;
+}
+
+static inline int32_t mipsdsp_rshift1_add_q32(int32_t a, int32_t b)
+{
+ int64_t temp, tempA, tempB;
+ int32_t result;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = (temp >> 1) & 0xFFFFFFFF;
+
+ return result;
+}
+
+static inline int32_t mipsdsp_rrshift1_add_q32(int32_t a, int32_t b)
+{
+ int64_t temp, tempA, tempB;
+ int32_t result;
+ tempA = a;
+ tempB = b;
+
+ temp = tempA + tempB;
+ temp += 1;
+ result = (temp >> 1) & 0xFFFFFFFF;
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_rshift1_add_u8(uint8_t a, uint8_t b)
+{
+ uint16_t tempA, tempB, temp;
+ uint8_t result;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB;
+ result = (temp >> 1) & 0x00FF;
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_rrshift1_add_u8(uint8_t a, uint8_t b)
+{
+ uint16_t tempA, tempB, temp;
+ uint8_t result;
+
+ tempA = a;
+ tempB = b;
+ temp = tempA + tempB + 1;
+ result = (temp >> 1) & 0x00FF;
+
+ return result;
+}
+
+static inline int64_t mipsdsp_rashift_short_acc(int32_t ac,
+ int32_t shift)
+{
+ int32_t sign, temp31;
+ int64_t temp, acc;
+
+ sign = (env->active_tc.HI[ac] >> 31) & 0x01;
+ acc = ((int64_t)env->active_tc.HI[ac] << 32) | \
+ ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
+ if(0 == shift)
+ temp = acc;
+ else {
+ if(0 == sign)
+ temp = (((int64_t)0x01 << (32 - shift + 1)) - 1) & (acc >> shift);
+ else
+ temp = ((((int64_t)0x01 << (shift + 1)) - 1) << (32 - shift)) | \
+ (acc >> shift);
+ }
+
+ temp31 = (temp >> 31) & 0x01;
+ if(sign != temp31)
+ set_DSPControl_overflow_flag(1, 23);
+
+ return temp;
+}
+
+/* 128 bits long. p[0] is LO, p[1] is HI. */
+static inline void mipsdsp__rashift_short_acc(int64_t *p,
+ int32_t ac,
+ int32_t shift)
+{
+ int64_t acc;
+
+ acc = ((int64_t)env->active_tc.HI[ac] << 32) | \
+ ((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
+ if(0 == shift) {
+ p[0] = acc << 1;
+ p[1] = (acc >> 63) & 0x01;
+ } else {
+ p[0] = acc >> (shift - 1);
+ p[1] = 0;
+ }
+}
+
+static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b)
+{
+ uint16_t tempA, tempB;
+ int32_t temp;
+
+ tempA = a;
+ tempB = b;
+
+ if((0x8000 == a) && (0x8000 == b)) {
+ temp = 0x7FFFFFFF;
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ } else
+ temp = ((uint32_t)tempA * (uint32_t)tempB) << 1;
+
+ return temp;
+}
+
+static inline int64_t mipsdsp_mul_q31_q31(int32_t ac, uint32_t a, uint32_t b)
+{
+ uint32_t tempA, tempB;
+ uint64_t temp;
+
+ tempA = a;
+ tempB = b;
+
+ if((0x80000000 == a) && (0x80000000 == b)) {
+ temp = 0x7FFFFFFFFFFFFFFF;
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ } else
+ temp = ((uint64_t)tempA * (uint64_t)tempB) << 1;
+
+ return temp;
+}
+
+static inline uint16_t mipsdsp_mul_u8_u8(uint8_t a, uint8_t b)
+{
+ uint16_t temp;
+ temp = (uint16_t)a * (uint16_t)b;
+
+ return temp;
+}
+
+static inline uint16_t mipsdsp_mul_u8_u16(uint8_t a, uint16_t b)
+{
+ uint16_t tempS;
+ uint32_t tempI, tempA, tempB;
+
+ tempA = a;
+ tempB = b;
+ tempI = tempA * tempB;
+ if(tempI > 0x00) {
+ tempI = 0x0000FFFF;
+ set_DSPControl_overflow_flag(1, 21);
+ }
+ tempS = tempI & 0x0000FFFF;
+ return tempS;
+}
+
+static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b)
+{
+ int16_t result, tempA, tempB;
+ int32_t temp;
+
+ tempA = a;
+ tempB = b;
+
+ if((0x8000 == a) && (0x8000 == b)) {
+ temp = 0x7FFF0000;
+ set_DSPControl_overflow_flag(1, 21);
+ } else {
+ temp = ((int32_t)tempA * (int32_t)tempB) << 1;
+ temp = temp + 0x00008000;
+ }
+ result = (temp & 0xFFFF0000) >> 16;
+
+ return result;
+}
+
+static inline int32_t mipsdsp_sat16_mul_q15_q15(uint16_t a, uint16_t b)
+{
+ int16_t tempA, tempB;
+ int32_t temp;
+
+ tempA = a;
+ tempB = b;
+
+ if((0x8000 == a) && (0x8000 == b)) {
+ temp = 0x7FFF0000;
+ set_DSPControl_overflow_flag(1, 21);
+ } else {
+ temp = ((uint32_t)tempA * (uint32_t)tempB);
+ temp = temp << 1;
+ }
+ temp = (temp >> 16) & 0x0000FFFF;
+
+ return temp;
+}
+
+static inline uint16_t mipsdsp_trunc16_sat16_round(uint32_t a)
+{
+ uint16_t result;
+ uint32_t temp32, temp31;
+ int64_t temp;
+
+ temp = (int32_t)a + 0x00008000;
+ temp32 = (temp >> 32) & 0x01;
+ temp31 = (temp >> 31) & 0x01;
+
+ if(temp32 != temp31) {
+ temp = 0x7FFFFFFF;
+ set_DSPControl_overflow_flag(1, 22);
+ }
+ result = (temp >> 16) & 0xFFFF;
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a)
+{
+ uint8_t result;
+ uint16_t mag;
+ uint32_t sign;
+
+ sign = (a >> 15) & 0x01;
+ mag = a & 0x7FFF;
+
+ if(0 == sign) {
+ if(mag > 0x7F80) {
+ result = 0xFF;
+ set_DSPControl_overflow_flag(1, 22);
+ } else
+ result = (mag >> 7) & 0xFFFF;
+ } else {
+ result = 0x00;
+ set_DSPControl_overflow_flag(1, 22);
+ }
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s)
+{
+ uint8_t sign;
+ uint8_t temp, discard;
+
+ if(0 == s)
+ temp = a;
+ else {
+ sign = (a >> 7) & 0x01;
+ temp = a << s;
+ if(sign != 0)
+ discard = (((0x01 << (8 -s)) -1) << s) | \
+ ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
+ else
+ discard = a >> (6 - (s - 1));
+
+ if(discard != 0x00)
+ set_DSPControl_overflow_flag(1, 22);
+ }
+
+ return temp;
+}
+
+static inline uint8_t mipsdsp_rshift8(uint8_t a, uint8_t s)
+{
+ uint8_t temp;
+ if(0 == s)
+ temp = a;
+ else
+ temp = a >> s;
+ return temp;
+}
+
+static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s)
+{
+ uint8_t sign;
+ uint16_t temp, discard;
+
+ if(0 == s)
+ temp = a;
+ else {
+ sign = (a >> 15) & 0x01;
+ temp = a << s;
+ if(sign != 0)
+ discard = (((0x01 << (16 -s)) -1) << s) | \
+ ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
+ else
+ discard = a >> (14 - (s - 1));
+
+ if((discard != 0x0000) && (discard != 0xFFFF))
+ set_DSPControl_overflow_flag(1, 22);
+ }
+
+ return temp;
+}
+
+static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s)
+{
+ uint8_t sign;
+ uint16_t temp, discard;
+
+ if(0 == s)
+ temp = a;
+ else {
+ sign = (a >> 15) & 0x01;
+ temp = a << s;
+ if(sign != 0)
+ discard = (((0x01 << (16 -s)) -1) << s) | \
+ ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
+ else
+ discard = a >> (14 - (s - 1));
+ if((discard != 0x0000) && (discard != 0xFFFF)) {
+ temp = sign == 0 ? 0x7FFF : 0x8000;
+ set_DSPControl_overflow_flag(1, 22);
+ }
+ }
+
+ return temp;
+}
+
+static inline uint32_t mipsdsp_sat32_lshift(uint32_t a, uint8_t s)
+{
+ uint8_t sign;
+ uint32_t temp, discard;
+
+ if(0 == s)
+ temp = a;
+ else {
+ sign = (a >> 31) & 0x01;
+ temp = a << s;
+ if(sign != 0)
+ discard = (((0x01 << (32 -s)) -1) << s) | \
+ ((a >> (30 - (s - 1))) & ((0x01 << s) - 1));
+ else
+ discard = a >> (30 - (s - 1));
+ if((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
+ temp = sign == 0 ? 0x7FFFFFFF : 0x80000000;
+ set_DSPControl_overflow_flag(1, 22);
+ }
+ }
+
+ return temp;
+}
+
+static inline uint16_t mipsdsp_rashift16(uint16_t a, uint8_t s)
+{
+ int16_t i, temp;
+
+ i = a;
+ if(0 == s)
+ temp = a;
+ else
+ temp = i >> s;
+
+ return temp;
+}
+
+static inline uint16_t mipsdsp_rnd16_rashift(uint16_t a, uint8_t s)
+{
+ int16_t i, result;
+ uint32_t temp;
+
+ i = a;
+ if(0 == s)
+ temp = (uint32_t)a << 1;
+ else
+ temp = (int32_t)i >> (s - 1);
+ temp = temp + 1;
+ result = temp >> 1;
+
+ return result;
+}
+
+static inline uint32_t mipsdsp_rnd32_rashift(uint32_t a, uint8_t s)
+{
+ int32_t i;
+ int64_t temp;
+ uint32_t result;
+
+ i = a;
+ if(0 == s)
+ temp = a << 1;
+ else
+ temp = (int64_t)i >> (s - 1);
+ temp += 1;
+ result = (temp >> 1) & 0x00000000FFFFFFFF;
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_sub_i16(int16_t a, int16_t b)
+{
+ uint8_t temp16, temp15;
+ uint16_t result;
+ int32_t temp;
+
+ temp = (int32_t)a - (int32_t)b;
+ temp16 = (temp >> 16) & 0x01;
+ temp15 = (temp >> 15) & 0x01;
+ if(temp16 != temp15)
+ set_DSPControl_overflow_flag(1, 20);
+ result = temp & 0x0000FFFF;
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_sat16_sub(int16_t a, int16_t b)
+{
+ uint8_t temp16, temp15;
+ uint16_t result;
+ int32_t temp;
+
+ temp = (int32_t)a - (int32_t)b;
+ temp16 = (temp >> 16) & 0x01;
+ temp15 = (temp >> 15) & 0x01;
+ if(temp16 != temp15) {
+ if(0 == temp16)
+ temp = 0x7FFF;
+ else
+ temp = 0x8000;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+ result = temp & 0x0000FFFF;
+
+ return result;
+}
+
+static inline uint32_t mipsdsp_sat32_sub(int32_t a, int32_t b)
+{
+ uint8_t temp32, temp31;
+ uint32_t result;
+ int64_t temp;
+
+ temp = (int64_t)a - (int64_t)b;
+ temp32 = (temp >> 32) & 0x01;
+ temp31 = (temp >> 31) & 0x01;
+ if(temp32 != temp31) {
+ if(0 == temp32)
+ temp = 0x7FFFFFFF;
+ else
+ temp = 0x80000000;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+ result = temp & 0x00000000FFFFFFFF;
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_rshift1_sub_q16(int16_t a, int16_t b)
+{
+ int32_t temp;
+ uint16_t result;
+
+ temp = (int32_t)a - (int32_t)b;
+ result = (temp >> 1) & 0x0000FFFF;
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_rrshift1_sub_q16(int16_t a, int16_t b)
+{
+ int32_t temp;
+ uint16_t result;
+
+ temp = (int32_t)a - (int32_t)b;
+ temp += 1;
+ result = (temp >> 1) & 0x0000FFFF;
+
+ return result;
+}
+
+static inline uint32_t mipsdsp_rshift1_sub_q32(int32_t a, int32_t b)
+{
+ int64_t temp;
+ uint32_t result;
+
+ temp = (int64_t)a - (int64_t)b;
+ result = (temp >> 1) & 0x00000000FFFFFFFF;
+
+ return result;
+}
+
+static inline uint32_t mipsdsp_rrshift1_sub_q32(int32_t a, int32_t b)
+{
+ int64_t temp;
+ uint32_t result;
+
+ temp = (int64_t)a - (int64_t)b;
+ temp += 1;
+ result = (temp >> 1) & 0x00000000FFFFFFFF;
+
+ return result;
+}
+
+static inline uint16_t mipsdsp_sub_u16_u16(uint16_t a, uint16_t b)
+{
+ uint8_t temp16;
+ uint16_t result;
+ uint32_t temp;
+
+ temp = (uint32_t)a - (uint32_t)b;
+ temp16 = (temp >> 16) & 0x01;
+ if(1 == temp16)
+ set_DSPControl_overflow_flag(1, 20);
+ result = temp & 0x0000FFFF;
+ return result;
+}
+
+static inline uint16_t mipsdsp_satu16_sub_u16_u16(uint16_t a, uint16_t b)
+{
+ uint8_t temp16;
+ uint16_t result;
+ uint32_t temp;
+
+ temp = (uint32_t)a - (uint32_t)b;
+ temp16 = (temp >> 16) & 0x01;
+
+ if(temp16 == 1) {
+ temp = 0x0000;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+ result = temp & 0x0000FFFF;
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_sub_u8(uint8_t a, uint8_t b)
+{
+ uint8_t result, temp8;
+ uint16_t temp;
+
+ temp = (uint16_t)a - (uint16_t)b;
+ temp8 = (temp >> 8) & 0x01;
+ if(0 == temp8)
+ set_DSPControl_overflow_flag(1, 20);
+ result = temp & 0x00FF;
+
+ return result;
+}
+
+static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b)
+{
+ uint8_t result, temp8;
+ uint16_t temp;
+
+ temp = (uint16_t)a - (uint16_t)b;
+ temp8 = (temp >> 8) & 0x01;
+ if(1 == temp8) {
+ temp = 0x00;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+ result = temp & 0x00FF;
+
+ return result;
+}
+/* MIPS DSP functions end */
+
+#define MIPSDSP_LHI 0xFFFFFFFF00000000
+#define MIPSDSP_LLO 0x00000000FFFFFFFF
+#define MIPSDSP_HI 0xFFFF0000
+#define MIPSDSP_LO 0x0000FFFF
+#define MIPSDSP_Q3 0xFF000000
+#define MIPSDSP_Q2 0x00FF0000
+#define MIPSDSP_Q1 0x0000FF00
+#define MIPSDSP_Q0 0x000000FF
+
+/* MIPS DSP */
+uint32_t helper_absqsph (uint32_t rt)
+{
+ uint32_t rd;
+ int16_t tempA, tempB;
+
+ tempA = (rt & MIPSDSP_HI) >> 16;
+ tempB = rt & MIPSDSP_LO;
+
+ rd = ((uint32_t)mipsdsp_sat_abs_u16 (tempA) << 16) | \
+ ((uint32_t)(mipsdsp_sat_abs_u16 (tempB)) & 0xFFFF);
+
+ return rd;
+}
+
+uint32_t helper_absqsw (uint32_t rt)
+{
+ uint32_t rd;
+ int32_t temp;
+
+ temp = rt;
+ rd = mipsdsp_sat_abs_u32 (temp);
+
+ return rd;
+}
+
+uint32_t helper_addqph (uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl, temph, templ;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ temph = mipsdsp_add_i16(rsh, rth);
+ templ = mipsdsp_add_i16(rsl, rtl);
+ rd = ((unsigned int)temph << 16) | ((unsigned int)templ & 0xFFFF);
+
+ return rd;
+}
+
+uint32_t helper_addqsph (uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl, temph, templ;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ temph = mipsdsp_sat_add_i16(rsh, rth);
+ templ = mipsdsp_sat_add_i16(rsl, rtl);
+ rd = ((uint32_t)temph << 16) | ((uint32_t)templ & 0xFFFF);
+
+ return rd;
+}
+
+uint32_t helper_addqsw (uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ rd = mipsdsp_sat_add_i32(rs, rt);
+ return rd;
+}
+
+uint32_t helper_addsc (uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint64_t temp, tempRs, tempRt;
+ int32_t flag;
+
+ tempRs = (uint64_t)rs & MIPSDSP_LLO;
+ tempRt = (uint64_t)rt & MIPSDSP_LLO;
+
+ temp = tempRs + tempRt;
+ flag = (temp & 0x0100000000) >> 32;
+ set_DSPControl_carryflag(flag);
+ rd = temp & MIPSDSP_LLO;
+
+ return rd;
+}
+
+uint32_t helper_addwc (uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int32_t temp32, temp31;
+ int64_t rsL, rtL, tempL;
+
+ rsL = (int32_t)rs;
+ rtL = (int32_t)rt;
+ tempL = rsL + rtL + get_DSPControl_carryflag();
+ temp31 = (tempL >> 31) & 0x01;
+ temp32 = (tempL >> 32) & 0x01;
+
+ if(temp31 != temp32)
+ set_DSPControl_overflow_flag(1, 20);
+
+ rd = tempL & MIPSDSP_LLO;
+
+ return rd;
+}
+
+uint32_t helper_bitrev(uint32_t rt)
+{
+ int32_t temp;
+ uint32_t rd;
+
+ temp = rt & MIPSDSP_LO;
+ rd = temp;
+
+ return rd;
+}
+
+void helper_cmpeqph(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t flag;
+ int32_t ccA = 0, ccB = 0;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt& MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ if(rsh == rth)
+ ccB = 1;
+ if(rsl == rtl)
+ ccA = 1;
+ flag = (ccB << 1) | ccA;
+ set_DSPControl_24(flag, 2);
+}
+
+void helper_cmpltph(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t flag;
+ int32_t ccA = 0, ccB = 0;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ if(rsh < rth)
+ ccB = 1;
+
+ if(rsl < rtl)
+ ccA = 1;
+
+ flag = (ccB << 1) | ccA;
+ set_DSPControl_24(flag, 2);
+}
+
+void helper_cmpleph(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t flag;
+ int32_t ccA = 0, ccB = 0;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ if(rsh <= rth)
+ ccB = 1;
+
+ if(rsl <= rtl)
+ ccA = 1;
+
+ flag = (ccB << 1) | ccA;
+ set_DSPControl_24(flag, 2);
+}
+
+uint32_t helper_cmpgueqqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+ uint32_t temp;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(rs3 == rt3)
+ cc3 = 1;
+
+ if(rs2 == rt2)
+ cc2 = 1;
+
+ if(rs1 == rt1)
+ cc1 = 1;
+
+ if(rs0 == rt0)
+ cc0 = 1;
+
+ temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_cmpgultqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+ uint32_t temp;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(rs3 < rt3)
+ cc3 = 1;
+
+ if(rs2 < rt2)
+ cc2 = 1;
+
+ if(rs1 < rt1)
+ cc1 = 1;
+
+ if(rs0 < rt0)
+ cc0 = 1;
+
+ temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_cmpguleqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+ uint32_t temp;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(rs3 <= rt3)
+ cc3 = 1;
+
+ if(rs2 <= rt2)
+ cc2 = 1;
+
+ if(rs1 <= rt1)
+ cc1 = 1;
+
+ if(rs0 <= rt0)
+ cc0 = 1;
+
+ temp = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ rd = temp;
+
+ return rd;
+}
+
+void helper_cmpueqqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+ uint32_t flag;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(rs3 == rt3)
+ cc3 = 1;
+
+ if(rs2 == rt2)
+ cc2 = 1;
+
+ if(rs1 == rt1)
+ cc1 = 1;
+
+ if(rs0 == rt0)
+ cc0 = 1;
+
+ flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ set_DSPControl_24(flag, 4);
+}
+
+void helper_cmpultqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+ uint32_t flag;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(rs3 < rt3)
+ cc3 = 1;
+
+ if(rs2 < rt2)
+ cc2 = 1;
+
+ if(rs1 < rt1)
+ cc1 = 1;
+
+ if(rs0 < rt0)
+ cc0 = 1;
+
+ flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ set_DSPControl_24(flag, 4);
+}
+
+void helper_cmpuleqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
+ uint32_t flag;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(rs3 <= rt3)
+ cc3 = 1;
+
+ if(rs2 <= rt2)
+ cc2 = 1;
+
+ if(rs1 <= rt1)
+ cc1 = 1;
+
+ if(rs0 <= rt0)
+ cc0 = 1;
+
+ flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ set_DSPControl_24(flag, 4);
+}
+
+void helper_dpaqswph(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t acc, dotp, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rth);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc += dotp;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+void helper_dpaqsalw(int ac, uint32_t rs, uint32_t rt)
+{
+ int32_t temp64, temp63, tempacc63, tempdotp63, tempDL63;
+ int64_t dotp, acc;
+ int64_t tempDL[2];
+ uint64_t temp;
+
+ dotp = mipsdsp_mul_q31_q31(ac, rs, rt);
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempDL[0] = acc + dotp;
+
+ tempacc63 = (acc >> 63) & 0x01;
+ tempdotp63 = (dotp >> 63) & 0x01;
+ tempDL63 = (tempDL[0] >> 63) & 0x01;
+
+ if (((tempacc63 == 1) && (tempdotp63 == 1)) | \
+ (((tempacc63 == 1) || (tempdotp63 == 1)) && tempDL63 == 0))
+ tempDL[1] = 1;
+ else
+ tempDL[1] = 0;
+
+ temp = tempDL[0];
+ temp64 = tempDL[1] & 0x01;
+ temp63 = (tempDL[0] >> 63) & 0x01;
+
+ if(temp64 != temp63) {
+ if(1 == temp64)
+ temp = 0x8000000000000000;
+ else
+ temp = 0x7FFFFFFFFFFFFFFF;
+
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ }
+
+ env->active_tc.HI[ac] = (temp & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = temp & MIPSDSP_LLO;
+}
+
+void helper_dpauhqbl(int ac, uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2;
+ uint8_t rt3, rt2;
+ uint16_t tempB, tempA;
+ uint64_t tempC, tempBL, tempAL, dotp;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ tempB = mipsdsp_mul_u8_u8(rs3, rt3);
+ tempA = mipsdsp_mul_u8_u8(rs2, rt2);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) + dotp;
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_dpauhqbr(int ac, uint32_t rs, uint32_t rt)
+{
+ uint8_t rs1, rs0;
+ uint8_t rt1, rt0;
+ uint16_t tempB, tempA;
+ uint64_t tempC, tempBL, tempAL, dotp;
+
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rs0 = (rs & MIPSDSP_Q0);
+ rt0 = (rt & MIPSDSP_Q0);
+ tempB = mipsdsp_mul_u8_u8(rs1, rt1);
+ tempA = mipsdsp_mul_u8_u8(rs0, rt0);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) + dotp;
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_dpsqswph(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t acc, dotp, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rth);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc -= dotp;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+void helper_dpsqsalw(int ac, uint32_t rs, uint32_t rt)
+{
+ int32_t temp64, temp63, tempacc63, tempdotp63, tempDL63;
+ int64_t dotp, acc;
+ int64_t tempDL[2];
+ uint64_t temp;
+
+ dotp = mipsdsp_mul_q31_q31(ac, rs, rt);
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempDL[0] = acc - dotp;
+
+ tempacc63 = (acc >> 63) & 0x01;
+ tempdotp63 = (dotp >> 63) & 0x01;
+ tempDL63 = (tempDL[0] >> 63) & 0x01;
+
+ if (((tempacc63 == 1) && (tempdotp63 == 0)) | \
+ (((tempacc63 == 1) || (tempdotp63 == 0)) && tempDL63 == 0))
+ tempDL[1] = 1;
+ else
+ tempDL[1] = 0;
+
+ temp = tempDL[0];
+ temp64 = tempDL[1] & 0x01;
+ temp63 = (tempDL[0] >> 63) & 0x01;
+ if(temp64 != temp63) {
+ if(temp64 == 1)
+ temp = 0x8000000000000000;
+ else
+ temp = 0x7FFFFFFFFFFFFFFF;
+ set_DSPControl_overflow_flag(1, ac + 16);
+ }
+
+ env->active_tc.HI[ac] = (temp & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = temp & MIPSDSP_LLO;
+}
+
+void helper_dpsuhqbl(int ac, uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rt3, rt2;
+ uint16_t tempB, tempA;
+ uint64_t dotp, tempBL, tempAL, tempC;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+
+ tempB = mipsdsp_mul_u8_u8(rs3, rt3);
+ tempA = mipsdsp_mul_u8_u8(rs2, rt2);
+ tempBL = tempB & 0xFFFF;
+ tempAL = tempA & 0xFFFF;
+
+ dotp = tempBL + tempAL;
+ tempC = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempC -= dotp;
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_dpsuhqbr(int ac, uint32_t rs, uint32_t rt)
+{
+ uint8_t rs1, rs0, rt1, rt0;
+ uint16_t tempB, tempA;
+ uint64_t dotp, tempBL, tempAL, tempC;
+
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = (rs & MIPSDSP_Q0);
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = (rt & MIPSDSP_Q0);
+
+ tempB = mipsdsp_mul_u8_u8(rs1, rt1);
+ tempA = mipsdsp_mul_u8_u8(rs0, rt0);
+ tempBL = tempB & 0xFFFF;
+ tempAL = tempA & 0xFFFF;
+
+ dotp = tempBL + tempAL;
+ tempC = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempC -= dotp;
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_extp(int ac, int size, int rt)
+{
+ int32_t start_pos;
+
+ start_pos = get_DSPControl_pos();
+ if(start_pos - (size + 1) >= -1) {
+ uint32_t temp;
+ uint64_t acc;
+
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ temp = (acc >> (start_pos - size)) & \
+ (((uint32_t)0x01 << (size + 1)) -1);
+ env->active_tc.gpr[rt] = temp;
+ set_DSPControl_efi(0);
+ } else {
+ set_DSPControl_efi(1);
+ }
+}
+
+void helper_extpdp(int ac, int size, int rt)
+{
+ int32_t start_pos;
+
+ start_pos = get_DSPControl_pos();
+ if(start_pos - (size + 1) >= -1) {
+ uint32_t temp;
+ uint64_t acc;
+
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ temp = (acc >> (start_pos - size)) & \
+ (((uint32_t)0x01 << (size + 1)) - 1);
+
+ env->active_tc.gpr[rt] = temp;
+ set_DSPControl_pos(start_pos - (size + 1));
+ set_DSPControl_efi(0);
+ }
+ else
+ set_DSPControl_efi(1);
+}
+
+void helper_extpdpv(int ac, uint32_t rs, int rt)
+{
+ int32_t start_pos, size;
+
+ start_pos = get_DSPControl_pos();
+ size = rs & 0x1F;
+
+ if(start_pos - (size + 1) >= -1) {
+ uint32_t temp;
+ uint64_t acc;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ temp = (acc >> (start_pos - size)) & (((int)0x01 << (size + 1)) - 1);
+ env->active_tc.gpr[rt] = temp;
+ set_DSPControl_pos(start_pos - (size + 1));
+ set_DSPControl_efi(0);
+ } else
+ set_DSPControl_efi(1);
+}
+
+void helper_extpv(int ac, uint32_t rs, int rt)
+{
+ int32_t start_pos, size;
+
+ start_pos = get_DSPControl_pos();
+ size = rs & 0x1F;
+
+ if(start_pos - (size + 1) >= -1) {
+ uint32_t temp;
+ uint64_t acc;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ temp = (acc >> (start_pos - size)) & \
+ (((uint32_t)0x01 << (size + 1)) - 1);
+ env->active_tc.gpr[rt] = temp;
+ set_DSPControl_efi(0);
+ } else
+ set_DSPControl_efi(1);
+}
+
+void helper_extrsh(int ac, int shift, int rt)
+{
+ int64_t temp;
+
+ temp = mipsdsp_rashift_short_acc(ac, shift);
+ if(temp > 0x0000000000007FFF) {
+ temp &= MIPSDSP_LHI;
+ temp |= 0x00007FFF;
+ set_DSPControl_overflow_flag(1, 23);
+ } else if(temp < 0xFFFFFFFFFFFF8000) {
+ temp &= MIPSDSP_LHI;
+ temp |= 0xFFFF8000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+
+ env->active_tc.gpr[rt] = temp & 0xFFFFFFFF;
+}
+
+void helper_extrw(int ac, int shift, int rt)
+{
+ int32_t tempI;
+ int64_t tempDL[2];
+
+ mipsdsp__rashift_short_acc(tempDL, ac, shift);
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+
+ tempI = (tempDL[0] >> 1) & MIPSDSP_LLO;
+ env->active_tc.gpr[rt] = tempI;
+
+ tempDL[0] += 1;
+ if(0 == tempDL[0])
+ tempDL[1] += 1;
+
+ if((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) && \
+ (!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI)))
+ set_DSPControl_overflow_flag(1, 23);
+}
+
+void helper_extrrw(int ac, int shift, int rt)
+{
+ int32_t tempI;
+ int64_t tempDL[2];
+
+ mipsdsp__rashift_short_acc(tempDL, ac, shift);
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+
+ tempDL[0] += 1;
+ if(tempDL[0] == 0)
+ tempDL[1] += 1;
+
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+ tempI = tempDL[0] >> 1;
+
+ env->active_tc.gpr[rt] = tempI;
+}
+
+void helper_extrrsw(int ac, int shift, int rt)
+{
+ int32_t tempI, temp64;
+ int64_t tempDL[2];
+
+ mipsdsp__rashift_short_acc(tempDL, ac, shift);
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) \
+ && (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+ tempDL[0] += 1;
+ if(0 == tempDL[0])
+ tempDL[1] += 1;
+ tempI = tempDL[0] >> 1;
+
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) \
+ && (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ {
+ temp64 = tempDL[1];
+ if(0 == temp64)
+ tempI = 0x7FFFFFFF;
+ else
+ tempI = 0x80000000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+ env->active_tc.gpr[rt] = tempI;
+}
+
+uint32_t helper_extrvsh(int ac, uint32_t rs)
+{
+ uint32_t rd;
+ int32_t shift, tempI;
+ int64_t tempL;
+
+ shift = rs & 0x0F;
+ tempL = mipsdsp_rashift_short_acc(ac, shift);
+ if(tempL > 0x000000000007FFF) {
+ tempI = 0x00007FFF;
+ set_DSPControl_overflow_flag(1, 23);
+ } else if(tempL < 0xFFFFFFFFFFF8000) {
+ tempI = 0xFFFF8000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+ rd = tempI;
+
+ return rd;
+}
+
+void helper_extrvw(int ac, uint32_t rs, int rt)
+{
+ int32_t shift, tempI;
+ int64_t tempDL[2];
+
+ shift = rs & 0x0F;
+ mipsdsp__rashift_short_acc(tempDL, ac, shift);
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+
+ tempI = tempDL[0] >> 1;
+ env->active_tc.gpr[rt] = tempI;
+
+ tempDL[0] += 1;
+ if(0 == tempDL[0])
+ tempDL[1] += 1;
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+}
+
+void helper_extrvrw(int ac, uint32_t rs, int rt)
+{
+ int32_t shift, tempI;
+ int64_t tempDL[2];
+
+ shift = rs & 0x0F;
+ mipsdsp__rashift_short_acc(tempDL, ac, shift);
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+
+ tempDL[0] += 1;
+ if(tempDL[0] == 0)
+ tempDL[1] += 1;
+
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+ tempI = tempDL[0] >> 1;
+ env->active_tc.gpr[rt] = tempI;
+}
+
+void helper_extrvrsw(int ac, uint32_t rs, int rt)
+{
+ int32_t shift, tempI;
+ int64_t tempDL[2];
+
+ shift = rs & 0x0F;
+ mipsdsp__rashift_short_acc(tempDL, ac, shift);
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI))
+ set_DSPControl_overflow_flag(1, 23);
+
+ tempDL[0] += 1;
+ if(tempDL[0] == 0)
+ tempDL[1] += 1;
+ tempI = tempDL[0] >> 1;
+
+ if((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) && \
+ (tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
+ if(0 == tempDL[1])
+ tempI = 0x7FFFFFFF;
+ else
+ tempI = 0x80000000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+ env->active_tc.gpr[rt] = tempI;
+}
+
+void helper_insv(int reg_rt, uint32_t rs, uint32_t rt)
+{
+ uint32_t pos, size, msb, lsb, rs_f, rt_f;
+ uint32_t temp, temprs, temprt;
+ target_ulong dspc;
+
+ dspc = env->active_tc.DSPControl;
+ pos = dspc & 0x1F;
+ size = (dspc >> 7) & 0x1F;
+ msb = pos + size - 1;
+ lsb = pos;
+
+ if(lsb > msb)
+ return;
+
+ rs_f = (((int32_t)0x01 << (msb - lsb + 1 + 1)) - 1) << lsb;
+ rt_f = rs_f ^ 0xFFFFFFFF;
+ temprs = rs & rs_f;
+ temprt = rt & rt_f;
+ temp = temprs | temprt;
+ env->active_tc.gpr[reg_rt] = temp;
+}
+
+target_ulong helper_lbux(target_ulong addr, int mem_idx)
+{
+ target_ulong temp;
+
+ temp = do_lbu(addr, mem_idx);
+ temp = temp & MIPSDSP_Q0;
+
+ return temp;
+}
+
+uint32_t helper_lhx(target_ulong vaddr, int mem_idx)
+{
+ target_ulong temp;
+ int16_t half;
+ uint32_t rd;
+
+ temp = do_lw(vaddr, mem_idx);
+ half = temp & 0x0000FFFF;
+ rd = (int32_t)half;
+
+ return rd;
+}
+
+uint32_t helper_lwx(target_ulong vaddr, int mem_idx)
+{
+ target_ulong temp;
+ uint32_t rd;
+
+ temp = do_lw(vaddr, mem_idx);
+ rd = (int32_t)temp;
+
+ return rd;
+}
+
+void helper_maqswphl(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rth;
+ int32_t tempA;
+ int64_t tempL, tempAL, acc;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ tempA = mipsdsp_mul_q15_q15(ac, rsh, rth);
+ tempAL = tempA;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempL = tempAL + acc;
+ env->active_tc.HI[ac] = (tempL & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempL & MIPSDSP_LLO;
+}
+
+void helper_maqsawphl(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rth;
+ int32_t tempA;
+ int64_t tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ tempA = mipsdsp_mul_q15_q15(ac, rsh, rth);
+ tempA = mipsdsp_sat32_acc_q31(ac, tempA);
+ tempAL = tempA;
+
+ env->active_tc.HI[ac] = (tempAL & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempAL & MIPSDSP_LLO;
+}
+
+void helper_maqswphr(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsl, rtl;
+ int32_t tempA;
+ int64_t tempL, tempAL, acc;
+
+ rsl = rs & MIPSDSP_LO;
+ rtl = rt & MIPSDSP_LO;
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl);
+ tempAL = tempA;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempL = tempAL + acc;
+
+ env->active_tc.HI[ac] = (tempL & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempL & MIPSDSP_LLO;
+}
+
+void helper_maqsawphr(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsl, rtl;
+ int32_t tempA;
+ int64_t tempAL;
+
+ rsl = rs & MIPSDSP_LO;
+ rtl = rs & MIPSDSP_LO;
+
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl);
+ tempA = mipsdsp_sat32_acc_q31(ac, tempA);
+ tempAL = tempA;
+
+ env->active_tc.HI[ac] = (tempAL & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempAL & MIPSDSP_LLO;
+}
+
+uint32_t helper_modsub(uint32_t rs, uint32_t rt)
+{
+ int32_t decr;
+ uint16_t lastindex;
+ uint32_t rd;
+
+ decr = rt & MIPSDSP_Q0;
+ lastindex = (rt >> 8) & MIPSDSP_LO;
+
+ if(0x00000000 == rs)
+ rd = (uint32_t)lastindex;
+ else
+ rd = rs - decr;
+
+ return rd;
+}
+
+void helper_mthlip(int ac, uint32_t rs)
+{
+ int32_t tempA, tempB, pos;
+
+ tempA = rs;
+ tempB = env->active_tc.LO[ac];
+ env->active_tc.HI[ac] = tempB;
+ env->active_tc.LO[ac] = tempA;
+ pos = get_DSPControl_pos();
+
+ if(pos > 32)
+ return;
+ else
+ set_DSPControl_pos(pos + 32);
+}
+
+uint32_t helper_muleqswphl(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rth;
+ int32_t temp;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ temp = mipsdsp_mul_q15_q15_overflowflag21(rsh, rth);
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_muleqswphr(uint32_t rs, uint32_t rt)
+{
+ int16_t rsl, rtl;
+ int32_t temp;
+ uint32_t rd;
+
+ rsl = rs & MIPSDSP_LO;
+ rtl = rt & MIPSDSP_LO;
+ temp = mipsdsp_mul_q15_q15_overflowflag21(rsl, rtl);
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_muleusphqbl(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2;
+ uint16_t tempB, tempA, rth, rtl;
+ uint32_t temp;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_mul_u8_u16(rs3, rth);
+ tempA = mipsdsp_mul_u8_u16(rs2, rtl);
+ temp = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+ rd = temp;
+ return rd;
+}
+
+uint32_t helper_muleusphqbr(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs1, rs0;
+ uint16_t tempB, tempA;
+ uint16_t rth, rtl;
+ uint32_t temp;
+ uint32_t rd;
+
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_u8_u16(rs1, rth);
+ tempA = mipsdsp_mul_u8_u16(rs0, rtl);
+ temp = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+ rd = temp;
+ return rd;
+}
+
+uint32_t helper_mulqrsph(uint32_t rs, uint32_t rt)
+{
+ int16_t tempB, tempA, rsh, rsl, rth, rtl;
+ int32_t temp;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_rndq15_mul_q15_q15(rsh, rth);
+ tempA = mipsdsp_rndq15_mul_q15_q15(rsl, rtl);
+ temp = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+ rd = temp;
+
+ return rd;
+}
+
+void helper_mulsaqswph(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t tempBL, tempAL, acc, dotp;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rth);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rtl);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL - tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ dotp = dotp + acc;
+ env->active_tc.HI[ac] = (dotp & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = dotp & MIPSDSP_LLO;
+}
+
+uint32_t helper_packrlph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsl, rth;
+ uint32_t rd;
+
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rd = (rsl << 16) | rth;
+
+ return rd;
+}
+
+uint32_t helper_pickqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tp3, tp2, tp1, tp0;
+
+ uint32_t dsp27, dsp26, dsp25, dsp24, rd;
+ target_ulong dsp;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ dsp = env->active_tc.DSPControl;
+ dsp27 = (dsp >> 27) & 0x01;
+ dsp26 = (dsp >> 26) & 0x01;
+ dsp25 = (dsp >> 25) & 0x01;
+ dsp24 = (dsp >> 24) & 0x01;
+
+ tp3 = dsp27 == 1 ? rs3:rt3;
+ tp2 = dsp26 == 1 ? rs2:rt2;
+ tp1 = dsp25 == 1 ? rs1:rt1;
+ tp0 = dsp24 == 1 ? rs0:rt0;
+
+ rd = ((uint32_t)tp3 << 24) | \
+ ((uint32_t)tp2 << 16) | \
+ ((uint32_t)tp1 << 8) | \
+ (uint32_t)tp0;
+
+ return rd;
+}
+
+uint32_t helper_preceqwphl(uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = rt & MIPSDSP_HI;
+
+ return rd;
+}
+
+uint32_t helper_pickph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t dsp25, dsp24;
+ uint32_t rd;
+ target_ulong dsp;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ dsp = env->active_tc.DSPControl;
+ dsp25 = (dsp >> 25) & 0x01;
+ dsp24 = (dsp >> 24) & 0x01;
+
+ tempB = dsp25 == 1 ? rsh: rth;
+ tempA = dsp24 == 1 ? rsl: rtl;
+ rd = (((uint32_t)tempB << 16) & MIPSDSP_HI) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_preceqwphr(uint32_t rt)
+{
+ uint16_t rtl;
+ uint32_t rd;
+
+ rtl = rt & MIPSDSP_LO;
+ rd = rtl << 16;
+
+ return rd;
+}
+
+uint32_t helper_precequphqbl(uint32_t rt)
+{
+ uint8_t rt3, rt2;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+
+ tempB = (uint16_t)rt3 << 7;
+ tempA = (uint16_t)rt2 << 7;
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_precequphqbla(uint32_t rt)
+{
+ uint8_t rt3, rt1;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+
+ tempB = (uint16_t)rt3 << 7;
+ tempA = (uint16_t)rt1 << 7;
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_precequphqbr(uint32_t rt)
+{
+ uint8_t rt1, rt0;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+ tempB = (uint16_t)rt1 << 7;
+ tempA = (uint16_t)rt0 << 7;
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_precequphqbra(uint32_t rt)
+{
+ uint8_t rt2, rt0;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt0 = rt & MIPSDSP_Q0;
+ tempB = (uint16_t)rt2 << 7;
+ tempA = (uint16_t)rt0 << 7;
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_preceuphqbl(uint32_t rt)
+{
+ uint8_t rt3, rt2;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ tempB = (uint16_t) rt3;
+ tempA = (uint16_t) rt2;
+ rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_preceuphqbla(uint32_t rt)
+{
+ uint8_t rt3, rt1;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ tempB = (uint16_t) rt3;
+ tempA = (uint16_t) rt1;
+ rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_preceuphqbr(uint32_t rt)
+{
+ uint8_t rt1, rt0;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+ tempB = (uint16_t) rt1;
+ tempA = (uint16_t) rt0;
+ rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+ return rd;
+}
+
+uint32_t helper_preceuphqbra(uint32_t rt)
+{
+ uint8_t rt2, rt0;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt0 = rt & MIPSDSP_Q0;
+ tempB = (uint16_t)rt2;
+ tempA = (uint16_t)rt0;
+ rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+ return rd;
+}
+
+uint32_t helper_precrqqbph(uint32_t rs, uint32_t rt)
+{
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ tempD = (rs & MIPSDSP_Q3) >> 24;
+ tempC = (rs & MIPSDSP_Q1) >> 8;
+ tempB = (rt & MIPSDSP_Q3) >> 24;
+ tempA = (rt & MIPSDSP_Q1) >> 8;
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_precrqphw(uint32_t rs, uint32_t rt)
+{
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ tempB = (rs & MIPSDSP_HI) >> 16;
+ tempA = (rt & MIPSDSP_HI) >> 16;
+ rd = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_precrqrsphw(uint32_t rs, uint32_t rt)
+{
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ tempB = mipsdsp_trunc16_sat16_round(rs);
+ tempA = mipsdsp_trunc16_sat16_round(rt);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_precrqusqbph(uint32_t rs, uint32_t rt)
+{
+ uint8_t tempD, tempC, tempB, tempA;
+ uint16_t rsh, rsl, rth, rtl;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempD = mipsdsp_sat8_reduce_precision(rsh);
+ tempC = mipsdsp_sat8_reduce_precision(rsl);
+ tempB = mipsdsp_sat8_reduce_precision(rth);
+ tempA = mipsdsp_sat8_reduce_precision(rtl);
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_radduwqb(uint32_t rs)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint16_t temp;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ temp = (uint16_t)rs3 + (uint16_t)rs2 + (uint16_t)rs1 + (uint16_t)rs0;
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_rddsp(uint32_t masknum)
+{
+ uint8_t mask[6];
+ uint32_t ruler, i;
+ uint32_t temp;
+ uint32_t rd;
+ target_ulong dsp;
+
+ ruler = 0x01;
+ for(i = 0; i < 6; i++) {
+ mask[i] = (masknum & ruler) >> i ;
+ ruler = ruler << 1;
+ }
+
+ temp = 0x00;
+ dsp = env->active_tc.DSPControl;
+
+ if(1 == mask[0])
+ temp |= dsp & 0x3F;
+
+ if(1 == mask[1])
+ temp |= dsp & 0x1F80;
+
+ if(1 == mask[2])
+ temp |= dsp & 0x2000;
+
+ if(1 == mask[3])
+ temp |= dsp & 0x00FF0000;
+
+ if(1 == mask[4])
+ temp |= dsp & 0xFF000000;
+
+ if(1 == mask[5])
+ temp |= dsp & 0x4000;
+
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_replph(uint32_t imm)
+{
+ int16_t temp;
+ int16_t imm_temp;
+ uint32_t rd;
+
+ imm_temp = imm & 0x03FF;
+ temp = (imm_temp << 22) >> 22;
+ rd = (((uint32_t)temp << 16) & MIPSDSP_HI) | \
+ ((uint32_t)temp & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_replqb(uint32_t imm)
+{
+ uint8_t temp;
+ uint32_t rd;
+
+ temp = imm & 0x00FF;
+ rd = ((uint32_t)temp << 24) | ((uint32_t)temp << 16) | \
+ ((uint32_t)temp << 8) | (uint32_t)temp;
+
+ return rd;
+}
+
+uint32_t helper_replvph(uint32_t rt)
+{
+ uint16_t temp;
+ uint32_t rd;
+
+ temp = rt & MIPSDSP_LO;
+ rd = ((uint32_t)temp << 16) | (uint32_t)temp;
+
+ return rd;
+}
+
+uint32_t helper_replvqb(uint32_t rt)
+{
+ uint8_t temp;
+ uint32_t rd;
+
+ temp = rt & MIPSDSP_Q0;
+ rd = ((uint32_t)temp << 24) | ((uint32_t)temp << 16) | \
+ ((uint32_t)temp << 8) | (uint32_t)temp;
+
+ return rd;
+}
+
+void helper_shilo(int ac, int shift)
+{
+ uint8_t sign;
+ uint64_t temp, acc;
+
+ shift = (shift << 26) >> 26;
+ sign = (shift >> 5) & 0x01;
+ shift = sign == 0 ? shift : -shift;
+ acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+
+ if(0 == shift)
+ temp = acc;
+ else {
+ if(0 == sign)
+ temp = acc >> shift;
+ else
+ temp = acc << shift;
+ }
+
+ env->active_tc.HI[ac] = (temp & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = temp & MIPSDSP_LLO;
+}
+
+void helper_shilov(int ac, uint32_t rs)
+{
+ uint8_t sign;
+ int8_t rs5_0;
+ uint64_t temp, acc;
+
+ rs5_0 = rs & 0x3F;
+ rs = (rs5_0 << 2) >> 2;
+ sign = (rs5_0 >> 5 ) & 0x01;
+ rs5_0 = sign ==0 ? rs : -rs;
+ acc = (((uint64_t)env->active_tc.HI[ac] << 32) & MIPSDSP_LHI) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ if(0 == rs5_0)
+ temp = acc;
+ else {
+ if(0 == sign)
+ temp = acc >> rs5_0;
+ else
+ temp = acc << rs5_0;
+ }
+
+ env->active_tc.HI[ac] = (temp & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = temp & MIPSDSP_LLO;
+}
+
+uint32_t helper_shllph(int sa, uint32_t rt)
+{
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_lshift16(rth, sa);
+ tempA = mipsdsp_lshift16(rtl, sa);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shllsph(int sa, uint32_t rt)
+{
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_sat16_lshift(rth, sa);
+ tempA = mipsdsp_sat16_lshift(rtl, sa);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shllqb(int sa, uint32_t rt)
+{
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = mipsdsp_lshift8(rt3, sa);
+ tempC = mipsdsp_lshift8(rt2, sa);
+ tempB = mipsdsp_lshift8(rt1, sa);
+ tempA = mipsdsp_lshift8(rt0, sa);
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | ((uint32_t)tempA);
+
+ return rd;
+}
+
+uint32_t helper_shllsw(int sa, uint32_t rt)
+{
+ uint32_t temp, rd;
+
+ temp = mipsdsp_sat32_lshift(rt, sa);
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_shllvph(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3_0;
+ uint16_t rth, rtl, tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ rs3_0 = rs & 0x0F;
+
+ tempB = mipsdsp_lshift16(rth, rs3_0);
+ tempA = mipsdsp_lshift16(rtl, rs3_0);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shllvsph(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3_0;
+ uint16_t rth, rtl, tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ rs3_0 = rs & 0x0F;
+
+ tempB = mipsdsp_sat16_lshift(rth, rs3_0);
+ tempA = mipsdsp_sat16_lshift(rtl, rs3_0);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shllvqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs2_0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs2_0 = rs & 0x07;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = mipsdsp_lshift8(rt3, rs2_0);
+ tempC = mipsdsp_lshift8(rt2, rs2_0);
+ tempB = mipsdsp_lshift8(rt1, rs2_0);
+ tempA = mipsdsp_lshift8(rt0, rs2_0);
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shllvsw(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs4_0;
+ uint32_t rd;
+
+ rs4_0 = rs & 0x1F;
+ rd = mipsdsp_sat32_lshift(rt, rs4_0);
+
+ return rd;
+}
+
+uint32_t helper_shraph(int sa, uint32_t rt)
+{
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_rashift16(rth, sa);
+ tempA = mipsdsp_rashift16(rtl, sa);
+ rd = ((uint32_t)tempB << 16) | (uint32_t) tempA;
+
+ return rd;
+}
+
+uint32_t helper_shrarph(int sa, uint32_t rt)
+{
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_rnd16_rashift(rth, sa);
+ tempA = mipsdsp_rnd16_rashift(rtl, sa);
+ rd = ((uint32_t)tempB << 16) | (uint32_t) tempA;
+
+ return rd;
+}
+
+uint32_t helper_shrarw(int sa, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rnd32_rashift(rt, sa);
+
+ return rd;
+}
+
+uint32_t helper_shravph(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3_0;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rs3_0 = rs & 0x0F;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_rashift16(rth, rs3_0);
+ tempA = mipsdsp_rashift16(rtl, rs3_0);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shravrph(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3_0;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rs3_0 = rs & 0x0F;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_rnd16_rashift(rth, rs3_0);
+ tempA = mipsdsp_rnd16_rashift(rtl, rs3_0);
+
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shravrw(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs4_0;
+ uint32_t rd;
+
+ rs4_0 = rs & 0x1F;
+ rd = mipsdsp_rnd32_rashift(rt, rs4_0);
+
+ return rd;
+}
+
+uint32_t helper_shrlqb(int sa, uint32_t rt)
+{
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = mipsdsp_rshift8(rt3, sa);
+ tempC = mipsdsp_rshift8(rt2, sa);
+ tempB = mipsdsp_rshift8(rt1, sa);
+ tempA = mipsdsp_rshift8(rt0, sa);
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shrlvqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs2_0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs2_0 = rs & 0x07;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = mipsdsp_rshift8(rt3, rs2_0);
+ tempC = mipsdsp_rshift8(rt2, rs2_0);
+ tempB = mipsdsp_rshift8(rt1, rs2_0);
+ tempA = mipsdsp_rshift8(rt0, rs2_0);
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subqph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_sub_i16(rsh, rth);
+ tempA = mipsdsp_sub_i16(rsl, rtl);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subqsph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_sat16_sub(rsh, rth);
+ tempA = mipsdsp_sat16_sub(rsl, rtl);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subqsw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_sat32_sub(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_subuqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = mipsdsp_sub_u8(rs3, rt3);
+ tempC = mipsdsp_sub_u8(rs2, rt2);
+ tempB = mipsdsp_sub_u8(rs1, rt1);
+ tempA = mipsdsp_sub_u8(rs0, rt0);
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+ return rd;
+}
+
+uint32_t helper_subusqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = mipsdsp_satu8_sub(rs3, rt3);
+ tempC = mipsdsp_satu8_sub(rs2, rt2);
+ tempB = mipsdsp_satu8_sub(rs1, rt1);
+ tempA = mipsdsp_satu8_sub(rs0, rt0);
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+void helper_wrdsp(uint32_t rs, int mask_num)
+{
+ uint8_t mask[6];
+ uint8_t i;
+ uint32_t newbits, overwrite;
+ target_ulong dsp;
+
+ newbits = 0x00;
+ overwrite = 0xFFFFFFFF;
+ dsp = env->active_tc.DSPControl;
+
+ for(i = 0; i < 6; i++)
+ mask[i] = (mask_num >> i) & 0x01;
+
+ if(1 == mask[0]) {
+ overwrite &= 0xFFFFFFC0;
+ newbits &= 0xFFFFFFC0;
+ newbits |= 0x0000003F & rs;
+ }
+
+ if(1 == mask[1]) {
+ overwrite &= 0xFFFFE07F;
+ newbits &= 0xFFFFE07F;
+ newbits |= 0x00001F80 & rs;
+ }
+
+ if(1 == mask[2]) {
+ overwrite &= 0xFFFFDFFF;
+ newbits &= 0xFFFFDFFF;
+ newbits |= 0x00002000 & rs;
+ }
+
+ if(1 == mask[3]) {
+ overwrite &= 0xFF00FFFF;
+ newbits &= 0xFF00FFFF;
+ newbits |= 0x00FF0000 & rs;
+ }
+
+ if(1 == mask[4]) {
+ overwrite &= 0x00FFFFFF;
+ newbits &= 0x00FFFFFF;
+ newbits |= 0xFF000000 & rs;
+ }
+
+ if(1 == mask[5]) {
+ overwrite &= 0xFFFFBFFF;
+ newbits &= 0xFFFFBFFF;
+ newbits |= 0x00004000 & rs;
+ }
+
+ dsp = dsp & overwrite;
+ dsp = dsp | newbits;
+ env->active_tc.DSPControl = dsp;
+}
+
+/* MIPS DSPR2 */
+uint32_t helper_absqsqb (uint32_t rt)
+{
+ uint32_t rd;
+ int8_t tempD, tempC, tempB, tempA;
+
+ tempD = (rt & MIPSDSP_Q3) >> 24;
+ tempC = (rt & MIPSDSP_Q2) >> 16;
+ tempB = (rt & MIPSDSP_Q1) >> 8;
+ tempA = rt & MIPSDSP_Q0;
+
+ rd = (((uint32_t)mipsdsp_sat_abs_u8 (tempD) << 24) & MIPSDSP_Q3) | \
+ (((uint32_t)mipsdsp_sat_abs_u8 (tempC) << 16) & MIPSDSP_Q2) | \
+ (((uint32_t)mipsdsp_sat_abs_u8 (tempB) << 8 ) & MIPSDSP_Q1) | \
+ ((uint32_t)mipsdsp_sat_abs_u8 (tempA) & MIPSDSP_Q0);
+
+ return rd;
+}
+
+uint32_t helper_addqhph(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int16_t rsh, rsl, rth, rtl, temph, templ;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ temph = mipsdsp_rshift1_add_q16(rsh, rth);
+ templ = mipsdsp_rshift1_add_q16(rsl, rtl);
+ rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_addqhrph(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int16_t rsh, rsl, rth, rtl, temph, templ;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ temph = mipsdsp_rrshift1_add_q16(rsh, rth);
+ templ = mipsdsp_rrshift1_add_q16(rsl, rtl);
+ rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_addqhw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rshift1_add_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_addqhrw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rrshift1_add_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_adduph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl, temph, templ;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ temph = mipsdsp_add_u16(rsh, rth);
+ templ = mipsdsp_add_u16(rsl, rtl);
+ rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_addusph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl, temph, templ;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ temph = mipsdsp_sat_add_u16(rsh, rth);
+ templ = mipsdsp_sat_add_u16(rsl, rtl);
+ rd = ((uint32_t)temph << 16) | ((uint32_t)templ & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_adduqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint8_t temp0, temp1, temp2, temp3;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ temp0 = mipsdsp_add_u8(rs0, rt0);
+ temp1 = mipsdsp_add_u8(rs1, rt1);
+ temp2 = mipsdsp_add_u8(rs2, rt2);
+ temp3 = mipsdsp_add_u8(rs3, rt3);
+
+ rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) | \
+ (((uint32_t)temp2 << 16) & MIPSDSP_Q2) | \
+ (((uint32_t)temp1 << 8) & MIPSDSP_Q1) | \
+ ((uint32_t)temp0 & MIPSDSP_Q0);
+
+ return rd;
+}
+
+uint32_t helper_addusqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint8_t temp0, temp1, temp2, temp3;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ temp0 = mipsdsp_sat_add_u8(rs0, rt0);
+ temp1 = mipsdsp_sat_add_u8(rs1, rt1);
+ temp2 = mipsdsp_sat_add_u8(rs2, rt2);
+ temp3 = mipsdsp_sat_add_u8(rs3, rt3);
+
+ rd = (((uint8_t)temp3 << 24) & MIPSDSP_Q3) | \
+ (((uint8_t)temp2 << 16) & MIPSDSP_Q2) | \
+ (((uint8_t)temp1 << 8) & MIPSDSP_Q1) | \
+ ((uint8_t)temp0 & MIPSDSP_Q0);
+
+ return rd;
+}
+
+uint32_t helper_adduhqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint8_t temp0, temp1, temp2, temp3;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ temp0 = mipsdsp_rshift1_add_u8(rs0, rt0);
+ temp1 = mipsdsp_rshift1_add_u8(rs1, rt1);
+ temp2 = mipsdsp_rshift1_add_u8(rs2, rt2);
+ temp3 = mipsdsp_rshift1_add_u8(rs3, rt3);
+
+ rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) | \
+ (((uint32_t)temp2 << 16) & MIPSDSP_Q2) | \
+ (((uint32_t)temp1 << 8) & MIPSDSP_Q1) | \
+ ((uint32_t)temp0 & MIPSDSP_Q0);
+
+ return rd;
+}
+
+uint32_t helper_adduhrqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint8_t temp0, temp1, temp2, temp3;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ temp0 = mipsdsp_rrshift1_add_u8(rs0, rt0);
+ temp1 = mipsdsp_rrshift1_add_u8(rs1, rt1);
+ temp2 = mipsdsp_rrshift1_add_u8(rs2, rt2);
+ temp3 = mipsdsp_rrshift1_add_u8(rs3, rt3);
+
+ rd = (((uint32_t)temp3 << 24) & MIPSDSP_Q3) | \
+ (((uint32_t)temp2 << 16) & MIPSDSP_Q2) | \
+ (((uint32_t)temp1 << 8) & MIPSDSP_Q1) | \
+ ((uint32_t)temp0 & MIPSDSP_Q0);
+
+ return rd;
+}
+
+uint32_t helper_append(uint32_t rt, uint32_t rs, int sa)
+{
+ int len;
+ uint32_t temp;
+
+ len = sa & 0x1F;
+
+ if(0 == len)
+ temp = rt;
+ else {
+ temp = (rt << len) | (rs & (((uint32_t)0x01 << len) - 1));
+ }
+ rt = temp;
+
+ return temp;
+}
+
+uint32_t helper_balign(uint32_t rt, uint32_t rs, uint32_t bp)
+{
+ uint32_t temp;
+ bp = bp & 0x03;
+
+ if(0 == bp || 2 == bp)
+ return rt;
+ else
+ temp = (rt << (8 * bp)) | (rs >> (8 * (4 - bp)));
+ rt = temp;
+
+ return rt;
+}
+
+
+uint32_t helper_cmpgdueqqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint32_t cc0 = 0, cc1 = 0, cc2 = 0, cc3 = 0;
+ uint32_t flag;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ if(rs0 == rt0)
+ cc0 = 1;
+
+ if(rs1 == rt1)
+ cc1 = 1;
+
+ if(rs2 == rt2)
+ cc2 = 1;
+
+ if(rs3 == rt3)
+ cc3 = 1;
+
+ flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ set_DSPControl_24(flag, 4);
+ rd = flag;
+
+ return rd;
+}
+
+uint32_t helper_cmpgdultqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint32_t cc0 = 0, cc1 = 0, cc2 = 0, cc3 = 0;
+ uint32_t flag;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ if(rs0 < rt0)
+ cc0 = 1;
+
+ if(rs1 < rt1)
+ cc1 = 1;
+
+ if(rs2 < rt2)
+ cc2 = 1;
+
+ if(rs3 < rt3)
+ cc3 = 1;
+
+ flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ set_DSPControl_24(flag, 4);
+ rd = flag;
+
+ return rd;
+}
+
+uint32_t helper_cmpgduleqb(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ uint8_t rs0, rs1, rs2, rs3;
+ uint8_t rt0, rt1, rt2, rt3;
+ uint32_t cc0 = 0, cc1 = 0, cc2 = 0, cc3 = 0;
+ uint32_t flag;
+
+ rs0 = rs & MIPSDSP_Q0;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+
+ rt0 = rt & MIPSDSP_Q0;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+
+ if(rs0 <= rt0)
+ cc0 = 1;
+
+ if(rs1 <= rt1)
+ cc1 = 1;
+
+ if(rs2 <= rt2)
+ cc2 = 1;
+
+ if(rs3 <= rt3)
+ cc3 = 1;
+
+ flag = (cc3 << 3) | (cc2 << 2) | (cc1 << 1) | cc0;
+ set_DSPControl_24(flag, 4);
+ rd = flag;
+
+ return rd;
+}
+
+void helper_dpawph(int ac, uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ int32_t tempA, tempB;
+ int64_t acc, tempAL, tempBL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = (int32_t)rsh * (int32_t)rth;
+ tempA = (int32_t)rsl * (int32_t)rtl;
+ tempBL = tempB;
+ tempAL = tempA;
+
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc += tempBL + tempAL;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+void helper_dpaqxswph(int ac, uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t acc, dotp, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rth);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc += dotp;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+void helper_dpaqxsawph(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA, tempC62_31, tempC63;
+ int64_t acc, dotp, tempBL, tempAL, tempC;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rth);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempC = acc + dotp;
+ tempC63 = (tempC >> 63) & 0x01;
+ tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;
+
+ if((0 == tempC63) && (0xFFFFFFFF == tempC62_31)) {
+ tempC = 0x80000000;
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ }
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_dpaxwph(int ac, uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t acc, dotp, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = (uint32_t)rsh * (uint32_t)rth;
+ tempA = (uint32_t)rsl * (uint32_t)rtl;
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc += dotp;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+void helper_dpswph(int ac, uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t acc, dotp, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = (int32_t)rsh * (int32_t)rth;
+ tempA = (int32_t)rsl * (int32_t)rtl;
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc -= dotp;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+void helper_dpsqxswph(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t dotp, tempC, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rth);
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ tempC = (((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO)) - dotp;
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_dpsqxsawph(int ac, uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA, tempC63, tempC62_31;
+ int64_t dotp, tempBL, tempAL, tempC;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_mul_q15_q15(ac, rsh, rtl);
+ tempA = mipsdsp_mul_q15_q15(ac, rsl, rth);
+
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+ tempC = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ tempC -= dotp;
+
+ tempC63 = (tempC >> 63) & 0x01;
+ tempC62_31 = (tempC >> 31) & 0xFFFFFFFF;
+
+ if((0 == tempC63) && (0 != tempC62_31)) {
+ tempC = 0x7FFFFFFF;
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ }
+
+ if((1 == tempC63) && (0xFFFFFFFF != tempC62_31)) {
+ tempC = 0xFFFFFFFF80000000;
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ }
+
+ env->active_tc.HI[ac] = (tempC & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = tempC & MIPSDSP_LLO;
+}
+
+void helper_dpsxwph(int ac, uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t acc, dotp, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = (int32_t)rsh * (int32_t)rtl;
+ tempA = (int32_t)rsl * (int32_t)rth;
+ tempBL = tempB;
+ tempAL = tempA;
+ dotp = tempBL + tempAL;
+
+ acc = ((uint64_t)env->active_tc.HI[ac] << 32) | \
+ ((uint64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc -= dotp;
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+uint32_t helper_mulph(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_mul_i16_i16(rsh, rth);
+ tempA = mipsdsp_mul_i16_i16(rsl, rtl);
+
+ rd = ((tempB & MIPSDSP_LO) << 16) | (tempA & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_mulsph(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_sat16_mul_i16_i16(rsh, rth);
+ tempA = mipsdsp_sat16_mul_i16_i16(rsl, rtl);
+
+ rd = ((tempB & MIPSDSP_LO) << 16) | (tempA & MIPSDSP_LO);
+
+ return rd;
+}
+
+uint32_t helper_mulqsph(uint32_t rs, uint32_t rt)
+{
+ int16_t rsh, rsl, rth, rtl;
+ int32_t temp, tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_sat16_mul_q15_q15(rsh, rth);
+ tempA = mipsdsp_sat16_mul_q15_q15(rsl, rtl);
+ temp = ((tempB & MIPSDSP_LO) << 16) | (tempA & MIPSDSP_LO);
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_mulqrsw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int32_t tempI;
+ int64_t tempL;
+
+ if((0x80000000 == rs) && (0x80000000 == rt)) {
+ tempL = 0x7FFFFFFF00000000;
+ set_DSPControl_overflow_flag(1, 21);
+ } else {
+ tempL = ((int64_t)rs * (int64_t)rt) << 1;
+ tempL += 0x80000000;
+ }
+ tempI = (tempL & MIPSDSP_LHI) >> 32;
+ rd = tempI;
+
+ return rd;
+}
+
+uint32_t helper_mulqsw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int32_t tempI;
+ int64_t tempL;
+
+ if((0x80000000 == rs) && (0x80000000 == rt)) {
+ tempL = 0x7FFFFFFF00000000;
+ set_DSPControl_overflow_flag(1, 21);
+ } else {
+ tempL = ((int64_t)rs * (int64_t)rt) << 1;
+ }
+ tempI = (tempL & MIPSDSP_LHI) >> 32;
+ rd = tempI;
+
+ return rd;
+}
+
+void helper_mulsawph(int ac, uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ int32_t tempB, tempA;
+ int64_t dotp, acc, tempBL, tempAL;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = (int32_t)rsh * (int32_t)rth;
+ tempA = (int32_t)rsl * (int32_t)rtl;
+ tempBL = tempB;
+ tempAL = tempA;
+
+ dotp = tempBL - tempAL;
+ acc = ((int64_t)env->active_tc.HI[ac] << 32) | \
+ ((int64_t)env->active_tc.LO[ac] & MIPSDSP_LLO);
+ acc = acc + dotp;
+
+ env->active_tc.HI[ac] = (acc & MIPSDSP_LHI) >> 32;
+ env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
+}
+
+uint32_t helper_precrqbph(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs2, rs0, rt2, rt0;
+ uint32_t rd;
+
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs0 = rs & MIPSDSP_Q0;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt0 = rt & MIPSDSP_Q0;
+ rd = ((uint32_t)rs2 << 24) | ((uint32_t)rs0 << 16) | \
+ ((uint32_t)rt2 << 8) | (uint32_t)rt0;
+
+ return rd;
+}
+
+uint32_t helper_precrsraphw(int sa, uint32_t rs, uint32_t rt)
+{
+ uint16_t tempB, tempA;
+
+ if(0 == sa) {
+ tempB = rt & MIPSDSP_LO;
+ tempA = rs & MIPSDSP_LO;
+ } else {
+ tempB = ((int32_t)rt >> sa) & MIPSDSP_LO;
+ tempA = ((int32_t)rs >> sa) & MIPSDSP_LO;
+ }
+ rt = ((uint32_t)tempB << 16) | ((uint32_t)tempA & MIPSDSP_LO);
+
+ return rt;
+}
+
+uint32_t helper_precrsrarphw(int sa, uint32_t rs, uint32_t rt)
+{
+ uint64_t tempB, tempA;
+
+ if(0 == sa) {
+ tempB = (rt & MIPSDSP_LO) << 1;
+ tempA = (rs & MIPSDSP_LO) << 1;
+ } else {
+ tempB = ((int32_t)rt >> (sa - 1)) + 1;
+ tempA = ((int32_t)rs >> (sa - 1)) + 1;
+ }
+ rt = (((tempB >> 1) & MIPSDSP_LO) << 16) | ((tempA >> 1) & MIPSDSP_LO);
+
+ return rt;
+}
+
+uint32_t helper_prepend(int sa, uint32_t rs, uint32_t rt)
+{
+ uint32_t temp;
+
+ if(0 == sa)
+ temp = rt;
+ else
+ temp = (rs << (32 - sa)) | rt >> sa;
+
+ rt = temp;
+
+ return rt;
+}
+
+uint32_t helper_shraqb(int sa, uint32_t rt)
+{
+ int8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = rt3 >> sa;
+ tempC = rt2 >> sa;
+ tempB = rt1 >> sa;
+ tempA = rt0 >> sa;
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shrarqb(int sa, uint32_t rt)
+{
+ int8_t rt3, rt2, rt1, rt0;
+ uint16_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(0 == sa) {
+ tempD = rt3 & 0x00FF;
+ tempC = rt2 & 0x00FF;
+ tempB = rt1 & 0x00FF;
+ tempA = rt0 & 0x00FF;
+ } else {
+ tempD = ((int16_t)rt3 >> (sa - 1)) + 1;
+ tempC = ((int16_t)rt2 >> (sa - 1)) + 1;
+ tempB = ((int16_t)rt1 >> (sa - 1)) + 1;
+ tempA = ((int16_t)rt0 >> (sa - 1)) + 1;
+ }
+
+ rd = ((uint32_t)((tempD >> 1) & 0x00FF) << 24) | \
+ ((uint32_t)((tempC >> 1) & 0x00FF) << 16) | \
+ ((uint32_t)((tempB >> 1) & 0x00FF) << 8) | \
+ (uint32_t)((tempA >> 1) & 0x00FF) ;
+
+ return rd;
+}
+
+uint32_t helper_shravqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs2_0;
+ int8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs2_0 = rs & 0x07;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(0 == rs2_0) {
+ tempD = rt3;
+ tempC = rt2;
+ tempB = rt1;
+ tempA = rt0;
+ } else {
+ tempD = rt3 >> rs2_0;
+ tempC = rt2 >> rs2_0;
+ tempB = rt1 >> rs2_0;
+ tempA = rt0 >> rs2_0;
+ }
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shravrqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs2_0;
+ int8_t rt3, rt2, rt1, rt0;
+ uint16_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs2_0 = rs & 0x07;
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ if(0 == rs2_0)
+ {
+ tempD = (int16_t)rt3 << 1;
+ tempC = (int16_t)rt2 << 1;
+ tempB = (int16_t)rt1 << 1;
+ tempA = (int16_t)rt0 << 1;
+ } else {
+ tempD = ((int16_t)rt3 >> (rs2_0 - 1)) + 1;
+ tempC = ((int16_t)rt2 >> (rs2_0 - 1)) + 1;
+ tempB = ((int16_t)rt1 >> (rs2_0 - 1)) + 1;
+ tempA = ((int16_t)rt0 >> (rs2_0 - 1)) + 1;
+ }
+
+ rd = ((uint32_t)((tempD >> 1) & 0x00FF) << 24) | \
+ ((uint32_t)((tempC >> 1) & 0x00FF) << 16) | \
+ ((uint32_t)((tempB >> 1) & 0x00FF) << 8) | \
+ (uint32_t)((tempA >> 1) & 0x00FF) ;
+
+ return rd;
+}
+
+uint32_t helper_shrlph(int sa, uint32_t rt)
+{
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = rth >> sa;
+ tempA = rtl >> sa;
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_shrlvph(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3_0;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rs3_0 = rs & 0x0F;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = rth >> rs3_0;
+ tempA = rtl >> rs3_0;
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subqhph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_rshift1_sub_q16(rsh, rth);
+ tempA = mipsdsp_rshift1_sub_q16(rsl, rtl);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subqhrph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl;
+ uint16_t rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+ tempB = mipsdsp_rrshift1_sub_q16(rsh, rth);
+ tempA = mipsdsp_rrshift1_sub_q16(rsl, rtl);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subqhw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rshift1_sub_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_subqhrw(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rrshift1_sub_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_subuph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_sub_u16_u16(rth, rsh);
+ tempA = mipsdsp_sub_u16_u16(rtl, rsl);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+ return rd;
+}
+
+uint32_t helper_subusph(uint32_t rs, uint32_t rt)
+{
+ uint16_t rsh, rsl, rth, rtl;
+ uint16_t tempB, tempA;
+ uint32_t rd;
+
+ rsh = (rs & MIPSDSP_HI) >> 16;
+ rsl = rs & MIPSDSP_LO;
+ rth = (rt & MIPSDSP_HI) >> 16;
+ rtl = rt & MIPSDSP_LO;
+
+ tempB = mipsdsp_satu16_sub_u16_u16(rth, rsh);
+ tempA = mipsdsp_satu16_sub_u16_u16(rtl, rsl);
+ rd = ((uint32_t)tempB << 16) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subuhqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = ((uint16_t)rs3 - (uint16_t)rt3) >> 1;
+ tempC = ((uint16_t)rs2 - (uint16_t)rt2) >> 1;
+ tempB = ((uint16_t)rs1 - (uint16_t)rt1) >> 1;
+ tempA = ((uint16_t)rs0 - (uint16_t)rt0) >> 1;
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+uint32_t helper_subuhrqb(uint32_t rs, uint32_t rt)
+{
+ uint8_t rs3, rs2, rs1, rs0;
+ uint8_t rt3, rt2, rt1, rt0;
+ uint8_t tempD, tempC, tempB, tempA;
+ uint32_t rd;
+
+ rs3 = (rs & MIPSDSP_Q3) >> 24;
+ rs2 = (rs & MIPSDSP_Q2) >> 16;
+ rs1 = (rs & MIPSDSP_Q1) >> 8;
+ rs0 = rs & MIPSDSP_Q0;
+
+ rt3 = (rt & MIPSDSP_Q3) >> 24;
+ rt2 = (rt & MIPSDSP_Q2) >> 16;
+ rt1 = (rt & MIPSDSP_Q1) >> 8;
+ rt0 = rt & MIPSDSP_Q0;
+
+ tempD = ((uint16_t)rs3 - (uint16_t)rt3 + 1) >> 1;
+ tempC = ((uint16_t)rs2 - (uint16_t)rt2 + 1) >> 1;
+ tempB = ((uint16_t)rs1 - (uint16_t)rt1 + 1) >> 1;
+ tempA = ((uint16_t)rs0 - (uint16_t)rt0 + 1) >> 1;
+
+ rd = ((uint32_t)tempD << 24) | ((uint32_t)tempC << 16) | \
+ ((uint32_t)tempB << 8) | (uint32_t)tempA;
+
+ return rd;
+}
+
+#undef MIPSDSP_LHI
+#undef MIPSDSP_LLO
+#undef MIPSDSP_HI
+#undef MIPSDSP_LO
+#undef MIPSDSP_Q0
+#undef MIPSDSP_Q1
+#undef MIPSDSP_Q2
+#undef MIPSDSP_Q3
--
1.7.5.4