From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:32860) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S70hD-0004un-F7 for qemu-devel@nongnu.org; Mon, 12 Mar 2012 04:33:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S70gy-00037Y-5a for qemu-devel@nongnu.org; Mon, 12 Mar 2012 04:33:35 -0400 Received: from mail-iy0-f173.google.com ([209.85.210.173]:52135) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S70gx-00035p-PM for qemu-devel@nongnu.org; Mon, 12 Mar 2012 04:33:20 -0400 Received: by mail-iy0-f173.google.com with SMTP id j26so7248932iaf.4 for ; Mon, 12 Mar 2012 01:33:19 -0700 (PDT) From: Jia Liu Date: Mon, 12 Mar 2012 16:32:37 +0800 Message-Id: <1331541159-5218-3-git-send-email-proljc@gmail.com> In-Reply-To: <1331541159-5218-1-git-send-email-proljc@gmail.com> References: <1331541159-5218-1-git-send-email-proljc@gmail.com> Content-Type: text/plain; charset="utf-8" Subject: [Qemu-devel] [PATCH 2/4] add MIPS DSP helpers implement List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aurelien@aurel32.net This patch is the helper implementation of MIPS ASE DSP. Signed-off-by: Jia Liu --- 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