* [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 15:33 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 02/12] Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
` (10 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add internal functions used by MIPS DSP helper functions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
Makefile.target | 3 +
target-mips/dsp_helper.c | 912 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 915 insertions(+), 0 deletions(-)
create mode 100644 target-mips/dsp_helper.c
diff --git a/Makefile.target b/Makefile.target
index 44b2e83..83b2dfc 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -99,6 +99,9 @@ endif
libobj-$(TARGET_SPARC) += int32_helper.o
libobj-$(TARGET_SPARC64) += int64_helper.o
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
+ifeq ($(TARGET_BASE_ARCH), mips)
+libobj-y += dsp_helper.o
+endif
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
new file mode 100644
index 0000000..d107eb0
--- /dev/null
+++ b/target-mips/dsp_helper.c
@@ -0,0 +1,912 @@
+/*
+ * MIPS ASE DSP Instruction emulation helpers for QEMU.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "helper.h"
+#include "dyngen-exec.h"
+
+/*** MIPS DSP internal 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 ((a & 0x80) == 0x80)
+ temp = -temp;
+ }
+
+ return temp;
+}
+
+static inline int16_t mipsdsp_sat_abs_u16(uint16_t a)
+{
+ int16_t temp;
+ temp = a;
+
+ if (a == 0x8000) {
+ set_DSPControl_overflow_flag(1, 20);
+ temp = 0x7fff;
+ } else {
+ if ((a & 0x8000) == 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 (temp16 == 0)
+ 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 & 0x100000000ull) >> 32;
+
+ if (temp31 != temp32) {
+ if (temp32 == 0)
+ 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 ((temp & 0x0100) == 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 ((temp & 0x00010000) == 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 & temp) == 0x0100) {
+ 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 & temp) == 0x00010000) {
+ 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] & 0x00000000FFFFFFFFull);
+ tempA = a;
+ temp += tempA;
+ temp32 = (temp >> 32) & 0x01;
+ temp31 = (temp >> 31) & 0x01;
+ result = temp & 0xFFFFFFFF;
+
+ if (temp32 != temp31) {
+ if (temp32 == 0)
+ 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);
+ temp &= 0x0000FFFF;
+
+ return temp;
+}
+
+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);
+ }
+ temp &= 0x0000FFFF;
+
+ return temp;
+}
+
+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 ((a == 0x8000) && (b == 0x8000)) {
+ 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 (shift == 0)
+ temp = acc;
+ else {
+ if (sign == 0)
+ 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 (shift == 0) {
+ 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 ((a == 0x8000) && (b == 0x8000)) {
+ 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 ((a == 0x80000000) && (b == 0x80000000)) {
+ temp = 0x7FFFFFFFFFFFFFFFull;
+ 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 ((a == 0x8000) && (b == 0x8000)) {
+ 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 ((a == 0x8000) && (b == 0x8000)) {
+ 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 (sign == 0) {
+ 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 (s == 0)
+ 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 (s == 0)
+ 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 (s == 0)
+ 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 (s == 0)
+ 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 (s == 0)
+ 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 (s == 0)
+ 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 (s == 0)
+ 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 (s == 0)
+ temp = a << 1;
+ else
+ temp = (int64_t)i >> (s - 1);
+ temp += 1;
+ result = (temp >> 1) & 0x00000000FFFFFFFFull;
+
+ 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 (temp16 == 0)
+ 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 (temp32 == 0)
+ temp = 0x7FFFFFFF;
+ else
+ temp = 0x80000000;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+ result = temp & 0x00000000FFFFFFFFull;
+
+ 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) & 0x00000000FFFFFFFFull;
+
+ 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) & 0x00000000FFFFFFFFull;
+
+ 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 (temp16 == 1)
+ 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 (temp8 == 0)
+ 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 (temp8 == 1) {
+ temp = 0x00;
+ set_DSPControl_overflow_flag(1, 20);
+ }
+ result = temp & 0x00FF;
+
+ return result;
+}
+/*** MIPS DSP internal functions end ***/
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions Jia Liu
@ 2012-03-27 15:33 ` Richard Henderson
2012-03-28 2:03 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 15:33 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> +ifeq ($(TARGET_BASE_ARCH), mips)
> +libobj-y += dsp_helper.o
> +endif
...
> +#include "dyngen-exec.h"
> +
> +/*** MIPS DSP internal functions begin ***/
> +static inline void set_DSPControl_overflow_flag(uint32_t flag, int position)
> +{
> + env->active_tc.DSPControl |= (target_ulong)flag << position;
> +}
In order to use dyngen-exec.h, and the global ENV variable,
you must also do
dsp_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
in the Makefile.target. If you had tested i386 host instead
of x86_64, you should have seen this failure.
Better, from the point of view of one working toward eliminating
dyngen-exec.h and these special calling conventions, is to actually
pass down env in the helper. E.g.
+/** DSP Arithmetic Sub-class insns **/
+uint32_t helper_addq_ph(CPUMIPSState *env, uint32_t rs, uint32_t rt)
+DEF_HELPER_FLAGS_3(addq_ph, 0, i32, env, i32, i32)
where mipsdsp_add_i16 and thence set_DSPControl_overflow_flag also
grow ENV parameters.
In addition, we can't use TCG_CALL_CONST | TCG_CALL_PURE on any
function that sets DSPControl, because that's the cpu_dspctrl tcg
variable.
You might get better performance out of TCG if you do *not* make
DSPControl a TCG variable, but instead perform explicit loads from
that slot in the few places that need it. That way you can at
least set TCG_CALL_CONST. (Though not TCG_CALL_PURE, because the
functions do have side effects.)
> + if (len == 2)
> + env->active_tc.DSPControl &= 0xFCFFFFFF;
> + else if (len == 4)
> + env->active_tc.DSPControl &= 0xF0FFFFFF;
Run all your patches through ./scripts/checkpatch.pl and fix the
errors that will report.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions
2012-03-27 15:33 ` Richard Henderson
@ 2012-03-28 2:03 ` Jia Liu
2012-03-29 11:16 ` Richard Henderson
0 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-28 2:03 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Tue, Mar 27, 2012 at 11:33 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> +ifeq ($(TARGET_BASE_ARCH), mips)
>> +libobj-y += dsp_helper.o
>> +endif
> ...
>
>> +#include "dyngen-exec.h"
>> +
>> +/*** MIPS DSP internal functions begin ***/
>> +static inline void set_DSPControl_overflow_flag(uint32_t flag, int position)
>> +{
>> + env->active_tc.DSPControl |= (target_ulong)flag << position;
>> +}
>
> In order to use dyngen-exec.h, and the global ENV variable,
> you must also do
>
> dsp_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
>
> in the Makefile.target. If you had tested i386 host instead
> of x86_64, you should have seen this failure.
>
> Better, from the point of view of one working toward eliminating
> dyngen-exec.h and these special calling conventions, is to actually
> pass down env in the helper. E.g.
>
Thanks, I'll add it.
> +/** DSP Arithmetic Sub-class insns **/
> +uint32_t helper_addq_ph(CPUMIPSState *env, uint32_t rs, uint32_t rt)
>
> +DEF_HELPER_FLAGS_3(addq_ph, 0, i32, env, i32, i32)
>
> where mipsdsp_add_i16 and thence set_DSPControl_overflow_flag also
> grow ENV parameters.
>
> In addition, we can't use TCG_CALL_CONST | TCG_CALL_PURE on any
> function that sets DSPControl, because that's the cpu_dspctrl tcg
> variable.
>
> You might get better performance out of TCG if you do *not* make
> DSPControl a TCG variable, but instead perform explicit loads from
> that slot in the few places that need it. That way you can at
> least set TCG_CALL_CONST. (Though not TCG_CALL_PURE, because the
> functions do have side effects.)
>
Thanks.
do you mean, I should write like this?
helper.h:
DEF_HELPER_FLAGS_3(addq_ph, 0, i32, env, i32, i32)
dsp_helper.c:
uint32_t helper_addq_ph(CPUMIPSState *env, uint32_t rs, uint32_t rt)
{}
Sorry I think I'm not turly understand your comment.
>> + if (len == 2)
>> + env->active_tc.DSPControl &= 0xFCFFFFFF;
>> + else if (len == 4)
>> + env->active_tc.DSPControl &= 0xF0FFFFFF;
>
> Run all your patches through ./scripts/checkpatch.pl and fix the
> errors that will report.
>
I've run ./scripts/checkpatch.pl, but I didn't get a ERR here...
It do have some ERR, but the all the other Macros write like that, so
I didn't have a idea about that.
>
> r~
Regards,
Jia.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions
2012-03-28 2:03 ` Jia Liu
@ 2012-03-29 11:16 ` Richard Henderson
0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2012-03-29 11:16 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/2012 10:03 PM, Jia Liu wrote:
> Thanks.
> do you mean, I should write like this?
> helper.h:
> DEF_HELPER_FLAGS_3(addq_ph, 0, i32, env, i32, i32)
>
> dsp_helper.c:
> uint32_t helper_addq_ph(CPUMIPSState *env, uint32_t rs, uint32_t rt)
> {}
Yes. Although the 0 flags argument probably warrants DEF_HELPER_3 instead.
Then, of course, you have to pass down the env parameter to all of the other
inline helpers that use it.
>>> + if (len == 2)
>>> + env->active_tc.DSPControl &= 0xFCFFFFFF;
>>> + else if (len == 4)
>>> + env->active_tc.DSPControl &= 0xF0FFFFFF;
>> Run all your patches through ./scripts/checkpatch.pl and fix the
>> errors that will report.
>>
> I've run ./scripts/checkpatch.pl, but I didn't get a ERR here...
You should have gotten an error about missing {.
if (len == 2) {
...
} else if (len == 4) {
...
}
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 02/12] Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 15:34 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 03/12] Add MIPS DSP Branch instruction Support Jia Liu
` (9 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
There are 4 accumulator registers (acc) used by MIPS ASE DSP instructions.
Each accumulator register is composed of by HIGH and LOW part. Use correct
acc value to index cpu_HI/cpu_LO rather than using a fix number (i.e. zero).
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/translate.c | 56 ++++++++++++++++++++++++++++------------------
1 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index a663b74..85a0998 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1972,6 +1972,7 @@ static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
{
const char *opn = "hilo";
+ unsigned int acc;
if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
/* Treat as NOP. */
@@ -1980,25 +1981,29 @@ static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
}
switch (opc) {
case OPC_MFHI:
- tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
+ acc = ((ctx->opcode) >> 21) & 0x03;
+ tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
opn = "mfhi";
break;
case OPC_MFLO:
- tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
+ acc = ((ctx->opcode) >> 21) & 0x03;
+ tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
opn = "mflo";
break;
case OPC_MTHI:
+ acc = ((ctx->opcode) >> 11) & 0x03;
if (reg != 0)
- tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
+ tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
else
- tcg_gen_movi_tl(cpu_HI[0], 0);
+ tcg_gen_movi_tl(cpu_HI[acc], 0);
opn = "mthi";
break;
case OPC_MTLO:
+ acc = ((ctx->opcode) >> 11) & 0x03;
if (reg != 0)
- tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
+ tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
else
- tcg_gen_movi_tl(cpu_LO[0], 0);
+ tcg_gen_movi_tl(cpu_LO[acc], 0);
opn = "mtlo";
break;
}
@@ -2011,6 +2016,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
const char *opn = "mul/div";
TCGv t0, t1;
+ unsigned int acc;
switch (opc) {
case OPC_DIV:
@@ -2073,6 +2079,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode >> 11) & 0x03;
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
@@ -2082,8 +2089,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "mult";
break;
@@ -2091,6 +2098,7 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode >> 11) & 0x03;
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
@@ -2102,8 +2110,8 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "multu";
break;
@@ -2150,19 +2158,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode >> 11) & 0x03;
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_add_i64(t2, t2, t3);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "madd";
break;
@@ -2170,21 +2179,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode) & 0x03;
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(t2, t0);
tcg_gen_extu_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_add_i64(t2, t2, t3);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "maddu";
break;
@@ -2192,19 +2202,20 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode >> 11) & 0x03;
tcg_gen_ext_tl_i64(t2, t0);
tcg_gen_ext_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_sub_i64(t2, t3, t2);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "msub";
break;
@@ -2212,21 +2223,22 @@ static void gen_muldiv (DisasContext *ctx, uint32_t opc,
{
TCGv_i64 t2 = tcg_temp_new_i64();
TCGv_i64 t3 = tcg_temp_new_i64();
+ acc = (ctx->opcode >> 11) & 0x03;
tcg_gen_ext32u_tl(t0, t0);
tcg_gen_ext32u_tl(t1, t1);
tcg_gen_extu_tl_i64(t2, t0);
tcg_gen_extu_tl_i64(t3, t1);
tcg_gen_mul_i64(t2, t2, t3);
- tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
+ tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
tcg_gen_sub_i64(t2, t3, t2);
tcg_temp_free_i64(t3);
tcg_gen_trunc_i64_tl(t0, t2);
tcg_gen_shri_i64(t2, t2, 32);
tcg_gen_trunc_i64_tl(t1, t2);
tcg_temp_free_i64(t2);
- tcg_gen_ext32s_tl(cpu_LO[0], t0);
- tcg_gen_ext32s_tl(cpu_HI[0], t1);
+ tcg_gen_ext32s_tl(cpu_LO[acc], t0);
+ tcg_gen_ext32s_tl(cpu_HI[acc], t1);
}
opn = "msubu";
break;
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 03/12] Add MIPS DSP Branch instruction Support
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 01/12] add MIPS DSP internal functions Jia Liu
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 02/12] Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 15:46 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 04/12] Add MIPS DSP Load instructions Support Jia Liu
` (8 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add MIPS DSP Branch instruction Support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/translate.c | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 85a0998..d2bd1ae 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -249,6 +249,11 @@ enum {
OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
};
+/* MIPS DSP REGIMM opcodes */
+enum {
+ OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
+};
+
/* Special2 opcodes */
#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
@@ -2755,6 +2760,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
}
btgt = ctx->pc + insn_bytes + offset;
break;
+ case OPC_BPOSGE32:
+ t0 = cpu_dspctrl;
+ tcg_gen_andi_i32(t0, t0, 0x3F);
+ bcond_compute = 1;
+ btgt = ctx->pc + insn_bytes + offset;
+ break;
case OPC_J:
case OPC_JAL:
case OPC_JALX:
@@ -2943,6 +2954,10 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
+ case OPC_BPOSGE32:
+ tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 31);
+ MIPS_DEBUG("bposge32 %s, " TARGET_FMT_lx, t0, btgt);
+ goto not_likely;
case OPC_BLTZALS:
case OPC_BLTZAL:
ctx->hflags |= (opc == OPC_BLTZALS
@@ -11180,8 +11195,6 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
*is_branch = 1;
break;
case BPOSGE64:
- case BPOSGE32:
- /* MIPS DSP: not implemented */
/* Fall through */
default:
MIPS_INVAL("pool32i");
@@ -12091,6 +12104,12 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
check_insn(env, ctx, ISA_MIPS32R2);
/* Treat as NOP. */
break;
+ case OPC_BPOSGE32: /* MIPS DSP branch */
+ {
+ gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
+ *is_branch = 1;
+ break;
+ }
default: /* Invalid */
MIPS_INVAL("regimm");
generate_exception(ctx, EXCP_RI);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 03/12] Add MIPS DSP Branch instruction Support
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 03/12] Add MIPS DSP Branch instruction Support Jia Liu
@ 2012-03-27 15:46 ` Richard Henderson
2012-03-28 1:27 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 15:46 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> Add MIPS DSP Branch instruction Support.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
> + case OPC_BPOSGE32:
> + tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 31);
Nit: It might be better to use TCG_COND_GE ... 32, since that's
both the name of the insn and its official documentation. Of
course that makes no difference to the correctness.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 03/12] Add MIPS DSP Branch instruction Support
2012-03-27 15:46 ` Richard Henderson
@ 2012-03-28 1:27 ` Jia Liu
0 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:27 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Tue, Mar 27, 2012 at 11:46 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> Add MIPS DSP Branch instruction Support.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>
> Reviewed-by: Richard Henderson <rth@twiddle.net>
>
>> + case OPC_BPOSGE32:
>> + tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 31);
>
> Nit: It might be better to use TCG_COND_GE ... 32, since that's
> both the name of the insn and its official documentation. Of
> course that makes no difference to the correctness.
>
Yeah, TCG_COND_GE looks better, I'll make it.
>
> r~
Regards,
Jia.
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 04/12] Add MIPS DSP Load instructions Support
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (2 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 03/12] Add MIPS DSP Branch instruction Support Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 15:49 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 05/12] Add helper functions for MIPS DSP Arithmetic instructions Jia Liu
` (7 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add MIPS DSP Load instructions Support.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/helper.h | 6 ++++
target-mips/op_helper.c | 37 ++++++++++++++++++++++++++
target-mips/translate.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 0 deletions(-)
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 76fb451..c32c835 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -297,4 +297,10 @@ DEF_HELPER_0(rdhwr_ccres, tl)
DEF_HELPER_1(pmon, void, int)
DEF_HELPER_0(wait, void)
+/*** MIPS DSP ***/
+/* DSP load */
+DEF_HELPER_2(lbux, tl, tl, int)
+DEF_HELPER_2(lhx, i32, i32, int)
+DEF_HELPER_2(lwx, i32, i32, int)
+
#include "def-helper.h"
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index ce01225..2864f33 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -3410,3 +3410,40 @@ 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 load */
+#define MIPSDSP_Q0 0x000000FF
+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;
+}
+#undef MIPSDSP_Q0
diff --git a/target-mips/translate.c b/target-mips/translate.c
index d2bd1ae..c698e78 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -317,6 +317,21 @@ enum {
OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
+
+ /* MIPS DSP */
+ OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
+ OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
+ /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
+ /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
+ OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
+ OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
+ OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
+ OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
+ OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
+ /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
+ /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
+ OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
};
/* BSHFL opcodes */
@@ -336,6 +351,14 @@ enum {
OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
};
+#define MASK_LX(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP load */
+enum {
+ OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
+ OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
+ OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
+};
+
/* Coprocessor 0 (rs field) */
#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
@@ -12062,6 +12085,50 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
check_insn(env, ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
+ case OPC_LX_DSP:
+ op2 = MASK_LX(ctx->opcode);
+ switch (op2) {
+ case OPC_LBUX:
+ {
+ TCGv addr = tcg_temp_new();
+ TCGv temp_mem = tcg_temp_new();
+
+ save_cpu_state(ctx, 1);
+ gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+ temp_mem = tcg_const_i32(ctx->mem_idx);
+ gen_helper_lbux(cpu_gpr[rd], addr, temp_mem);
+ tcg_temp_free_i32(addr);
+ tcg_temp_free_i32(temp_mem);
+ break;
+ }
+ case OPC_LHX:
+ {
+ TCGv addr = tcg_temp_new();
+ TCGv temp_mem = tcg_temp_new();
+
+ save_cpu_state(ctx, 1);
+ gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+ temp_mem = tcg_const_i32(ctx->mem_idx);
+ gen_helper_lhx(cpu_gpr[rd], addr, temp_mem);
+ tcg_temp_free_i32(addr);
+ tcg_temp_free_i32(temp_mem);
+ break;
+ }
+ case OPC_LWX:
+ {
+ TCGv addr = tcg_temp_new();
+ TCGv temp_mem = tcg_temp_new();
+
+ save_cpu_state(ctx, 1);
+ gen_op_addr_add(ctx, addr, cpu_gpr[rs], cpu_gpr[rt]);
+ temp_mem = tcg_const_i32(ctx->mem_idx);
+ gen_helper_lwx(cpu_gpr[rd], addr, temp_mem);
+ tcg_temp_free_i32(addr);
+ tcg_temp_free_i32(temp_mem);
+ break;
+ }
+ }
+ break;
#if defined(TARGET_MIPS64)
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 04/12] Add MIPS DSP Load instructions Support
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 04/12] Add MIPS DSP Load instructions Support Jia Liu
@ 2012-03-27 15:49 ` Richard Henderson
2012-03-28 1:46 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 15:49 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> +DEF_HELPER_2(lbux, tl, tl, int)
> +DEF_HELPER_2(lhx, i32, i32, int)
> +DEF_HELPER_2(lwx, i32, i32, int)
These should not be helpers. They are exactly the qemu_ld{8,16,32}u opcodes.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 04/12] Add MIPS DSP Load instructions Support
2012-03-27 15:49 ` Richard Henderson
@ 2012-03-28 1:46 ` Jia Liu
0 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:46 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Tue, Mar 27, 2012 at 11:49 PM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> +DEF_HELPER_2(lbux, tl, tl, int)
>> +DEF_HELPER_2(lhx, i32, i32, int)
>> +DEF_HELPER_2(lwx, i32, i32, int)
>
> These should not be helpers. They are exactly the qemu_ld{8,16,32}u opcodes.
>
Yes, thank you.
I'll fix it.
>
> r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 05/12] Add helper functions for MIPS DSP Arithmetic instructions
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (3 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 04/12] Add MIPS DSP Load instructions Support Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 16:03 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions Jia Liu
` (6 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add helper functions for MIPS DSP Arithmetic instructions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/dsp_helper.c | 875 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 52 +++
2 files changed, 927 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index d107eb0..2bed0fc 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -910,3 +910,878 @@ static inline uint8_t mipsdsp_satu8_sub(uint8_t a, uint8_t b)
return result;
}
/*** MIPS DSP internal functions end ***/
+
+#define MIPSDSP_LHI 0xFFFFFFFF00000000ull
+#define MIPSDSP_LLO 0x00000000FFFFFFFFull
+#define MIPSDSP_HI 0xFFFF0000
+#define MIPSDSP_LO 0x0000FFFF
+#define MIPSDSP_Q3 0xFF000000
+#define MIPSDSP_Q2 0x00FF0000
+#define MIPSDSP_Q1 0x0000FF00
+#define MIPSDSP_Q0 0x000000FF
+
+/** DSP Arithmetic Sub-class insns **/
+uint32_t helper_addq_ph(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_addq_s_ph(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_addq_s_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ rd = mipsdsp_sat_add_i32(rs, rt);
+ return rd;
+}
+
+uint32_t helper_addu_qb(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_addu_s_qb(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_adduh_qb(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_adduh_r_qb(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_addu_ph(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_addu_s_ph(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_addqh_ph(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_addqh_r_ph(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_addqh_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rshift1_add_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_addqh_r_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rrshift1_add_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_subq_ph(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_subq_s_ph(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_subq_s_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_sat32_sub(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_subu_qb(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_subu_s_qb(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;
+}
+
+uint32_t helper_subuh_qb(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_subuh_r_qb(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;
+}
+
+uint32_t helper_subu_ph(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_subu_s_ph(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_subqh_ph(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_subqh_r_ph(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_subqh_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rshift1_sub_q32(rs, rt);
+
+ return rd;
+}
+
+uint32_t helper_subqh_r_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rrshift1_sub_q32(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 & 0x0100000000ull) >> 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_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 (rs == 0x00000000)
+ rd = (uint32_t)lastindex;
+ else
+ rd = rs - decr;
+
+ return rd;
+}
+
+uint32_t helper_raddu_w_qb(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_absq_s_qb(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_absq_s_ph(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_absq_s_w(uint32_t rt)
+{
+ uint32_t rd;
+ int32_t temp;
+
+ temp = rt;
+ rd = mipsdsp_sat_abs_u32(temp);
+
+ return rd;
+}
+
+uint32_t helper_precr_qb_ph(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_precrq_qb_ph(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_precr_sra_ph_w(int sa, uint32_t rs, uint32_t rt)
+{
+ uint16_t tempB, tempA;
+
+ if (sa == 0) {
+ 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_precr_sra_r_ph_w(int sa, uint32_t rs, uint32_t rt)
+{
+ uint64_t tempB, tempA;
+
+ if (sa == 0) {
+ 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_precrq_ph_w(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_precrq_rs_ph_w(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_precrqu_s_qb_ph(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_preceq_w_phl(uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = rt & MIPSDSP_HI;
+
+ return rd;
+}
+
+uint32_t helper_preceq_w_phr(uint32_t rt)
+{
+ uint16_t rtl;
+ uint32_t rd;
+
+ rtl = rt & MIPSDSP_LO;
+ rd = rtl << 16;
+
+ return rd;
+}
+
+uint32_t helper_precequ_ph_qbl(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_precequ_ph_qbr(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_precequ_ph_qbla(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_precequ_ph_qbra(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_preceu_ph_qbl(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_preceu_ph_qbr(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_preceu_ph_qbla(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_preceu_ph_qbra(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;
+}
+
+
+#undef MIPSDSP_LHI
+#undef MIPSDSP_LLO
+#undef MIPSDSP_HI
+#undef MIPSDSP_LO
+#undef MIPSDSP_Q0
+#undef MIPSDSP_Q1
+#undef MIPSDSP_Q2
+#undef MIPSDSP_Q3
diff --git a/target-mips/helper.h b/target-mips/helper.h
index c32c835..40e682b 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -303,4 +303,56 @@ DEF_HELPER_2(lbux, tl, tl, int)
DEF_HELPER_2(lhx, i32, i32, int)
DEF_HELPER_2(lwx, i32, i32, int)
+/* DSP Arithmetic Sub-class insns */
+DEF_HELPER_FLAGS_2(addq_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addq_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addu_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addu_s_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addu_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addu_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subq_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subq_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subu_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subu_s_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subu_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subu_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addsc, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(addwc, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(modsub, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(absq_s_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(absq_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(absq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32, i32)
+DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32, i32)
+DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(precrq_rs_ph_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(precrqu_s_qb_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_1(preceq_w_phl, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(preceq_w_phr, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(precequ_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(precequ_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(precequ_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(precequ_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(preceu_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+
#include "def-helper.h"
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 05/12] Add helper functions for MIPS DSP Arithmetic instructions
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 05/12] Add helper functions for MIPS DSP Arithmetic instructions Jia Liu
@ 2012-03-27 16:03 ` Richard Henderson
2012-03-28 1:45 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 16:03 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> +DEF_HELPER_FLAGS_2(addq_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
> +DEF_HELPER_FLAGS_2(addq_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
> +DEF_HELPER_FLAGS_2(addq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
> +DEF_HELPER_FLAGS_2(addu_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
As mentioned in the first mail, those of these functions that can set
bits in DSPControl cannot be TCG_CALL_CONST | TCG_CALL_PURE. There are
still plenty of these that *are* pure functions though.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 05/12] Add helper functions for MIPS DSP Arithmetic instructions
2012-03-27 16:03 ` Richard Henderson
@ 2012-03-28 1:45 ` Jia Liu
0 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:45 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Wed, Mar 28, 2012 at 12:03 AM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> +DEF_HELPER_FLAGS_2(addq_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
>> +DEF_HELPER_FLAGS_2(addq_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
>> +DEF_HELPER_FLAGS_2(addq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
>> +DEF_HELPER_FLAGS_2(addu_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
>
> As mentioned in the first mail, those of these functions that can set
> bits in DSPControl cannot be TCG_CALL_CONST | TCG_CALL_PURE. There are
> still plenty of these that *are* pure functions though.
>
Thanks, I'll check it.
>
> r~
Regards,
Jia.
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (4 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 05/12] Add helper functions for MIPS DSP Arithmetic instructions Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 16:11 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 07/12] Add helper functions for MIPS DSP Multiply instructions Jia Liu
` (5 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add helper functions for MIPS DSP GPR-Based Shift instructions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/dsp_helper.c | 411 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 24 +++
2 files changed, 435 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 2bed0fc..d73061f 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -1776,6 +1776,417 @@ uint32_t helper_preceu_ph_qbra(uint32_t rt)
return rd;
}
+/** DSP GPR-Based Shift Sub-class insns **/
+uint32_t helper_shll_qb(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_shllv_qb(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_shll_ph(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_shllv_ph(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_shll_s_ph(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_shllv_s_ph(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_shll_s_w(int sa, uint32_t rt)
+{
+ uint32_t temp, rd;
+
+ temp = mipsdsp_sat32_lshift(rt, sa);
+ rd = temp;
+
+ return rd;
+}
+
+uint32_t helper_shllv_s_w(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_shrl_qb(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_shrlv_qb(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_shrl_ph(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_shrlv_ph(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_shra_qb(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_shra_r_qb(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 (sa == 0) {
+ 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_shrav_qb(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 (rs2_0 == 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_shrav_r_qb(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 (rs2_0 == 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_shra_ph(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_shrav_ph(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_shra_r_ph(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_shrav_r_ph(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_shra_r_w(int sa, uint32_t rt)
+{
+ uint32_t rd;
+
+ rd = mipsdsp_rnd32_rashift(rt, sa);
+
+ return rd;
+}
+
+uint32_t helper_shrav_r_w(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;
+}
+
#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 40e682b..191be3a 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -355,4 +355,28 @@ DEF_HELPER_FLAGS_1(preceu_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
DEF_HELPER_FLAGS_1(preceu_ph_qbla, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
DEF_HELPER_FLAGS_1(preceu_ph_qbra, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+/* DSP GPR-Based Shift Sub-class insns */
+DEF_HELPER_FLAGS_2(shll_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shllv_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shll_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shllv_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shll_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shllv_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shll_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shllv_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shrl_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shrlv_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shrlv_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shra_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shrav_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shrav_r_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shra_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shrav_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shra_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shrav_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
+DEF_HELPER_FLAGS_2(shrav_r_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+
#include "def-helper.h"
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions Jia Liu
@ 2012-03-27 16:11 ` Richard Henderson
2012-03-28 1:43 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 16:11 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> +DEF_HELPER_FLAGS_2(shll_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
Likewise, some of these are not pure|const...
> +DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
... and some are.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions
2012-03-27 16:11 ` Richard Henderson
@ 2012-03-28 1:43 ` Jia Liu
2012-03-29 13:09 ` Richard Henderson
0 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:43 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Wed, Mar 28, 2012 at 12:11 AM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> +DEF_HELPER_FLAGS_2(shll_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
>
It should be DEF_HELPER_2(shll_qb, i32, int, i32). Is it?
Sorry I'm not sure about it.
> Likewise, some of these are not pure|const...
>
>> +DEF_HELPER_FLAGS_2(shra_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
>
> ... and some are.
>
>
> r~
Regards,
Jia.
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions
2012-03-28 1:43 ` Jia Liu
@ 2012-03-29 13:09 ` Richard Henderson
0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2012-03-29 13:09 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/2012 09:43 PM, Jia Liu wrote:
> On Wed, Mar 28, 2012 at 12:11 AM, Richard Henderson <rth@twiddle.net> wrote:
>> On 03/27/12 02:24, Jia Liu wrote:
>>> +DEF_HELPER_FLAGS_2(shll_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
>>
>
> It should be DEF_HELPER_2(shll_qb, i32, int, i32). Is it?
> Sorry I'm not sure about it.
Exactly.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 07/12] Add helper functions for MIPS DSP Multiply instructions
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (5 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 06/12] Add helper functions for MIPS DSP GPR-Based Shift instructions Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 08/12] Add helper functions for MIPS DSP Bit/Manipulation instructions Jia Liu
` (4 subsequent siblings)
11 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add helper functions for MIPS DSP Multiply instructions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/dsp_helper.c | 724 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 34 +++
2 files changed, 758 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index d73061f..4692cc4 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -2187,6 +2187,730 @@ uint32_t helper_shrav_r_w(uint32_t rs, uint32_t rt)
return rd;
}
+/** DSP Multiply Sub-class insns **/
+uint32_t helper_muleu_s_ph_qbl(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_muleu_s_ph_qbr(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_mulq_rs_ph(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;
+}
+
+uint32_t helper_muleq_s_w_phl(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_muleq_s_w_phr(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;
+}
+
+void helper_dpau_h_qbl(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_dpau_h_qbr(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_dpsu_h_qbl(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_dpsu_h_qbr(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_dpa_w_ph(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_dpax_w_ph(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_dpaq_s_w_ph(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_dpaqx_s_w_ph(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_dpaqx_sa_w_ph(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 ((tempC63 == 0) && (tempC62_31 == 0xFFFFFFFF)) {
+ 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_dps_w_ph(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_dpsx_w_ph(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;
+}
+
+void helper_dpsq_s_w_ph(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_dpsqx_s_w_ph(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_dpsqx_sa_w_ph(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 ((tempC63 == 0) && (tempC62_31 != 0)) {
+ tempC = 0x7FFFFFFF;
+ set_DSPControl_overflow_flag(1, 16 + ac);
+ }
+
+ if ((tempC63 == 1) && (tempC62_31 != 0xFFFFFFFF)) {
+ tempC = 0xFFFFFFFF80000000ull;
+ 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_mulsaq_s_w_ph(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;
+}
+
+void helper_dpaq_sa_l_w(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 (temp64 == 1)
+ temp = 0x8000000000000000ull;
+ else
+ temp = 0x7FFFFFFFFFFFFFFFull;
+
+ 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_dpsq_sa_l_w(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 = 0x8000000000000000ull;
+ else
+ temp = 0x7FFFFFFFFFFFFFFFull;
+ 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_maq_s_w_phl(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_maq_s_w_phr(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_maq_sa_w_phl(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_maq_sa_w_phr(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_mul_ph(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_mul_s_ph(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_mulq_s_ph(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_mulq_s_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int32_t tempI;
+ int64_t tempL;
+
+ if ((rs == 0x80000000) && (rt == 0x80000000)) {
+ tempL = 0x7FFFFFFF00000000ull;
+ set_DSPControl_overflow_flag(1, 21);
+ } else {
+ tempL = ((int64_t)rs * (int64_t)rt) << 1;
+ }
+ tempI = (tempL & MIPSDSP_LHI) >> 32;
+ rd = tempI;
+
+ return rd;
+}
+
+uint32_t helper_mulq_rs_w(uint32_t rs, uint32_t rt)
+{
+ uint32_t rd;
+ int32_t tempI;
+ int64_t tempL;
+
+ if ((rs == 0x80000000) && (rt == 0x80000000)) {
+ tempL = 0x7FFFFFFF00000000ull;
+ 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;
+}
+
+void helper_mulsa_w_ph(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;
+}
#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 191be3a..f3fffa1 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -379,4 +379,38 @@ DEF_HELPER_FLAGS_2(shrav_r_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
DEF_HELPER_FLAGS_2(shra_r_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32)
DEF_HELPER_FLAGS_2(shrav_r_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+/* DSP Multiply Sub-class insns */
+DEF_HELPER_FLAGS_2(muleu_s_ph_qbl, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(muleu_s_ph_qbr, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(mulq_rs_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(muleq_s_w_phl, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(muleq_s_w_phr, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_3(dpau_h_qbl, void, int, i32, i32)
+DEF_HELPER_3(dpau_h_qbr, void, int, i32, i32)
+DEF_HELPER_3(dpsu_h_qbl, void, int, i32, i32)
+DEF_HELPER_3(dpsu_h_qbr, void, int, i32, i32)
+DEF_HELPER_3(dpa_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpax_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpaq_s_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpaqx_s_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpaqx_sa_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dps_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpsx_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpsq_s_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpsqx_s_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpsqx_sa_w_ph, void, int, i32, i32)
+DEF_HELPER_3(mulsaq_s_w_ph, void, int, i32, i32)
+DEF_HELPER_3(dpaq_sa_l_w, void, int, i32, i32)
+DEF_HELPER_3(dpsq_sa_l_w, void, int, i32, i32)
+DEF_HELPER_3(maq_s_w_phl, void, int, i32, i32)
+DEF_HELPER_3(maq_s_w_phr, void, int, i32, i32)
+DEF_HELPER_3(maq_sa_w_phl, void, int, i32, i32)
+DEF_HELPER_3(maq_sa_w_phr, void, int, i32, i32)
+DEF_HELPER_FLAGS_2(mul_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(mul_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(mulq_s_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(mulq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(mulq_rs_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_3(mulsa_w_ph, void, int, i32, i32)
+
#include "def-helper.h"
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 08/12] Add helper functions for MIPS DSP Bit/Manipulation instructions
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (6 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 07/12] Add helper functions for MIPS DSP Multiply instructions Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 16:23 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 09/12] Add helper functions for MIPS DSP Compare-Pick instructions Jia Liu
` (3 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add helper functions for MIPS DSP Bit/Manipulation instructions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/dsp_helper.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 8 ++++
2 files changed, 93 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 4692cc4..cd9764f 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -2912,6 +2912,91 @@ void helper_mulsa_w_ph(int ac, uint32_t rs, uint32_t rt)
env->active_tc.LO[ac] = acc & MIPSDSP_LLO;
}
+/** DSP Bit/Manipulation Sub-class insns **/
+uint32_t helper_bitrev(uint32_t rt)
+{
+ int32_t temp;
+ uint32_t rd;
+
+ temp = rt & MIPSDSP_LO;
+ rd = temp;
+
+ return rd;
+}
+
+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;
+}
+
+uint32_t helper_repl_qb(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_replv_qb(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;
+}
+
+uint32_t helper_repl_ph(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_replv_ph(uint32_t rt)
+{
+ uint16_t temp;
+ uint32_t rd;
+
+ temp = rt & MIPSDSP_LO;
+ rd = ((uint32_t)temp << 16) | (uint32_t)temp;
+
+ return rd;
+}
+
+
#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
#undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index f3fffa1..c45c173 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -413,4 +413,12 @@ DEF_HELPER_FLAGS_2(mulq_s_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
DEF_HELPER_FLAGS_2(mulq_rs_w, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
DEF_HELPER_3(mulsa_w_ph, void, int, i32, i32)
+/* DSP Bit/Manipulation Sub-class insns */
+DEF_HELPER_FLAGS_1(bitrev, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_3(insv, void, int, i32, i32)
+DEF_HELPER_FLAGS_1(repl_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(replv_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(repl_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+DEF_HELPER_FLAGS_1(replv_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+
#include "def-helper.h"
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 08/12] Add helper functions for MIPS DSP Bit/Manipulation instructions
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 08/12] Add helper functions for MIPS DSP Bit/Manipulation instructions Jia Liu
@ 2012-03-27 16:23 ` Richard Henderson
2012-03-28 1:47 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 16:23 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> +uint32_t helper_bitrev(uint32_t rt)
> +{
> + int32_t temp;
> + uint32_t rd;
> +
> + temp = rt & MIPSDSP_LO;
> + rd = temp;
> +
> + return rd;
> +}
Forgot to actually reverse the bits.
> +uint32_t helper_repl_qb(uint32_t imm)
...
> +uint32_t helper_repl_ph(uint32_t imm)
Should not be helpers. The full 32-bit immediate can be
computed directly in the translator.
> +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;
> +}
Err... why does this modify the env directly, rather than
return a value? "return rt" would seem to be the correct
way to leave the value of reg_rt unchanged...
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 08/12] Add helper functions for MIPS DSP Bit/Manipulation instructions
2012-03-27 16:23 ` Richard Henderson
@ 2012-03-28 1:47 ` Jia Liu
0 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:47 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Wed, Mar 28, 2012 at 12:23 AM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> +uint32_t helper_bitrev(uint32_t rt)
>> +{
>> + int32_t temp;
>> + uint32_t rd;
>> +
>> + temp = rt & MIPSDSP_LO;
>> + rd = temp;
>> +
>> + return rd;
>> +}
>
> Forgot to actually reverse the bits.
>
>> +uint32_t helper_repl_qb(uint32_t imm)
> ...
>> +uint32_t helper_repl_ph(uint32_t imm)
>
> Should not be helpers. The full 32-bit immediate can be
> computed directly in the translator.
>
>> +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;
>> +}
>
> Err... why does this modify the env directly, rather than
> return a value? "return rt" would seem to be the correct
> way to leave the value of reg_rt unchanged...
>
>
> r~
Yes, thank you Richard.
I'll fix them all.
Regards,
Jia.
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 09/12] Add helper functions for MIPS DSP Compare-Pick instructions
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (7 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 08/12] Add helper functions for MIPS DSP Bit/Manipulation instructions Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 17:42 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 10/12] Add helper functions for MIPS DSP Accumulator and DSPControl Access instrutions helpers Jia Liu
` (2 subsequent siblings)
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add helper functions for MIPS DSP Compare-Pick instructions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/dsp_helper.c | 496 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 21 ++
2 files changed, 517 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index cd9764f..14c460c 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -2996,6 +2996,502 @@ uint32_t helper_replv_ph(uint32_t rt)
return rd;
}
+/** DSP Compare-Pick Sub-class insns **/
+void helper_cmpu_eq_qb(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_cmpu_lt_qb(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_cmpu_le_qb(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);
+}
+
+uint32_t helper_cmpgdu_eq_qb(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_cmpgdu_lt_qb(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_cmpgdu_le_qb(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_cmpgu_eq_qb(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_cmpgu_lt_qb(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_cmpgu_le_qb(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_cmp_eq_ph(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_cmp_lt_ph(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_cmp_le_ph(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_pick_qb(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_pick_ph(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_append(uint32_t rt, uint32_t rs, int sa)
+{
+ int len;
+ uint32_t temp;
+
+ len = sa & 0x1F;
+
+ if (len == 0)
+ temp = rt;
+ else {
+ temp = (rt << len) | (rs & (((uint32_t)0x01 << len) - 1));
+ }
+ rt = temp;
+
+ return temp;
+}
+
+uint32_t helper_prepend(int sa, uint32_t rs, uint32_t rt)
+{
+ uint32_t temp;
+
+ if (sa == 0)
+ temp = rt;
+ else
+ temp = (rs << (32 - sa)) | rt >> sa;
+
+ rt = temp;
+
+ return rt;
+}
+
+uint32_t helper_balign(uint32_t rt, uint32_t rs, uint32_t bp)
+{
+ uint32_t temp;
+ bp = bp & 0x03;
+
+ if (bp == 0 || bp == 2)
+ return rt;
+ else
+ temp = (rt << (8 * bp)) | (rs >> (8 * (4 - bp)));
+ rt = temp;
+
+ return rt;
+}
+
+uint32_t helper_packrl_ph(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;
+}
#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
diff --git a/target-mips/helper.h b/target-mips/helper.h
index c45c173..36d6c19 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -421,4 +421,25 @@ DEF_HELPER_FLAGS_1(replv_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
DEF_HELPER_FLAGS_1(repl_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
DEF_HELPER_FLAGS_1(replv_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32)
+/* DSP Compare-Pick Sub-class insns */
+DEF_HELPER_2(cmpu_eq_qb, void, i32, i32)
+DEF_HELPER_2(cmpu_lt_qb, void, i32, i32)
+DEF_HELPER_2(cmpu_le_qb, void, i32, i32)
+DEF_HELPER_FLAGS_2(cmpgdu_eq_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cmpgdu_lt_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cmpgdu_le_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cmpgu_eq_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cmpgu_lt_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_FLAGS_2(cmpgu_le_qb, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+DEF_HELPER_2(cmp_eq_ph, void, i32, i32)
+DEF_HELPER_2(cmp_lt_ph, void, i32, i32)
+DEF_HELPER_2(cmp_le_ph, void, i32, i32)
+DEF_HELPER_2(pick_qb, i32, i32, i32)
+DEF_HELPER_2(pick_ph, i32, i32, i32)
+DEF_HELPER_FLAGS_3(append, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32, int)
+DEF_HELPER_FLAGS_3(prepend, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32, i32)
+DEF_HELPER_FLAGS_3(balign, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+
+
#include "def-helper.h"
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 09/12] Add helper functions for MIPS DSP Compare-Pick instructions
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 09/12] Add helper functions for MIPS DSP Compare-Pick instructions Jia Liu
@ 2012-03-27 17:42 ` Richard Henderson
2012-03-28 1:52 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 17:42 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> + uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
> + uint32_t flag;
...
> + if (rs3 == rt3)
> + cc3 = 1;
Clearer as "cc3 = (rs3 == rt3);", etc.
I begin to wonder if it wouldn't be better to model the DSPControl
word as individual variables of their respective fields. That way
you don't need to involve ENV so much.
E.g.
Assume cpu_dspcc is a TCGv_i32 variable containing 4 bits.
case CMPGU_COND_QB:
gen_helper_cmpdu_cond_qb(cpu_gr[rd], cpu_gr[rs], cpu_gr[rt]);
break;
case CMPGDU_COND_QB:
gen_helper_cmpdu_cond_qb(cpu_dspcc, cpu_gr[rs], cpu_gr[rt]);
tcg_gen_mov(cpu_gr[rd], cpu_dspcc);
break;
No need for two separate helpers. Even if you don't decide to split
the field, you probably don't want to duplicate so much code in the
helpers file.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 09/12] Add helper functions for MIPS DSP Compare-Pick instructions
2012-03-27 17:42 ` Richard Henderson
@ 2012-03-28 1:52 ` Jia Liu
0 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:52 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Wed, Mar 28, 2012 at 1:42 AM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> + uint32_t cc3 = 0, cc2 = 0, cc1 = 0, cc0 = 0;
>> + uint32_t flag;
> ...
>> + if (rs3 == rt3)
>> + cc3 = 1;
>
> Clearer as "cc3 = (rs3 == rt3);", etc.
>
I'll try to make code more clearer.
> I begin to wonder if it wouldn't be better to model the DSPControl
> word as individual variables of their respective fields. That way
> you don't need to involve ENV so much.
>
> E.g.
>
> Assume cpu_dspcc is a TCGv_i32 variable containing 4 bits.
>
> case CMPGU_COND_QB:
> gen_helper_cmpdu_cond_qb(cpu_gr[rd], cpu_gr[rs], cpu_gr[rt]);
> break;
> case CMPGDU_COND_QB:
> gen_helper_cmpdu_cond_qb(cpu_dspcc, cpu_gr[rs], cpu_gr[rt]);
> tcg_gen_mov(cpu_gr[rd], cpu_dspcc);
> break;
>
> No need for two separate helpers. Even if you don't decide to split
> the field, you probably don't want to duplicate so much code in the
> helpers file.
>
Thanks, I'll combine them.
>
> r~
Regards,
Jia.
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 10/12] Add helper functions for MIPS DSP Accumulator and DSPControl Access instrutions helpers
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (8 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 09/12] Add helper functions for MIPS DSP Compare-Pick instructions Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c Jia Liu
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 12/12] add MIPS DSP testcases Jia Liu
11 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Add helper functions for MIPS DSP Accumulator and DSPControl Access instrutions.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/dsp_helper.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++
target-mips/helper.h | 18 ++
2 files changed, 452 insertions(+), 0 deletions(-)
diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
index 14c460c..8973cb0 100644
--- a/target-mips/dsp_helper.c
+++ b/target-mips/dsp_helper.c
@@ -3493,6 +3493,440 @@ uint32_t helper_packrl_ph(uint32_t rs, uint32_t rt)
return rd;
}
+/** DSP Accumulator and DSPControl Access Sub-class insns **/
+uint32_t helper_extr_w(int ac, int shift)
+{
+ 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;
+
+ tempDL[0] += 1;
+ if (tempDL[0] == 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);
+
+ return tempI;
+}
+
+uint32_t helper_extr_r_w(int ac, int shift)
+{
+ 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;
+
+ return tempI;
+}
+
+uint32_t helper_extr_rs_w(int ac, int shift)
+{
+ 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 (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)) {
+ temp64 = tempDL[1];
+ if (temp64 == 0)
+ tempI = 0x7FFFFFFF;
+ else
+ tempI = 0x80000000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+
+ return tempI;
+}
+
+uint32_t helper_extr_s_h(int ac, int shift)
+{
+ int64_t temp;
+ uint32_t tempI;
+
+ temp = mipsdsp_rashift_short_acc(ac, shift);
+ if (temp > 0x0000000000007FFFull) {
+ temp &= MIPSDSP_LHI;
+ temp |= 0x00007FFF;
+ set_DSPControl_overflow_flag(1, 23);
+ } else if (temp < 0xFFFFFFFFFFFF8000ull) {
+ temp &= MIPSDSP_LHI;
+ temp |= 0xFFFF8000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+
+ tempI = temp & 0xFFFFFFFF;
+ return tempI;
+}
+
+uint32_t helper_extrv_s_h(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 > 0x000000000007FFFull) {
+ tempI = 0x00007FFF;
+ set_DSPControl_overflow_flag(1, 23);
+ } else if (tempL < 0xFFFFFFFFFFF8000ull) {
+ tempI = 0xFFFF8000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+ rd = tempI;
+
+ return rd;
+}
+
+uint32_t helper_extrv_w(int ac, uint32_t rs)
+{
+ 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;
+
+ 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);
+
+ return tempI;
+}
+
+uint32_t helper_extrv_r_w(int ac, uint32_t rs)
+{
+ 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;
+
+ return tempI;
+}
+
+uint32_t helper_extrv_rs_w(int ac, uint32_t rs)
+{
+ 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 (tempDL[1] == 0)
+ tempI = 0x7FFFFFFF;
+ else
+ tempI = 0x80000000;
+ set_DSPControl_overflow_flag(1, 23);
+ }
+
+ return tempI;
+}
+
+uint32_t helper_extp(int ac, int size)
+{
+ int32_t start_pos;
+ uint32_t temp;
+ uint64_t acc;
+
+ temp = 0;
+ start_pos = get_DSPControl_pos();
+ if (start_pos - (size + 1) >= -1) {
+ 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);
+ set_DSPControl_efi(0);
+ } else {
+ set_DSPControl_efi(1);
+ }
+
+ return temp;
+}
+
+uint32_t helper_extpv(int ac, uint32_t rs)
+{
+ int32_t start_pos, size;
+ uint32_t temp;
+ uint64_t acc;
+
+ temp = 0;
+ start_pos = get_DSPControl_pos();
+ size = rs & 0x1F;
+
+ if (start_pos - (size + 1) >= -1) {
+ 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);
+ set_DSPControl_efi(0);
+ } else
+ set_DSPControl_efi(1);
+
+ return temp;
+}
+
+uint32_t helper_extpdp(int ac, int size)
+{
+ int32_t start_pos;
+ uint32_t temp;
+ uint64_t acc;
+
+ temp = 0;
+ start_pos = get_DSPControl_pos();
+ if (start_pos - (size + 1) >= -1) {
+ 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);
+
+ set_DSPControl_pos(start_pos - (size + 1));
+ set_DSPControl_efi(0);
+ } else
+ set_DSPControl_efi(1);
+
+ return temp;
+}
+
+uint32_t helper_extpdpv(int ac, uint32_t rs)
+{
+ int32_t start_pos, size;
+ uint32_t temp;
+ uint64_t acc;
+
+ temp = 0;
+ start_pos = get_DSPControl_pos();
+ size = rs & 0x1F;
+
+ if (start_pos - (size + 1) >= -1) {
+ 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);
+ set_DSPControl_pos(start_pos - (size + 1));
+ set_DSPControl_efi(0);
+ } else
+ set_DSPControl_efi(1);
+
+ return temp;
+}
+
+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 (shift == 0)
+ temp = acc;
+ else {
+ if (sign == 0)
+ 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 (rs5_0 == 0)
+ temp = acc;
+ else {
+ if (sign == 0)
+ 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;
+}
+
+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);
+}
+
+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 (mask[0] == 1) {
+ overwrite &= 0xFFFFFFC0;
+ newbits &= 0xFFFFFFC0;
+ newbits |= 0x0000003F & rs;
+ }
+
+ if (mask[1] == 1) {
+ overwrite &= 0xFFFFE07F;
+ newbits &= 0xFFFFE07F;
+ newbits |= 0x00001F80 & rs;
+ }
+
+ if (mask[2] == 1) {
+ overwrite &= 0xFFFFDFFF;
+ newbits &= 0xFFFFDFFF;
+ newbits |= 0x00002000 & rs;
+ }
+
+ if (mask[3] == 1) {
+ overwrite &= 0xFF00FFFF;
+ newbits &= 0xFF00FFFF;
+ newbits |= 0x00FF0000 & rs;
+ }
+
+ if (mask[4] == 1) {
+ overwrite &= 0x00FFFFFF;
+ newbits &= 0x00FFFFFF;
+ newbits |= 0xFF000000 & rs;
+ }
+
+ if (mask[5] == 1) {
+ overwrite &= 0xFFFFBFFF;
+ newbits &= 0xFFFFBFFF;
+ newbits |= 0x00004000 & rs;
+ }
+
+ dsp = dsp & overwrite;
+ dsp = dsp | newbits;
+ env->active_tc.DSPControl = dsp;
+}
+
+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 (mask[0] == 1)
+ temp |= dsp & 0x3F;
+
+ if (mask[1] == 1)
+ temp |= dsp & 0x1F80;
+
+ if (mask[2] == 1)
+ temp |= dsp & 0x2000;
+
+ if (mask[3] == 1)
+ temp |= dsp & 0x00FF0000;
+
+ if (mask[4] == 1)
+ temp |= dsp & 0xFF000000;
+
+ if (mask[5] == 1)
+ temp |= dsp & 0x4000;
+
+ rd = temp;
+
+ return rd;
+}
+
#undef MIPSDSP_LHI
#undef MIPSDSP_LLO
#undef MIPSDSP_HI
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 36d6c19..8fab999 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -441,5 +441,23 @@ DEF_HELPER_FLAGS_3(prepend, TCG_CALL_CONST | TCG_CALL_PURE, i32, int, i32, i32)
DEF_HELPER_FLAGS_3(balign, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32, i32)
DEF_HELPER_FLAGS_2(packrl_ph, TCG_CALL_CONST | TCG_CALL_PURE, i32, i32, i32)
+/* DSP Accumulator and DSPControl Access Sub-class insns */
+DEF_HELPER_2(extr_w, i32, int, int)
+DEF_HELPER_2(extr_r_w, i32, int, int)
+DEF_HELPER_2(extr_rs_w, i32, int, int)
+DEF_HELPER_2(extr_s_h, i32, int, int)
+DEF_HELPER_2(extrv_s_h, i32, int, i32)
+DEF_HELPER_2(extrv_w, i32, int, i32)
+DEF_HELPER_2(extrv_r_w, i32, int, i32)
+DEF_HELPER_2(extrv_rs_w, i32, int, i32)
+DEF_HELPER_2(extp, i32, int, int)
+DEF_HELPER_2(extpv, i32, int, i32)
+DEF_HELPER_2(extpdp, i32, int, int)
+DEF_HELPER_2(extpdpv, i32, int, i32)
+DEF_HELPER_2(shilo, void, int, int)
+DEF_HELPER_2(shilov, void, int, i32)
+DEF_HELPER_2(mthlip, void, int, i32)
+DEF_HELPER_2(wrdsp, void, i32, int)
+DEF_HELPER_1(rddsp, i32, i32)
#include "def-helper.h"
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (9 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 10/12] Add helper functions for MIPS DSP Accumulator and DSPControl Access instrutions helpers Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
2012-03-27 17:48 ` Richard Henderson
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 12/12] add MIPS DSP testcases Jia Liu
11 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
Handle MIPS DSP instructions in target-mips/translate.c.
Signed-off-by: Jia Liu <proljc@gmail.com>
---
target-mips/translate.c | 943 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 943 insertions(+), 0 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c698e78..0b31b46 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -359,6 +359,224 @@ enum {
OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
};
+#define MASK_ABSQ_S_PH(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
+ OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
+};
+
+#define MASK_ADDU_QB(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
+ OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
+ OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
+ OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
+ OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
+ OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
+ OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
+ OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
+};
+
+#define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
+#define MASK_ADDUH_QB(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSPR2 */
+enum {
+ OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
+ OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
+ OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
+};
+
+#define OPC_MUL_PH_DSP OPC_ADDUH_QB_DSP
+/* #define MASK_MUL_PH(op) MASK_SPECIAL3(op) | (op & (0x1F << 6)) */
+/* MIPS DSPR2 */
+enum {
+ OPC_MULQ_RS_W = (0x17 << 6) | OPC_MUL_PH_DSP,
+ OPC_MULQ_S_W = (0x16 << 6) | OPC_MUL_PH_DSP,
+};
+
+#define MASK_APPEND(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSPR2 */
+enum {
+ OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
+ OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
+ OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
+};
+
+#define MASK_CMPU_EQ_QB(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
+ OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
+};
+
+#define MASK_DPA_W_PH(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
+};
+
+/* MIPS DSPR2 */
+enum{
+ OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
+ OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
+ OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
+};
+
+#define MASK_EXTR_W(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
+ OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
+ OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
+ OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
+ OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
+ OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
+ OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
+};
+
+#define MASK_INSV(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
+};
+
+
+#define MASK_SHLL_QB(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
+/* MIPS DSP */
+enum {
+ OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
+};
+
+/* MIPS DSPR2 */
+enum {
+ OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
+ OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
+};
+
/* Coprocessor 0 (rs field) */
#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
@@ -12081,10 +12299,735 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
break;
case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
+ /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
+ * the same mask and op1. */
+ if (op1 == OPC_MULT_G_2E) {
+ int is_mult_g_2e = 0;
+ op2 = MASK_ADDUH_QB(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSPR2 */
+ case OPC_ADDQH_PH:
+ gen_helper_addqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQH_R_PH:
+ gen_helper_addqh_r_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQH_W:
+ gen_helper_addqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQH_R_W:
+ gen_helper_addqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDUH_QB:
+ gen_helper_adduh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDUH_R_QB:
+ gen_helper_adduh_r_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MUL_PH:
+ gen_helper_mul_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MUL_S_PH:
+ gen_helper_mul_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_PH:
+ gen_helper_subqh_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_R_PH:
+ gen_helper_subqh_r_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_W:
+ gen_helper_subqh_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQH_R_W:
+ gen_helper_subqh_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBUH_QB:
+ gen_helper_subuh_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBUH_R_QB:
+ gen_helper_subuh_r_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* OPC_MUL_PH_DSP */
+ /* MIPS DSPR2 */
+ case OPC_MULQ_RS_W:
+ gen_helper_mulq_rs_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULQ_S_W:
+ gen_helper_mulq_s_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ default:
+ is_mult_g_2e = 1;
+ break;
+ }
+ if (is_mult_g_2e == 0)
+ break;
+ }
case OPC_MOD_G_2E ... OPC_MODU_G_2E:
check_insn(env, ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
+ /* MIPS DSP opcodes */
+ case OPC_ABSQ_S_PH_DSP:
+ op2 = MASK_ABSQ_S_PH(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_ABSQ_S_PH:
+ gen_helper_absq_s_ph(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_ABSQ_S_W:
+ gen_helper_absq_s_w(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_BITREV:
+ gen_helper_bitrev(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQ_W_PHL:
+ gen_helper_preceq_w_phl(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQ_W_PHR:
+ gen_helper_preceq_w_phr(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBL:
+ gen_helper_precequ_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBLA:
+ gen_helper_precequ_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBR:
+ gen_helper_precequ_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEQU_PH_QBRA:
+ gen_helper_precequ_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBL:
+ gen_helper_preceu_ph_qbl(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBLA:
+ gen_helper_preceu_ph_qbla(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBR:
+ gen_helper_preceu_ph_qbr(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_PRECEU_PH_QBRA:
+ gen_helper_preceu_ph_qbra(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_REPL_PH:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode >> 16) & 0x03FF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_repl_ph(cpu_gpr[rd], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ case OPC_REPL_QB:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode >> 16) & 0xFF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_repl_qb(cpu_gpr[rd], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ case OPC_REPLV_PH:
+ gen_helper_replv_ph(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ case OPC_REPLV_QB:
+ gen_helper_replv_qb(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_ABSQ_S_QB:
+ gen_helper_absq_s_qb(cpu_gpr[rd], cpu_gpr[rt]);
+ break;
+ }
+ break;
+ case OPC_ADDU_QB_DSP:
+ op2 = MASK_ADDU_QB(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_ADDQ_PH:
+ gen_helper_addq_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQ_S_PH:
+ gen_helper_addq_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDQ_S_W:
+ gen_helper_addq_s_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDSC:
+ gen_helper_addsc(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDU_QB:
+ gen_helper_addu_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDU_S_QB:
+ gen_helper_addu_s_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDWC:
+ gen_helper_addwc(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MODSUB:
+ gen_helper_modsub(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEQ_S_W_PHL:
+ gen_helper_muleq_s_w_phl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEQ_S_W_PHR:
+ gen_helper_muleq_s_w_phr(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEU_S_PH_QBL:
+ gen_helper_muleu_s_ph_qbl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULEU_S_PH_QBR:
+ gen_helper_muleu_s_ph_qbr(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULQ_RS_PH:
+ gen_helper_mulq_rs_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_RADDU_W_QB:
+ gen_helper_raddu_w_qb(cpu_gpr[rd], cpu_gpr[rs]);
+ break;
+ case OPC_SUBQ_PH:
+ gen_helper_subq_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQ_S_PH:
+ gen_helper_subq_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBQ_S_W:
+ gen_helper_subq_s_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_QB:
+ gen_helper_subu_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_S_QB:
+ gen_helper_subu_s_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_ADDU_PH:
+ gen_helper_addu_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_ADDU_S_PH:
+ gen_helper_addu_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_MULQ_S_PH:
+ gen_helper_mulq_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_PH:
+ gen_helper_subu_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SUBU_S_PH:
+ gen_helper_subu_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ }
+ break;
+ case OPC_APPEND_DSP:
+ op2 = MASK_APPEND(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSPR2 */
+ case OPC_APPEND:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_append(cpu_gpr[rt], cpu_gpr[rt],
+ cpu_gpr[rs], temp_rd);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_BALIGN:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_balign(cpu_gpr[rt], cpu_gpr[rt],
+ cpu_gpr[rs], temp_rd);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_PREPEND:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_prepend(cpu_gpr[rt], temp_rd,
+ cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ }
+ break;
+ case OPC_CMPU_EQ_QB_DSP:
+ op2 = MASK_CMPU_EQ_QB(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_CMP_EQ_PH:
+ gen_helper_cmp_eq_ph(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMP_LT_PH:
+ gen_helper_cmp_lt_ph(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMP_LE_PH:
+ gen_helper_cmp_le_ph(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGU_EQ_QB:
+ gen_helper_cmpgu_eq_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGU_LT_QB:
+ gen_helper_cmpgu_lt_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGU_LE_QB:
+ gen_helper_cmpgu_le_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPU_EQ_QB:
+ gen_helper_cmpu_eq_qb(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPU_LT_QB:
+ gen_helper_cmpu_lt_qb(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPU_LE_QB:
+ gen_helper_cmpu_le_qb(cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PACKRL_PH:
+ gen_helper_packrl_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PICK_QB:
+ gen_helper_pick_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PICK_PH:
+ gen_helper_pick_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQ_QB_PH:
+ gen_helper_precrq_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQ_PH_W:
+ gen_helper_precrq_ph_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQ_RS_PH_W:
+ gen_helper_precrq_rs_ph_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECRQU_S_QB_PH:
+ gen_helper_precrqu_s_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_CMPGDU_EQ_QB:
+ gen_helper_cmpgdu_eq_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGDU_LT_QB:
+ gen_helper_cmpgdu_lt_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_CMPGDU_LE_QB:
+ gen_helper_cmpgdu_le_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECR_QB_PH:
+ gen_helper_precr_qb_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_PRECR_SRA_PH_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_precr_sra_ph_w(cpu_gpr[rt], temp_rd,
+ cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_PRECR_SRA_R_PH_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_precr_sra_r_ph_w(cpu_gpr[rt], temp_rd,
+ cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ }
+ }
+ break;
+ case OPC_DPA_W_PH_DSP:
+ op2 = MASK_DPA_W_PH(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_DPAQ_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaq_s_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAQ_SA_L_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaq_sa_l_w(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAU_H_QBL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpau_h_qbl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAU_H_QBR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpau_h_qbr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQ_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsq_s_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQ_SA_L_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsq_sa_l_w(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSU_H_QBL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsu_h_qbl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSU_H_QBR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsu_h_qbr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_S_W_PHL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maq_s_w_phl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_SA_W_PHL:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maq_sa_w_phl(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_S_W_PHR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maq_s_w_phr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MAQ_SA_W_PHR:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_maq_sa_w_phr(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MULSAQ_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_mulsaq_s_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ /* MIPS DSPR2 */
+ case OPC_DPA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpa_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAQX_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaqx_s_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAQX_SA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpaqx_sa_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPAX_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpax_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPS_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dps_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQX_S_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsqx_s_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSQX_SA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsqx_sa_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_DPSX_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_dpsx_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MULSA_W_PH:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_mulsa_w_ph(temp_rd, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ }
+ break;
+ case OPC_EXTR_W_DSP:
+ op2 = MASK_EXTR_W(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_EXTP:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ gen_helper_extp(cpu_gpr[rt], temp_rd, temp_rs);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ break;
+ }
+ case OPC_EXTPDP:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ gen_helper_extpdp(cpu_gpr[rt], temp_rd, temp_rs);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ break;
+ }
+ case OPC_EXTPDPV:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extpdpv(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_EXTPV:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extpv(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_EXTR_S_H:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ gen_helper_extr_s_h(cpu_gpr[rt], temp_rd, temp_rs);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ break;
+ }
+ case OPC_EXTR_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ gen_helper_extr_w(cpu_gpr[rt], temp_rd, temp_rs);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ break;
+ }
+ case OPC_EXTR_R_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ gen_helper_extr_r_w(cpu_gpr[rt], temp_rd, temp_rs);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ break;
+ }
+ case OPC_EXTR_RS_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ TCGv temp_rs = tcg_const_i32(rs);
+ gen_helper_extr_rs_w(cpu_gpr[rt], temp_rd, temp_rs);
+ tcg_temp_free(temp_rd);
+ tcg_temp_free(temp_rs);
+ break;
+ }
+ case OPC_EXTRV_S_H:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extrv_s_h(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_EXTRV_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extrv_w(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_EXTRV_R_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extrv_r_w(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_EXTRV_RS_W:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_extrv_rs_w(cpu_gpr[rt], temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_MTHLIP:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_mthlip(temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_RDDSP:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode >> 16) & 0x03FF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_rddsp(cpu_gpr[rd], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ case OPC_SHILO:
+ {
+ TCGv temp_imm;
+ TCGv temp_rd = tcg_const_i32(rd);
+ imm = (ctx->opcode >> 20) & 0x3F;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_shilo(temp_rd, temp_imm);
+ tcg_temp_free(temp_imm);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_SHILOV:
+ {
+ TCGv temp_rd = tcg_const_i32(rd);
+ gen_helper_shilov(temp_rd, cpu_gpr[rs]);
+ tcg_temp_free(temp_rd);
+ break;
+ }
+ case OPC_WRDSP:
+ {
+ TCGv temp_imm;
+ imm = (ctx->opcode >> 11) & 0x3FF;
+ temp_imm = tcg_const_i32(imm);
+ gen_helper_wrdsp(cpu_gpr[rs], temp_imm);
+ tcg_temp_free(temp_imm);
+ break;
+ }
+ }
+ break;
+ case OPC_INSV_DSP:
+ op2 = MASK_INSV(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_INSV:
+ {
+ TCGv temp_rt = tcg_const_i32(rt);
+ gen_helper_insv(temp_rt, cpu_gpr[rs], cpu_gpr[rt]);
+ tcg_temp_free(temp_rt);
+ break;
+ }
+ }
+ break;
+ case OPC_SHLL_QB_DSP:
+ {
+ TCGv temp_rs = tcg_const_i32(rs);
+ op2 = MASK_SHLL_QB(ctx->opcode);
+ switch (op2) {
+ /* MIPS DSP */
+ case OPC_SHLL_PH:
+ gen_helper_shll_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHLL_S_PH:
+ gen_helper_shll_s_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHLL_QB:
+ gen_helper_shll_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHLL_S_W:
+ gen_helper_shll_s_w(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHLLV_PH:
+ gen_helper_shllv_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHLLV_S_PH:
+ gen_helper_shllv_s_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHLLV_QB:
+ gen_helper_shllv_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHLLV_S_W:
+ gen_helper_shllv_s_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHRA_PH:
+ gen_helper_shra_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRA_R_PH:
+ gen_helper_shra_r_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRA_R_W:
+ gen_helper_shra_r_w(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRAV_PH:
+ gen_helper_shrav_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHRAV_R_PH:
+ gen_helper_shrav_r_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHRAV_R_W:
+ gen_helper_shrav_r_w(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHRL_QB:
+ gen_helper_shrl_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRLV_QB:
+ gen_helper_shrlv_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ /* MIPS DSPR2 */
+ case OPC_SHRA_QB:
+ gen_helper_shra_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRA_R_QB:
+ gen_helper_shra_r_qb(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRAV_QB:
+ gen_helper_shrav_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHRAV_R_QB:
+ gen_helper_shrav_r_qb(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ case OPC_SHRL_PH:
+ gen_helper_shrl_ph(cpu_gpr[rd], temp_rs, cpu_gpr[rt]);
+ break;
+ case OPC_SHRLV_PH:
+ gen_helper_shrlv_ph(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
+ break;
+ }
+ tcg_temp_free(temp_rs);
+ break;
+ }
case OPC_LX_DSP:
op2 = MASK_LX(ctx->opcode);
switch (op2) {
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c Jia Liu
@ 2012-03-27 17:48 ` Richard Henderson
2012-03-28 1:36 ` Jia Liu
0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2012-03-27 17:48 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/12 02:24, Jia Liu wrote:
> Handle MIPS DSP instructions in target-mips/translate.c.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
This patch should have been split as well, adding translations of the insns
at the same time you add the helpers. That said, the actual code looks ok.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c
2012-03-27 17:48 ` Richard Henderson
@ 2012-03-28 1:36 ` Jia Liu
2012-03-29 13:20 ` Richard Henderson
0 siblings, 1 reply; 33+ messages in thread
From: Jia Liu @ 2012-03-28 1:36 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel, aurelien
On Wed, Mar 28, 2012 at 1:48 AM, Richard Henderson <rth@twiddle.net> wrote:
> On 03/27/12 02:24, Jia Liu wrote:
>> Handle MIPS DSP instructions in target-mips/translate.c.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>
> This patch should have been split as well, adding translations of the insns
> at the same time you add the helpers. That said, the actual code looks ok.
>
helpers can be grouped by MIPS DSP manual, BUT translations have to
grouped by opcode.
There is some difference between them, I'll try to do this.
>
> r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c
2012-03-28 1:36 ` Jia Liu
@ 2012-03-29 13:20 ` Richard Henderson
0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2012-03-29 13:20 UTC (permalink / raw)
To: Jia Liu; +Cc: qemu-devel, aurelien
On 03/27/2012 09:36 PM, Jia Liu wrote:
>> > This patch should have been split as well, adding translations of the insns
>> > at the same time you add the helpers. That said, the actual code looks ok.
>> >
> helpers can be grouped by MIPS DSP manual, BUT translations have to
> grouped by opcode.
> There is some difference between them, I'll try to do this.
>
One possibility is to add the bare skeleton of the decoding by opcode first,
leaving out the actual case statements. Then add the
case OPCODE:
gen_helper();
break;
in the patch adding the helpers.
r~
^ permalink raw reply [flat|nested] 33+ messages in thread
* [Qemu-devel] [PATCH V3 12/12] add MIPS DSP testcases
2012-03-27 9:24 [Qemu-devel] [PATCH V3 00/12] Qemu MIPS ASE DSP Support Jia Liu
` (10 preceding siblings ...)
2012-03-27 9:24 ` [Qemu-devel] [PATCH V3 11/12] Handle MIPS DSP instructions in target-mips/translate.c Jia Liu
@ 2012-03-27 9:24 ` Jia Liu
11 siblings, 0 replies; 33+ messages in thread
From: Jia Liu @ 2012-03-27 9:24 UTC (permalink / raw)
To: qemu-devel; +Cc: aurelien
MIPS DSP testcases
Signed-off-by: Jia Liu <proljc@gmail.com>
---
tests/tcg/mips/mips32-dsp/Makefile | 133 ++++++++++++++++++++++++
tests/tcg/mips/mips32-dsp/absq_s_ph.c | 30 ++++++
tests/tcg/mips/mips32-dsp/absq_s_w.c | 37 +++++++
tests/tcg/mips/mips32-dsp/addq_ph.c | 30 ++++++
tests/tcg/mips/mips32-dsp/addq_s_ph.c | 30 ++++++
tests/tcg/mips/mips32-dsp/addsc.c | 30 ++++++
tests/tcg/mips/mips32-dsp/addu_qb.c | 30 ++++++
tests/tcg/mips/mips32-dsp/addu_s_qb.c | 30 ++++++
tests/tcg/mips/mips32-dsp/addwc.c | 30 ++++++
tests/tcg/mips/mips32-dsp/bitrev.c | 20 ++++
tests/tcg/mips/mips32-dsp/bposge32.c | 44 ++++++++
tests/tcg/mips/mips32-dsp/cmp_eq_ph.c | 35 ++++++
tests/tcg/mips/mips32-dsp/cmp_le_ph.c | 35 ++++++
tests/tcg/mips/mips32-dsp/cmp_lt_ph.c | 35 ++++++
tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c | 31 ++++++
tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c | 31 ++++++
tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c | 31 ++++++
tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c | 35 ++++++
tests/tcg/mips/mips32-dsp/cmpu_le_qb.c | 35 ++++++
tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c | 35 ++++++
tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c | 31 ++++++
tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c | 31 ++++++
tests/tcg/mips/mips32-dsp/dpau_h_qbl.c | 27 +++++
tests/tcg/mips/mips32-dsp/dpau_h_qbr.c | 27 +++++
tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c | 27 +++++
tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c | 31 ++++++
tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c | 27 +++++
tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c | 27 +++++
tests/tcg/mips/mips32-dsp/extp.c | 44 ++++++++
tests/tcg/mips/mips32-dsp/extpdp.c | 46 ++++++++
tests/tcg/mips/mips32-dsp/extpdpv.c | 47 +++++++++
tests/tcg/mips/mips32-dsp/extpv.c | 45 ++++++++
tests/tcg/mips/mips32-dsp/extr_r_w.c | 25 +++++
tests/tcg/mips/mips32-dsp/extr_rs_w.c | 25 +++++
tests/tcg/mips/mips32-dsp/extr_s_h.c | 25 +++++
tests/tcg/mips/mips32-dsp/extr_w.c | 25 +++++
tests/tcg/mips/mips32-dsp/extrv_r_w.c | 29 +++++
tests/tcg/mips/mips32-dsp/extrv_rs_w.c | 29 +++++
tests/tcg/mips/mips32-dsp/extrv_s_h.c | 29 +++++
tests/tcg/mips/mips32-dsp/extrv_w.c | 29 +++++
tests/tcg/mips/mips32-dsp/insv.c | 23 ++++
tests/tcg/mips/mips32-dsp/lbux.c | 23 ++++
tests/tcg/mips/mips32-dsp/lhx.c | 23 ++++
tests/tcg/mips/mips32-dsp/lwx.c | 23 ++++
tests/tcg/mips/mips32-dsp/madd.c | 31 ++++++
tests/tcg/mips/mips32-dsp/maddu.c | 31 ++++++
tests/tcg/mips/mips32-dsp/maq_s_w_phl.c | 31 ++++++
tests/tcg/mips/mips32-dsp/maq_s_w_phr.c | 31 ++++++
tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c | 31 ++++++
tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c | 31 ++++++
tests/tcg/mips/mips32-dsp/mfhi.c | 21 ++++
tests/tcg/mips/mips32-dsp/mflo.c | 21 ++++
tests/tcg/mips/mips32-dsp/modsub.c | 30 ++++++
tests/tcg/mips/mips32-dsp/msub.c | 30 ++++++
tests/tcg/mips/mips32-dsp/msubu.c | 30 ++++++
tests/tcg/mips/mips32-dsp/mthi.c | 21 ++++
tests/tcg/mips/mips32-dsp/mthlip.c | 34 ++++++
tests/tcg/mips/mips32-dsp/mtlo.c | 21 ++++
tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c | 40 +++++++
tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c | 25 +++++
tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c | 25 +++++
tests/tcg/mips/mips32-dsp/mulq_rs_ph.c | 25 +++++
tests/tcg/mips/mips32-dsp/mult.c | 24 +++++
tests/tcg/mips/mips32-dsp/multu.c | 24 +++++
tests/tcg/mips/mips32-dsp/packrl_ph.c | 21 ++++
tests/tcg/mips/mips32-dsp/pick_ph.c | 23 ++++
tests/tcg/mips/mips32-dsp/pick_qb.c | 23 ++++
tests/tcg/mips/mips32-dsp/preceq_w_phl.c | 20 ++++
tests/tcg/mips/mips32-dsp/preceq_w_phr.c | 20 ++++
tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c | 20 ++++
tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c | 20 ++++
tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c | 20 ++++
tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c | 20 ++++
tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c | 20 ++++
tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c | 20 ++++
tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c | 20 ++++
tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c | 20 ++++
tests/tcg/mips/mips32-dsp/precrq_ph_w.c | 21 ++++
tests/tcg/mips/mips32-dsp/precrq_qb_ph.c | 21 ++++
tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c | 21 ++++
tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c | 21 ++++
tests/tcg/mips/mips32-dsp/raddu_w_qb.c | 20 ++++
tests/tcg/mips/mips32-dsp/rddsp.c | 54 ++++++++++
tests/tcg/mips/mips32-dsp/repl_ph.c | 23 ++++
tests/tcg/mips/mips32-dsp/repl_qb.c | 16 +++
tests/tcg/mips/mips32-dsp/replv_ph.c | 19 ++++
tests/tcg/mips/mips32-dsp/replv_qb.c | 19 ++++
tests/tcg/mips/mips32-dsp/shilo.c | 27 +++++
tests/tcg/mips/mips32-dsp/shilov.c | 29 +++++
tests/tcg/mips/mips32-dsp/shll_ph.c | 24 +++++
tests/tcg/mips/mips32-dsp/shll_qb.c | 23 ++++
tests/tcg/mips/mips32-dsp/shll_s_ph.c | 24 +++++
tests/tcg/mips/mips32-dsp/shll_s_w.c | 24 +++++
tests/tcg/mips/mips32-dsp/shllv_ph.c | 25 +++++
tests/tcg/mips/mips32-dsp/shllv_qb.c | 24 +++++
tests/tcg/mips/mips32-dsp/shllv_s_ph.c | 25 +++++
tests/tcg/mips/mips32-dsp/shllv_s_w.c | 25 +++++
tests/tcg/mips/mips32-dsp/shra_ph.c | 20 ++++
tests/tcg/mips/mips32-dsp/shra_r_ph.c | 20 ++++
tests/tcg/mips/mips32-dsp/shra_r_w.c | 20 ++++
tests/tcg/mips/mips32-dsp/shrav_ph.c | 21 ++++
tests/tcg/mips/mips32-dsp/shrav_r_ph.c | 21 ++++
tests/tcg/mips/mips32-dsp/shrav_r_w.c | 21 ++++
tests/tcg/mips/mips32-dsp/shrl_qb.c | 20 ++++
tests/tcg/mips/mips32-dsp/shrlv_qb.c | 21 ++++
tests/tcg/mips/mips32-dsp/subq_ph.c | 25 +++++
tests/tcg/mips/mips32-dsp/subq_s_ph.c | 25 +++++
tests/tcg/mips/mips32-dsp/subq_s_w.c | 25 +++++
tests/tcg/mips/mips32-dsp/subu_qb.c | 25 +++++
tests/tcg/mips/mips32-dsp/subu_s_qb.c | 25 +++++
tests/tcg/mips/mips32-dsp/wrdsp.c | 54 ++++++++++
tests/tcg/mips/mips32-dspr2/Makefile | 71 +++++++++++++
tests/tcg/mips/mips32-dspr2/absq_s_qb.c | 31 ++++++
tests/tcg/mips/mips32-dspr2/addqh_ph.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/addqh_r_ph.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/addqh_r_w.c | 34 ++++++
tests/tcg/mips/mips32-dspr2/addqh_w.c | 34 ++++++
tests/tcg/mips/mips32-dspr2/addu_ph.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/addu_s_ph.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/adduh_qb.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/adduh_r_qb.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/append.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/balign.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c | 37 +++++++
tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c | 37 +++++++
tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c | 37 +++++++
tests/tcg/mips/mips32-dspr2/dpa_w_ph.c | 27 +++++
tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c | 57 ++++++++++
tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/dpax_w_ph.c | 27 +++++
tests/tcg/mips/mips32-dspr2/dps_w_ph.c | 27 +++++
tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c | 31 ++++++
tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c | 31 ++++++
tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c | 27 +++++
tests/tcg/mips/mips32-dspr2/mul_ph.c | 25 +++++
tests/tcg/mips/mips32-dspr2/mul_s_ph.c | 25 +++++
tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c | 40 +++++++
tests/tcg/mips/mips32-dspr2/mulq_rs_w.c | 36 +++++++
tests/tcg/mips/mips32-dspr2/mulq_s_ph.c | 25 +++++
tests/tcg/mips/mips32-dspr2/mulq_s_w.c | 36 +++++++
tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c | 29 +++++
tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c | 29 +++++
tests/tcg/mips/mips32-dspr2/precr_qb_ph.c | 21 ++++
tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c | 32 ++++++
tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c | 32 ++++++
tests/tcg/mips/mips32-dspr2/prepend.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/shra_qb.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/shra_r_qb.c | 30 ++++++
tests/tcg/mips/mips32-dspr2/shrav_qb.c | 32 ++++++
tests/tcg/mips/mips32-dspr2/shrav_r_qb.c | 32 ++++++
tests/tcg/mips/mips32-dspr2/shrl_ph.c | 20 ++++
tests/tcg/mips/mips32-dspr2/shrlv_ph.c | 21 ++++
tests/tcg/mips/mips32-dspr2/subqh_ph.c | 21 ++++
tests/tcg/mips/mips32-dspr2/subqh_r_ph.c | 21 ++++
tests/tcg/mips/mips32-dspr2/subqh_r_w.c | 21 ++++
tests/tcg/mips/mips32-dspr2/subqh_w.c | 21 ++++
tests/tcg/mips/mips32-dspr2/subu_ph.c | 25 +++++
tests/tcg/mips/mips32-dspr2/subu_s_ph.c | 25 +++++
tests/tcg/mips/mips32-dspr2/subuh_qb.c | 21 ++++
tests/tcg/mips/mips32-dspr2/subuh_r_qb.c | 21 ++++
160 files changed, 4596 insertions(+), 0 deletions(-)
create mode 100644 tests/tcg/mips/mips32-dsp/Makefile
create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/absq_s_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/addq_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/addq_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/addsc.c
create mode 100644 tests/tcg/mips/mips32-dsp/addu_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/addu_s_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/addwc.c
create mode 100644 tests/tcg/mips/mips32-dsp/bitrev.c
create mode 100644 tests/tcg/mips/mips32-dsp/bposge32.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmp_le_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
create mode 100644 tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
create mode 100644 tests/tcg/mips/mips32-dsp/extp.c
create mode 100644 tests/tcg/mips/mips32-dsp/extpdp.c
create mode 100644 tests/tcg/mips/mips32-dsp/extpdpv.c
create mode 100644 tests/tcg/mips/mips32-dsp/extpv.c
create mode 100644 tests/tcg/mips/mips32-dsp/extr_r_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/extr_rs_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/extr_s_h.c
create mode 100644 tests/tcg/mips/mips32-dsp/extr_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/extrv_r_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/extrv_rs_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/extrv_s_h.c
create mode 100644 tests/tcg/mips/mips32-dsp/extrv_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/insv.c
create mode 100644 tests/tcg/mips/mips32-dsp/lbux.c
create mode 100644 tests/tcg/mips/mips32-dsp/lhx.c
create mode 100644 tests/tcg/mips/mips32-dsp/lwx.c
create mode 100644 tests/tcg/mips/mips32-dsp/madd.c
create mode 100644 tests/tcg/mips/mips32-dsp/maddu.c
create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
create mode 100644 tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
create mode 100644 tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
create mode 100644 tests/tcg/mips/mips32-dsp/mfhi.c
create mode 100644 tests/tcg/mips/mips32-dsp/mflo.c
create mode 100644 tests/tcg/mips/mips32-dsp/modsub.c
create mode 100644 tests/tcg/mips/mips32-dsp/msub.c
create mode 100644 tests/tcg/mips/mips32-dsp/msubu.c
create mode 100644 tests/tcg/mips/mips32-dsp/mthi.c
create mode 100644 tests/tcg/mips/mips32-dsp/mthlip.c
create mode 100644 tests/tcg/mips/mips32-dsp/mtlo.c
create mode 100644 tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
create mode 100644 tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
create mode 100644 tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/mult.c
create mode 100644 tests/tcg/mips/mips32-dsp/multu.c
create mode 100644 tests/tcg/mips/mips32-dsp/packrl_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/pick_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/pick_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phl.c
create mode 100644 tests/tcg/mips/mips32-dsp/preceq_w_phr.c
create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
create mode 100644 tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
create mode 100644 tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
create mode 100644 tests/tcg/mips/mips32-dsp/precrq_ph_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/raddu_w_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/rddsp.c
create mode 100644 tests/tcg/mips/mips32-dsp/repl_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/repl_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/replv_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/replv_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/shilo.c
create mode 100644 tests/tcg/mips/mips32-dsp/shilov.c
create mode 100644 tests/tcg/mips/mips32-dsp/shll_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shll_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shll_s_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/shllv_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shllv_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shllv_s_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/shra_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shra_r_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/shrav_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/shrav_r_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/shrl_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/shrlv_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/subq_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dsp/subq_s_w.c
create mode 100644 tests/tcg/mips/mips32-dsp/subu_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/subu_s_qb.c
create mode 100644 tests/tcg/mips/mips32-dsp/wrdsp.c
create mode 100644 tests/tcg/mips/mips32-dspr2/Makefile
create mode 100644 tests/tcg/mips/mips32-dspr2/absq_s_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_r_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/addqh_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/addu_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/addu_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/append.c
create mode 100644 tests/tcg/mips/mips32-dspr2/balign.c
create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dps_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mul_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mul_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mulq_s_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/prepend.c
create mode 100644 tests/tcg/mips/mips32-dspr2/shra_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/shra_r_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/shrl_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/shrlv_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_r_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subqh_w.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subu_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subu_s_ph.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_qb.c
create mode 100644 tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
diff --git a/tests/tcg/mips/mips32-dsp/Makefile b/tests/tcg/mips/mips32-dsp/Makefile
new file mode 100644
index 0000000..ee8a386
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/Makefile
@@ -0,0 +1,133 @@
+-include ../../config-host.mak
+
+CROSS=mipsel-unknown-linux-gnu-
+
+SIM=qemu-mipsel
+
+CC = $(CROSS)gcc
+CFLAGS = -march=mips32r2 -mgp32 -mdsp -static
+
+TESTCASES = absq_s_ph.tst
+TESTCASES += absq_s_w.tst
+TESTCASES += addq_ph.tst
+TESTCASES += addq_s_ph.tst
+TESTCASES += addsc.tst
+TESTCASES += addu_qb.tst
+TESTCASES += addu_s_qb.tst
+TESTCASES += addwc.tst
+TESTCASES += bitrev.tst
+TESTCASES += bposge32.tst
+TESTCASES += cmp_eq_ph.tst
+TESTCASES += cmpgu_eq_qb.tst
+TESTCASES += cmpgu_le_qb.tst
+TESTCASES += cmpgu_lt_qb.tst
+TESTCASES += cmp_le_ph.tst
+TESTCASES += cmp_lt_ph.tst
+TESTCASES += cmpu_eq_qb.tst
+TESTCASES += cmpu_le_qb.tst
+TESTCASES += cmpu_lt_qb.tst
+TESTCASES += dpaq_sa_l_w.tst
+TESTCASES += dpaq_s_w_ph.tst
+TESTCASES += dpau_h_qbl.tst
+TESTCASES += dpau_h_qbr.tst
+TESTCASES += dpsq_sa_l_w.tst
+TESTCASES += dpsq_s_w_ph.tst
+TESTCASES += dpsu_h_qbl.tst
+TESTCASES += dpsu_h_qbr.tst
+TESTCASES += extp.tst
+TESTCASES += extpdp.tst
+TESTCASES += extpdpv.tst
+TESTCASES += extpv.tst
+TESTCASES += extr_rs_w.tst
+TESTCASES += extr_r_w.tst
+TESTCASES += extr_s_h.tst
+TESTCASES += extrv_rs_w.tst
+TESTCASES += extrv_r_w.tst
+TESTCASES += extrv_s_h.tst
+TESTCASES += extrv_w.tst
+TESTCASES += extr_w.tst
+TESTCASES += insv.tst
+TESTCASES += lbux.tst
+TESTCASES += lhx.tst
+TESTCASES += lwx.tst
+TESTCASES += madd.tst
+TESTCASES += maddu.tst
+TESTCASES += maq_sa_w_phl.tst
+TESTCASES += maq_sa_w_phr.tst
+TESTCASES += maq_s_w_phl.tst
+TESTCASES += maq_s_w_phr.tst
+TESTCASES += mfhi.tst
+TESTCASES += mflo.tst
+TESTCASES += modsub.tst
+TESTCASES += msub.tst
+TESTCASES += msubu.tst
+TESTCASES += mthi.tst
+TESTCASES += mthlip.tst
+TESTCASES += mtlo.tst
+TESTCASES += muleq_s_w_phr.tst
+TESTCASES += muleu_s_ph_qbl.tst
+TESTCASES += muleu_s_ph_qbr.tst
+TESTCASES += mulq_rs_ph.tst
+TESTCASES += mult.tst
+TESTCASES += multu.tst
+TESTCASES += packrl_ph.tst
+TESTCASES += pick_ph.tst
+TESTCASES += pick_qb.tst
+TESTCASES += precequ_ph_qbla.tst
+TESTCASES += precequ_ph_qbl.tst
+TESTCASES += precequ_ph_qbra.tst
+TESTCASES += precequ_ph_qbr.tst
+TESTCASES += preceq_w_phl.tst
+TESTCASES += preceq_w_phr.tst
+TESTCASES += preceu_ph_qbla.tst
+TESTCASES += preceu_ph_qbl.tst
+TESTCASES += preceu_ph_qbra.tst
+TESTCASES += preceu_ph_qbr.tst
+TESTCASES += precrq_ph_w.tst
+TESTCASES += precrq_qb_ph.tst
+TESTCASES += precrq_rs_ph_w.tst
+TESTCASES += precrqu_s_qb_ph.tst
+TESTCASES += raddu_w_qb.tst
+TESTCASES += rddsp.tst
+TESTCASES += repl_ph.tst
+TESTCASES += repl_qb.tst
+TESTCASES += replv_ph.tst
+TESTCASES += replv_qb.tst
+TESTCASES += shilo.tst
+TESTCASES += shilov.tst
+TESTCASES += shll_ph.tst
+TESTCASES += shll_qb.tst
+TESTCASES += shll_s_ph.tst
+TESTCASES += shll_s_w.tst
+TESTCASES += shllv_ph.tst
+TESTCASES += shllv_qb.tst
+TESTCASES += shllv_s_ph.tst
+TESTCASES += shllv_s_w.tst
+TESTCASES += shra_ph.tst
+TESTCASES += shra_r_ph.tst
+TESTCASES += shra_r_w.tst
+TESTCASES += shrav_ph.tst
+TESTCASES += shrav_r_ph.tst
+TESTCASES += shrav_r_w.tst
+TESTCASES += shrl_qb.tst
+TESTCASES += shrlv_qb.tst
+TESTCASES += subq_ph.tst
+TESTCASES += subq_s_ph.tst
+TESTCASES += subq_s_w.tst
+TESTCASES += subu_qb.tst
+TESTCASES += subu_s_qb.tst
+TESTCASES += wrdsp.tst
+
+all: $(TESTCASES)
+
+%.tst: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+check: $(TESTCASES)
+ @for case in $(TESTCASES); do \
+ echo $(SIM) ./$$case;\
+ $(SIM) ./$$case; \
+ done
+
+clean:
+ $(RM) -rf $(TESTCASES)
diff --git a/tests/tcg/mips/mips32-dsp/absq_s_ph.c b/tests/tcg/mips/mips32-dsp/absq_s_ph.c
new file mode 100644
index 0000000..0bffb19
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/absq_s_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x10017EFD;
+ result = 0x10017EFD;
+
+ __asm volatile
+ ("absq_s.ph %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x8000A536;
+ result = 0x7FFF5ACA;
+
+ __asm volatile
+ ("absq_s.ph %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/absq_s_w.c b/tests/tcg/mips/mips32-dsp/absq_s_w.c
new file mode 100644
index 0000000..51ee6ae
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/absq_s_w.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x80000000;
+ result = 0x7FFFFFFF;
+ __asm volatile
+ ("absq_s.w %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x80030000;
+ result = 0x7FFD0000;
+ __asm volatile
+ ("absq_s.w %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x31036080;
+ result = 0x31036080;
+ __asm volatile
+ ("absq_s.w %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addq_ph.c b/tests/tcg/mips/mips32-dsp/addq_ph.c
new file mode 100644
index 0000000..e02f762
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addq_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0xFFFFFFFF;
+ rt = 0x10101010;
+ result = 0x100F100F;
+ __asm volatile
+ ("addq.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ rs = 0x3712847D;
+ rt = 0x0031AF2D;
+ result = 0x374333AA;
+ __asm volatile
+ ("addq.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addq_s_ph.c b/tests/tcg/mips/mips32-dsp/addq_s_ph.c
new file mode 100644
index 0000000..806ebd9
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addq_s_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0xFFFFFFFF;
+ rt = 0x10101010;
+ result = 0x100F100F;
+ __asm volatile
+ ("addq_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ rs = 0x3712847D;
+ rt = 0x0031AF2D;
+ result = 0x37438000;
+ __asm volatile
+ ("addq_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addsc.c b/tests/tcg/mips/mips32-dsp/addsc.c
new file mode 100644
index 0000000..7b58894
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addsc.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x0000000F;
+ rt = 0x00000001;
+ result = 0x00000010;
+ __asm volatile
+ ("addsc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF0FFF;
+ rt = 0x00010111;
+ result = 0x00001110;
+ __asm volatile
+ ("addsc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addu_qb.c b/tests/tcg/mips/mips32-dsp/addu_qb.c
new file mode 100644
index 0000000..72fb685
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addu_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010001;
+ result = 0x00000000;
+ __asm volatile
+ ("addu.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0xFF011112;
+ __asm volatile
+ ("addu.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addu_s_qb.c b/tests/tcg/mips/mips32-dsp/addu_s_qb.c
new file mode 100644
index 0000000..654838a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addu_s_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x10FF01FF;
+ rt = 0x10010001;
+ result = 0x20FF01FF;
+ __asm volatile
+ ("addu_s.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0xFFFF1112;
+ __asm volatile
+ ("addu_s.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/addwc.c b/tests/tcg/mips/mips32-dsp/addwc.c
new file mode 100644
index 0000000..2b6193b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/addwc.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x10FF01FF;
+ rt = 0x10010001;
+ result = 0x21000200;
+ __asm volatile
+ ("addwc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0x00011112;
+ __asm volatile
+ ("addwc %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/bitrev.c b/tests/tcg/mips/mips32-dsp/bitrev.c
new file mode 100644
index 0000000..12c247e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/bitrev.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x00005678;
+
+ __asm volatile
+ ("bitrev %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/bposge32.c b/tests/tcg/mips/mips32-dsp/bposge32.c
new file mode 100644
index 0000000..0d84cc9
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/bposge32.c
@@ -0,0 +1,44 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int dsp, sum;
+ int result;
+
+ dsp = 0x20;
+ sum = 0x01;
+ result = 0x02;
+
+ __asm volatile
+ ("wrdsp %1\n\t"
+ "bposge32 test1\n\t"
+ "nop\n\t"
+ "addi %0, 0xA2 \n\t"
+ "nop\n\t"
+ "test1: \n\t"
+ "addi %0, 0x01 \n\t"
+ : "+r"(sum)
+ : "r"(dsp)
+ );
+ assert(sum == result);
+
+ dsp = 0x10;
+ sum = 0x01;
+ result = 0xA4;
+
+ __asm volatile
+ ("wrdsp %1\n\t"
+ "bposge32 test2\n\t"
+ "nop\n\t"
+ "addi %0, 0xA2 \n\t"
+ "nop\n\t"
+ "test2: \n\t"
+ "addi %0, 0x01 \n\t"
+ : "+r"(sum)
+ : "r"(dsp)
+ );
+ assert(sum == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c b/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
new file mode 100644
index 0000000..f9cee0b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmp_eq_ph.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA33FF;
+ result = 0x00;
+ __asm volatile
+ ("cmp.eq.ph %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ rd = (rd >> 24) & 0x03;
+ assert(rd == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x03;
+ __asm volatile
+ ("cmp.eq.ph %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ rd = (rd >> 24) & 0x03;
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmp_le_ph.c b/tests/tcg/mips/mips32-dsp/cmp_le_ph.c
new file mode 100644
index 0000000..992cea0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmp_le_ph.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA33FF;
+ result = 0x02;
+ __asm volatile
+ ("cmp.le.ph %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ rd = (rd >> 24) & 0x03;
+ assert(rd == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x03;
+ __asm volatile
+ ("cmp.le.ph %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ rd = (rd >> 24) & 0x03;
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c b/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
new file mode 100644
index 0000000..836807b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmp_lt_ph.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA33FF;
+ result = 0x02;
+ __asm volatile
+ ("cmp.lt.ph %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ rd = (rd >> 24) & 0x03;
+ assert(rd == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x00;
+ __asm volatile
+ ("cmp.lt.ph %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ rd = (rd >> 24) & 0x03;
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
new file mode 100644
index 0000000..3cebff7
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpgu_eq_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x02;
+ __asm volatile
+ ("cmpgu.eq.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x0F;
+ __asm volatile
+ ("cmpgu.eq.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
new file mode 100644
index 0000000..bb25a72
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpgu_le_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x0F;
+ __asm volatile
+ ("cmpgu.le.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ rs = 0x11777066;
+ rt = 0x11766066;
+ result = 0x09;
+ __asm volatile
+ ("cmpgu.le.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c b/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
new file mode 100644
index 0000000..9f80549
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpgu_lt_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x0D;
+ __asm volatile
+ ("cmpgu.lt.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ rs = 0x11777066;
+ rt = 0x11766066;
+ result = 0x00;
+ __asm volatile
+ ("cmpgu.lt.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
new file mode 100644
index 0000000..86d0b69
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpu_eq_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x02;
+ __asm volatile
+ ("cmpu.eq.qb %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(dsp == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x0F;
+ __asm volatile
+ ("cmpu.eq.qb %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(dsp == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
new file mode 100644
index 0000000..7dd8652
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpu_le_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x0F;
+ __asm volatile
+ ("cmpu.le.qb %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(dsp == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x0F;
+ __asm volatile
+ ("cmpu.le.qb %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(dsp == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c b/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
new file mode 100644
index 0000000..639fc44
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/cmpu_lt_qb.c
@@ -0,0 +1,35 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x0D;
+ __asm volatile
+ ("cmpu.lt.qb %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(dsp == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x00;
+ __asm volatile
+ ("cmpu.lt.qb %1, %2\n\t"
+ "rddsp %0\n\t"
+ : "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(dsp == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
new file mode 100644
index 0000000..1ac9b05
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpaq_s_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 0, acl = 0;
+ int resulth, resultl, resultdsp;
+
+ rs = 0x800000FF;
+ rt = 0x80000002;
+ resulth = 0x00;
+ resultl = 0x800003FB;
+ resultdsp = 0x01;
+ __asm volatile
+ ("mthi %0, $ac1 \n\t"
+ "mtlo %1, $ac1 \n\t"
+ "dpaq_s.w.ph $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2 \n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = dsp >> 17 & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
new file mode 100644
index 0000000..a53ea48
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpaq_sa_l_w.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 0, acl = 0;
+ int resulth, resultl, resultdsp;
+
+ rs = 0x800000FF;
+ rt = 0x80000002;
+ resulth = 0x7FFFFFFF;
+ resultl = 0xFFFFFFFF;
+ resultdsp = 0x01;
+ __asm volatile
+ ("mthi %0, $ac1 \n\t"
+ "mtlo %0, $ac1 \n\t"
+ "dpaq_sa.l.w $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2 \n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c b/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
new file mode 100644
index 0000000..c985411
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpau_h_qbl.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 3;
+ int resulth, resultl;
+
+ rs = 0x800000FF;
+ rt = 0x80000002;
+ resulth = 0x05;
+ resultl = 0x4003;
+ __asm volatile
+ ("mthi %0, $ac1 \n\t"
+ "mtlo %1, $ac1 \n\t"
+ "dpau.h.qbl $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c b/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
new file mode 100644
index 0000000..78779e2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpau_h_qbr.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 3;
+ int resulth, resultl;
+
+ rs = 0x800000FF;
+ rt = 0x80000002;
+ resulth = 0x05;
+ resultl = 0x0201;
+ __asm volatile
+ ("mthi %0, $ac1 \n\t"
+ "mtlo %1, $ac1 \n\t"
+ "dpau.h.qbr $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
new file mode 100644
index 0000000..8a59155
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsq_s_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x04;
+ resultl = 0xEE9794A3;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsq_s.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
new file mode 100644
index 0000000..7ae97de
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsq_sa_l_w.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 5, acl = 5;
+ int resulth, resultl, resultdsp;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x7FFFFFFF;
+ resultl = 0xFFFFFFFF;
+ resultdsp = 0x01;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsq_sa.l.w $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2\n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c b/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
new file mode 100644
index 0000000..7aa33bf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsu_h_qbl.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x04;
+ resultl = 0xFFFFFEE5;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsu.h.qbl $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c b/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
new file mode 100644
index 0000000..c030b84
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/dpsu_h_qbr.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x04;
+ resultl = 0xFFFFE233;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsu.h.qbr $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extp.c b/tests/tcg/mips/mips32-dsp/extp.c
new file mode 100644
index 0000000..c087ae9
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extp.c
@@ -0,0 +1,44 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ result = 0x000C;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extp %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 14) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x01;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extp %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 14) & 0x01;
+ assert(dsp == 1);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extpdp.c b/tests/tcg/mips/mips32-dsp/extpdp.c
new file mode 100644
index 0000000..61278dd
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extpdp.c
@@ -0,0 +1,46 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ach, acl, dsp, pos, efi;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ result = 0x000C;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpdp %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ pos = dsp & 0x3F;
+ efi = (dsp >> 14) & 0x01;
+ assert(pos == 3);
+ assert(efi == 0);
+ assert(result == rt);
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x01;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpdp %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ efi = (dsp >> 14) & 0x01;
+ assert(efi == 1);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extpdpv.c b/tests/tcg/mips/mips32-dsp/extpdpv.c
new file mode 100644
index 0000000..5f7eb9c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extpdpv.c
@@ -0,0 +1,47 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, ach, acl, dsp, pos, efi;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ rs = 0x03;
+ result = 0x000C;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpdpv %0, $ac1, %4\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl), "r"(rs)
+ );
+ pos = dsp & 0x3F;
+ efi = (dsp >> 14) & 0x01;
+ assert(pos == 3);
+ assert(efi == 0);
+ assert(result == rt);
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x01;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpdpv %0, $ac1, %4\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl), "r"(rs)
+ );
+ efi = (dsp >> 14) & 0x01;
+ assert(efi == 1);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extpv.c b/tests/tcg/mips/mips32-dsp/extpv.c
new file mode 100644
index 0000000..9f288c1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extpv.c
@@ -0,0 +1,45 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ac, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ ac = 0x03;
+ result = 0x000C;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpv %0, $ac1, %4\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl), "r"(ac)
+ );
+ dsp = (dsp >> 14) & 0x01;
+ assert(dsp == 0);
+ assert(result == rt);
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x01;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extpv %0, $ac1, %4\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(ach), "r"(acl), "r"(ac)
+ );
+ dsp = (dsp >> 14) & 0x01;
+ assert(dsp == 1);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_r_w.c b/tests/tcg/mips/mips32-dsp/extr_r_w.c
new file mode 100644
index 0000000..106f185
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_r_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ result = 0xA0001699;
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_r.w %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_rs_w.c b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
new file mode 100644
index 0000000..4e9f493
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_rs_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ result = 0x7FFFFFFF;
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_rs.w %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_s_h.c b/tests/tcg/mips/mips32-dsp/extr_s_h.c
new file mode 100644
index 0000000..1d0e180
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_s_h.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ result = 0x00007FFF;
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr_s.h %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extr_w.c b/tests/tcg/mips/mips32-dsp/extr_w.c
new file mode 100644
index 0000000..961cd2e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extr_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ result = 0xA0001699;
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "extr.w %0, $ac1, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "=r"(dsp)
+ : "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_r_w.c b/tests/tcg/mips/mips32-dsp/extrv_r_w.c
new file mode 100644
index 0000000..d84bd5f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_r_w.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ rs = 0x03;
+ result = 0xA0001699;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "extrv_r.w %0, $ac1, %2\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(rs), "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_rs_w.c b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c
new file mode 100644
index 0000000..ac28b20
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_rs_w.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ rs = 0x03;
+ result = 0x7FFFFFFF;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "extrv_rs.w %0, $ac1, %2\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(rs), "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_s_h.c b/tests/tcg/mips/mips32-dsp/extrv_s_h.c
new file mode 100644
index 0000000..93d49c3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_s_h.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ rs = 0x03;
+ result = 0x00007FFF;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "extrv_s.h %0, $ac1, %2\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(rs), "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/extrv_w.c b/tests/tcg/mips/mips32-dsp/extrv_w.c
new file mode 100644
index 0000000..d596f72
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/extrv_w.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, ach, acl, dsp;
+ int result;
+
+ ach = 0x05;
+ acl = 0xB4CB;
+ dsp = 0x07;
+ rs = 0x03;
+ result = 0xA0001699;
+
+ __asm volatile
+ ("wrdsp %1, 0x01\n\t"
+ "mthi %3, $ac1\n\t"
+ "mtlo %4, $ac1\n\t"
+ "extrv.w %0, $ac1, %2\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rt), "+r"(dsp)
+ : "r"(rs), "r"(ach), "r"(acl)
+ );
+ dsp = (dsp >> 23) & 0x01;
+ assert(dsp == 1);
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/insv.c b/tests/tcg/mips/mips32-dsp/insv.c
new file mode 100644
index 0000000..4020f43
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/insv.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs, dsp;
+ int result;
+
+ /* msb = 10, lsb = 5 */
+ dsp = 0x305;
+ rt = 0x12345678;
+ rs = 0x87654321;
+ result = 0x12345338;
+ __asm volatile
+ ("wrdsp %2, 0x03\n\t"
+ "insv %0, %1 \n\t"
+ : "+r"(rt)
+ : "r"(rs), "r"(dsp)
+ );
+ assert(rt == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/lbux.c b/tests/tcg/mips/mips32-dsp/lbux.c
new file mode 100644
index 0000000..37e2692
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/lbux.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int value, index, rd;
+ int result;
+
+ value = 0xBCDEF389;
+ index = 28;
+ result = value & 0xFF;
+ __asm volatile
+ ("lw $10, 28($fp)\n\t"
+ "sw %2, 28($fp)\n\t"
+ "lbux %0, %1($fp)\n\t"
+ "sw $10, 28($fp)\n\t"
+ : "=r"(rd)
+ : "r"(index), "r"(value)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/lhx.c b/tests/tcg/mips/mips32-dsp/lhx.c
new file mode 100644
index 0000000..033f7e4
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/lhx.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int value, index, rd;
+ int result;
+
+ value = 0xBCDEF389;
+ index = 28;
+ result = 0xFFFFF389;
+ __asm volatile
+ ("lw $10, 28($fp)\n\t"
+ "sw %2, 28($fp)\n\t"
+ "lhx %0, %1($fp)\n\t"
+ "sw $10, 28($fp)\n\t"
+ : "=r"(rd)
+ : "r"(index), "r"(value)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/lwx.c b/tests/tcg/mips/mips32-dsp/lwx.c
new file mode 100644
index 0000000..381b15c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/lwx.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int value, index, rd;
+ int result;
+
+ value = 0xBCDEF389;
+ index = 28;
+ result = value;
+ __asm volatile
+ ("lw $10, 28($fp)\n\t"
+ "sw %2, 28($fp)\n\t"
+ "lwx %0, %1($fp)\n\t"
+ "sw $10, 28($fp)\n\t"
+ : "=r"(rd)
+ : "r"(index), "r"(value)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/madd.c b/tests/tcg/mips/mips32-dsp/madd.c
new file mode 100644
index 0000000..5dc0bad
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/madd.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int acho, aclo;
+ int resulth, resultl;
+
+ achi = 0x05;
+ acli = 0xB4CB;
+ rs = 0x01;
+ rt = 0x01;
+ resulth = 0x05;
+ resultl = 0xB4CC;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "madd $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maddu.c b/tests/tcg/mips/mips32-dsp/maddu.c
new file mode 100644
index 0000000..5dc0bad
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maddu.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int acho, aclo;
+ int resulth, resultl;
+
+ achi = 0x05;
+ acli = 0xB4CB;
+ rs = 0x01;
+ rt = 0x01;
+ resulth = 0x05;
+ resultl = 0xB4CC;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "madd $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
new file mode 100644
index 0000000..40f3996
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phl.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int acho, aclo;
+ int resulth, resultl;
+
+ achi = 0x05;
+ acli = 0xB4CB;
+ rs = 0xFF060000;
+ rt = 0xCB000000;
+ resulth = 0x04;
+ resultl = 0x947438CB;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "maq_s.w.phl $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
new file mode 100644
index 0000000..5c1fddb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_s_w_phr.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int acho, aclo;
+ int resulth, resultl;
+
+ achi = 0x05;
+ acli = 0xB4CB;
+ rs = 0xFF06;
+ rt = 0xCB00;
+ resulth = 0x04;
+ resultl = 0x947438CB;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "maq_s.w.phr $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c b/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
new file mode 100644
index 0000000..6f9a9d2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_sa_w_phl.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int acho, aclo;
+ int resulth, resultl;
+
+ achi = 0x05;
+ acli = 0xB4CB;
+ rs = 0xFF060000;
+ rt = 0xCB000000;
+ resulth = 0xFFFFFFFF;
+ resultl = 0x80000000;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "maq_sa.w.phl $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c b/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
new file mode 100644
index 0000000..ec09e5c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/maq_sa_w_phr.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rt, rs;
+ int achi, acli;
+ int acho, aclo;
+ int resulth, resultl;
+
+ achi = 0x05;
+ acli = 0xB4CB;
+ rs = 0xFF06;
+ rt = 0xCB00;
+ resulth = 0xFFFFFFFF;
+ resultl = 0x80000000;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "maq_sa.w.phr $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(resulth == acho);
+ assert(resultl == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mfhi.c b/tests/tcg/mips/mips32-dsp/mfhi.c
new file mode 100644
index 0000000..fd33824
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mfhi.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int achi, acho;
+ int result;
+
+ achi = 0x004433;
+ result = 0x004433;
+
+ __asm volatile
+ ("mthi %1, $ac1\n\t"
+ "mfhi %0, $ac1\n\t"
+ : "=r"(acho)
+ : "r"(achi)
+ );
+ assert(result == acho);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mflo.c b/tests/tcg/mips/mips32-dsp/mflo.c
new file mode 100644
index 0000000..f3520ac
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mflo.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int acli, aclo;
+ int result;
+
+ acli = 0x004433;
+ result = 0x004433;
+
+ __asm volatile
+ ("mthi %1, $ac1\n\t"
+ "mfhi %0, $ac1\n\t"
+ : "=r"(aclo)
+ : "r"(acli)
+ );
+ assert(result == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/modsub.c b/tests/tcg/mips/mips32-dsp/modsub.c
new file mode 100644
index 0000000..1e91e27
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/modsub.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0xFFFFFFFF;
+ rt = 0x000000FF;
+ result = 0xFFFFFF00;
+ __asm volatile
+ ("modsub %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ rs = 0x00000000;
+ rt = 0x00CD1FFF;
+ result = 0x0000CD1F;
+ __asm volatile
+ ("modsub %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/msub.c b/tests/tcg/mips/mips32-dsp/msub.c
new file mode 100644
index 0000000..277ef74
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/msub.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int achi, acli, rs, rt;
+ int acho, aclo;
+ int resulth, resultl;
+
+ rs = 0x00BBAACC;
+ rt = 0x0B1C3D2F;
+ achi = 0x00004433;
+ acli = 0xFFCC0011;
+ resulth = 0xFFF81F29;
+ resultl = 0xB355089D;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "msub $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(acho == resulth);
+ assert(aclo == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/msubu.c b/tests/tcg/mips/mips32-dsp/msubu.c
new file mode 100644
index 0000000..04eda52
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/msubu.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int achi, acli, rs, rt;
+ int acho, aclo;
+ int resulth, resultl;
+
+ rs = 0x00BBAACC;
+ rt = 0x0B1C3D2F;
+ achi = 0x00004433;
+ acli = 0xFFCC0011;
+ resulth = 0xFFF81F29;
+ resultl = 0xB355089D;
+
+ __asm volatile
+ ("mthi %2, $ac1\n\t"
+ "mtlo %3, $ac1\n\t"
+ "msubu $ac1, %4, %5\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(acho), "=r"(aclo)
+ : "r"(achi), "r"(acli), "r"(rs), "r"(rt)
+ );
+ assert(acho == resulth);
+ assert(aclo == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mthi.c b/tests/tcg/mips/mips32-dsp/mthi.c
new file mode 100644
index 0000000..fd33824
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mthi.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int achi, acho;
+ int result;
+
+ achi = 0x004433;
+ result = 0x004433;
+
+ __asm volatile
+ ("mthi %1, $ac1\n\t"
+ "mfhi %0, $ac1\n\t"
+ : "=r"(acho)
+ : "r"(achi)
+ );
+ assert(result == acho);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mthlip.c b/tests/tcg/mips/mips32-dsp/mthlip.c
new file mode 100644
index 0000000..5c47fdc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mthlip.c
@@ -0,0 +1,34 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, ach, acl, dsp;
+ int result, resulth, resultl;
+
+ dsp = 0x07;
+ ach = 0x05;
+ acl = 0xB4CB;
+ rs = 0x00FFBBAA;
+ resulth = 0xB4CB;
+ resultl = 0x00FFBBAA;
+ result = 0x27;
+
+ __asm volatile
+ ("wrdsp %0, 0x01\n\t"
+ "mthi %1, $ac1\n\t"
+ "mtlo %2, $ac1\n\t"
+ "mthlip %3, $ac1\n\t"
+ "mfhi %1, $ac1\n\t"
+ "mflo %2, $ac1\n\t"
+ "rddsp %0\n\t"
+ : "+r"(dsp), "+r"(ach), "+r"(acl)
+ : "r"(rs)
+ );
+ dsp = dsp & 0x3F;
+ assert(dsp == result);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mtlo.c b/tests/tcg/mips/mips32-dsp/mtlo.c
new file mode 100644
index 0000000..f3520ac
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mtlo.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int acli, aclo;
+ int result;
+
+ acli = 0x004433;
+ result = 0x004433;
+
+ __asm volatile
+ ("mthi %1, $ac1\n\t"
+ "mfhi %0, $ac1\n\t"
+ : "=r"(aclo)
+ : "r"(acli)
+ );
+ assert(result == aclo);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c b/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
new file mode 100644
index 0000000..d036090
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleq_s_w_phr.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x8000;
+ rt = 0x8000;
+ result = 0x7FFFFFFF;
+ resultdsp = 1;
+
+ __asm volatile
+ ("muleq_s.w.phr %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ rs = 0x1234;
+ rt = 0x4321;
+ result = 0x98be968;
+ resultdsp = 1;
+
+ __asm volatile
+ ("muleq_s.w.phr %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
new file mode 100644
index 0000000..23e4156
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbl.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80001234;
+ rt = 0x80004321;
+ result = 0xFFFF0000;
+ resultdsp = 1;
+
+ __asm volatile
+ ("muleu_s.ph.qbl %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
new file mode 100644
index 0000000..b404709
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/muleu_s_ph_qbr.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x8000;
+ rt = 0x80004321;
+ result = 0xFFFF0000;
+ resultdsp = 1;
+
+ __asm volatile
+ ("muleu_s.ph.qbr %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
new file mode 100644
index 0000000..0f35ea5
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mulq_rs_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80001234;
+ rt = 0x80004321;
+ result = 0x7FFF098C;
+ resultdsp = 1;
+
+ __asm volatile
+ ("mulq_rs.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/mult.c b/tests/tcg/mips/mips32-dsp/mult.c
new file mode 100644
index 0000000..a7e2bcf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/mult.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, ach, acl;
+ int result, resulth, resultl;
+
+ rs = 0x00FFBBAA;
+ rt = 0x4B231000;
+ resulth = 0x4b0f01;
+ resultl = 0x71f8a000;
+ __asm volatile
+ ("mult $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(ach), "=r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/multu.c b/tests/tcg/mips/mips32-dsp/multu.c
new file mode 100644
index 0000000..a7e2bcf
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/multu.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, ach, acl;
+ int result, resulth, resultl;
+
+ rs = 0x00FFBBAA;
+ rt = 0x4B231000;
+ resulth = 0x4b0f01;
+ resultl = 0x71f8a000;
+ __asm volatile
+ ("mult $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "=r"(ach), "=r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/packrl_ph.c b/tests/tcg/mips/mips32-dsp/packrl_ph.c
new file mode 100644
index 0000000..531aa8a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/packrl_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x56788765;
+
+ __asm volatile
+ ("packrl.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/pick_ph.c b/tests/tcg/mips/mips32-dsp/pick_ph.c
new file mode 100644
index 0000000..2fa1c78
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/pick_ph.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x0A000000;
+ result = 0x12344321;
+
+ __asm volatile
+ ("wrdsp %3, 0x10 \n\t"
+ "pick.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dsp)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/pick_qb.c b/tests/tcg/mips/mips32-dsp/pick_qb.c
new file mode 100644
index 0000000..562cb17
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/pick_qb.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ dsp = 0x0A000000;
+ result = 0x12655621;
+
+ __asm volatile
+ ("wrdsp %3, 0x10 \n\t"
+ "pick.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt), "r"(dsp)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceq_w_phl.c b/tests/tcg/mips/mips32-dsp/preceq_w_phl.c
new file mode 100644
index 0000000..28d6480
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceq_w_phl.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x87650000;
+
+ __asm volatile
+ ("preceq.w.phl %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceq_w_phr.c b/tests/tcg/mips/mips32-dsp/preceq_w_phr.c
new file mode 100644
index 0000000..c671294
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceq_w_phr.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x43210000;
+
+ __asm volatile
+ ("preceq.w.phr %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
new file mode 100644
index 0000000..e590f8c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbl.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x43803280;
+
+ __asm volatile
+ ("precequ.ph.qbl %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
new file mode 100644
index 0000000..99efb1f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbla.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x43802180;
+
+ __asm volatile
+ ("precequ.ph.qbla %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
new file mode 100644
index 0000000..3a1b36a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbr.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x21801080;
+
+ __asm volatile
+ ("precequ.ph.qbr %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c b/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
new file mode 100644
index 0000000..f7fd85b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precequ_ph_qbra.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x32801080;
+
+ __asm volatile
+ ("precequ.ph.qbra %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
new file mode 100644
index 0000000..1b91b4b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbl.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x00870065;
+
+ __asm volatile
+ ("preceu.ph.qbl %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
new file mode 100644
index 0000000..ef085fc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbla.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x00870043;
+
+ __asm volatile
+ ("preceu.ph.qbla %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
new file mode 100644
index 0000000..2468d1a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbr.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x00430021;
+
+ __asm volatile
+ ("preceu.ph.qbr %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c b/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
new file mode 100644
index 0000000..073b4c8
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/preceu_ph_qbra.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0x00650021;
+
+ __asm volatile
+ ("preceu.ph.qbra %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrq_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_ph_w.c
new file mode 100644
index 0000000..5dfaba6
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrq_ph_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x12348765;
+
+ __asm volatile
+ ("precrq.ph.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c b/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
new file mode 100644
index 0000000..cdacffb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrq_qb_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x12568743;
+
+ __asm volatile
+ ("precrq.qb.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
new file mode 100644
index 0000000..ea433ca
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrq_rs_ph_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x12348765;
+
+ __asm volatile
+ ("precrq_rs.ph.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c b/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
new file mode 100644
index 0000000..ea63d19
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/precrqu_s_qb_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x24AC0086;
+
+ __asm volatile
+ ("precrqu_s.qb.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/raddu_w_qb.c b/tests/tcg/mips/mips32-dsp/raddu_w_qb.c
new file mode 100644
index 0000000..9cd03be
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/raddu_w_qb.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs;
+ int result;
+
+ rs = 0x12345678;
+ result = 0x114;
+
+ __asm volatile
+ ("raddu.w.qb %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/rddsp.c b/tests/tcg/mips/mips32-dsp/rddsp.c
new file mode 100644
index 0000000..0a1ae62
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/rddsp.c
@@ -0,0 +1,54 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int dsp_i, dsp_o;
+ int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i;
+ int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o;
+ int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r;
+
+ ccond_i = 0x000000BC;/* 4 */
+ outflag_i = 0x0000001B;/* 3 */
+ efi_i = 0x00000001;/* 5 */
+ c_i = 0x00000001;/* 2 */
+ scount_i = 0x0000000F;/* 1 */
+ pos_i = 0x0000000C;/* 0 */
+
+ dsp_i = (ccond_i << 24) | \
+ (outflag_i << 16) | \
+ (efi_i << 14) | \
+ (c_i << 13) | \
+ (scount_i << 7) | \
+ pos_i;
+
+ ccond_r = ccond_i;
+ outflag_r = outflag_i;
+ efi_r = efi_i;
+ c_r = c_i;
+ scount_r = scount_i;
+ pos_r = pos_i;
+
+ __asm volatile
+ ("wrdsp %1, 0x3F\n\t"
+ "rddsp %0, 0x3F\n\t"
+ : "=r"(dsp_o)
+ : "r"(dsp_i)
+ );
+
+ ccond_o = (dsp_o >> 24) & 0xFF;
+ outflag_o = (dsp_o >> 16) & 0xFF;
+ efi_o = (dsp_o >> 14) & 0x01;
+ c_o = (dsp_o >> 14) & 0x01;
+ scount_o = (dsp_o >> 7) & 0x3F;
+ pos_o = dsp_o & 0x1F;
+
+ assert(ccond_o == ccond_r);
+ assert(outflag_o == outflag_r);
+ assert(efi_o == efi_r);
+ assert(c_o == c_r);
+ assert(scount_o == scount_r);
+ assert(pos_o == pos_r);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/repl_ph.c b/tests/tcg/mips/mips32-dsp/repl_ph.c
new file mode 100644
index 0000000..ec1dd51
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/repl_ph.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, result;
+
+ result = 0x01BF01BF;
+ __asm volatile
+ ("repl.ph %0, 0x1BF\n\t"
+ : "=r"(rd)
+ );
+ assert(rd == result);
+
+ result = 0xFE00FE00;
+ __asm volatile
+ ("repl.ph %0, -512\n\t"
+ : "=r"(rd)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/repl_qb.c b/tests/tcg/mips/mips32-dsp/repl_qb.c
new file mode 100644
index 0000000..c7d0122
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/repl_qb.c
@@ -0,0 +1,16 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, result;
+
+ result = 0xBFBFBFBF;
+ __asm volatile
+ ("repl.qb %0, 0xBF\n\t"
+ : "=r"(rd)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/replv_ph.c b/tests/tcg/mips/mips32-dsp/replv_ph.c
new file mode 100644
index 0000000..a4fab74
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/replv_ph.c
@@ -0,0 +1,19 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x56785678;
+ __asm volatile
+ ("replv.ph %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/replv_qb.c b/tests/tcg/mips/mips32-dsp/replv_qb.c
new file mode 100644
index 0000000..6ef43fe
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/replv_qb.c
@@ -0,0 +1,19 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x78787878;
+ __asm volatile
+ ("replv.qb %0, %1\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shilo.c b/tests/tcg/mips/mips32-dsp/shilo.c
new file mode 100644
index 0000000..4e1e3d2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shilo.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int ach, acl;
+ int resulth, resultl;
+
+ ach = 0xBBAACCFF;
+ acl = 0x1C3B001D;
+
+ resulth = 0x17755;
+ resultl = 0x99fe3876;
+
+ __asm volatile
+ ("mthi %0, $ac1 \n\t"
+ "mtlo %1, $ac1 \n\t"
+ "shilo $ac1, 0x0F\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shilov.c b/tests/tcg/mips/mips32-dsp/shilov.c
new file mode 100644
index 0000000..02c97d5
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shilov.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, ach, acl;
+ int resulth, resultl;
+
+ rs = 0x0F;
+ ach = 0xBBAACCFF;
+ acl = 0x1C3B001D;
+
+ resulth = 0x17755;
+ resultl = 0x99fe3876;
+
+ __asm volatile
+ ("mthi %0, $ac1 \n\t"
+ "mtlo %1, $ac1 \n\t"
+ "shilov $ac1, %2\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_ph.c b/tests/tcg/mips/mips32-dsp/shll_ph.c
new file mode 100644
index 0000000..b514123
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_ph.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x12345678;
+ result = 0xA000C000;
+ resultdsp = 1;
+
+ __asm volatile
+ ("shll.ph %0, %2, 0x0B\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_qb.c b/tests/tcg/mips/mips32-dsp/shll_qb.c
new file mode 100644
index 0000000..a573e36
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_qb.c
@@ -0,0 +1,23 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x87654321;
+ result = 0x38281808;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("shll.qb %0, %2, 0x03\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_s_ph.c b/tests/tcg/mips/mips32-dsp/shll_s_ph.c
new file mode 100644
index 0000000..3f73388
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_s_ph.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x12345678;
+ result = 0x7FFF7FFF;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("shll_s.ph %0, %2, 0x0B\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shll_s_w.c b/tests/tcg/mips/mips32-dsp/shll_s_w.c
new file mode 100644
index 0000000..44cf45c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shll_s_w.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt, dsp;
+ int result, resultdsp;
+
+ rt = 0x12345678;
+ result = 0x7FFFFFFF;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("shll_s.w %0, %2, 0x0B\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_ph.c b/tests/tcg/mips/mips32-dsp/shllv_ph.c
new file mode 100644
index 0000000..7d08e51
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x0B;
+ rt = 0x12345678;
+ result = 0xA000C000;
+ resultdsp = 1;
+
+ __asm volatile
+ ("shllv.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt), "r"(rs)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_qb.c b/tests/tcg/mips/mips32-dsp/shllv_qb.c
new file mode 100644
index 0000000..786faec
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_qb.c
@@ -0,0 +1,24 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x03;
+ rt = 0x87654321;
+ result = 0x38281808;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("shllv.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt), "r"(rs)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_s_ph.c b/tests/tcg/mips/mips32-dsp/shllv_s_ph.c
new file mode 100644
index 0000000..c892161
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x0B;
+ rt = 0x12345678;
+ result = 0x7FFF7FFF;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("shllv_s.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt), "r"(rs)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shllv_s_w.c b/tests/tcg/mips/mips32-dsp/shllv_s_w.c
new file mode 100644
index 0000000..1cc88dc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shllv_s_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x0B;
+ rt = 0x12345678;
+ result = 0x7FFFFFFF;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("shllv_s.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rt), "r"(rs)
+ );
+ dsp = (dsp >> 22) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shra_ph.c b/tests/tcg/mips/mips32-dsp/shra_ph.c
new file mode 100644
index 0000000..9c01033
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shra_ph.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0xF0EC0864;
+
+ __asm volatile
+ ("shra.ph %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shra_r_ph.c b/tests/tcg/mips/mips32-dsp/shra_r_ph.c
new file mode 100644
index 0000000..99cb54b
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shra_r_ph.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0xF0ED0864;
+
+ __asm volatile
+ ("shra_r.ph %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shra_r_w.c b/tests/tcg/mips/mips32-dsp/shra_r_w.c
new file mode 100644
index 0000000..43bc579
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shra_r_w.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x87654321;
+ result = 0xF0ECA864;
+
+ __asm volatile
+ ("shra_r.w %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrav_ph.c b/tests/tcg/mips/mips32-dsp/shrav_ph.c
new file mode 100644
index 0000000..66a705f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrav_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x03;
+ rt = 0x87654321;
+ result = 0xF0EC0864;
+
+ __asm volatile
+ ("shrav.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrav_r_ph.c b/tests/tcg/mips/mips32-dsp/shrav_r_ph.c
new file mode 100644
index 0000000..7957a82
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrav_r_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x03;
+ rt = 0x87654321;
+ result = 0xF0ED0864;
+
+ __asm volatile
+ ("shrav_r.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrav_r_w.c b/tests/tcg/mips/mips32-dsp/shrav_r_w.c
new file mode 100644
index 0000000..fb1a36d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrav_r_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x03;
+ rt = 0x87654321;
+ result = 0xF0ECA864;
+
+ __asm volatile
+ ("shrav_r.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrl_qb.c b/tests/tcg/mips/mips32-dsp/shrl_qb.c
new file mode 100644
index 0000000..663ada8
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrl_qb.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x00010203;
+
+ __asm volatile
+ ("shrl.qb %0, %1, 0x05\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/shrlv_qb.c b/tests/tcg/mips/mips32-dsp/shrlv_qb.c
new file mode 100644
index 0000000..b0212e0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/shrlv_qb.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x05;
+ rt = 0x12345678;
+ result = 0x00010203;
+
+ __asm volatile
+ ("shrlv.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subq_ph.c b/tests/tcg/mips/mips32-dsp/subq_ph.c
new file mode 100644
index 0000000..73170a1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subq_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x8ACF1357;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subq.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subq_s_ph.c b/tests/tcg/mips/mips32-dsp/subq_s_ph.c
new file mode 100644
index 0000000..b0e7047
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subq_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x7FFF1357;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subq_s.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subq_s_w.c b/tests/tcg/mips/mips32-dsp/subq_s_w.c
new file mode 100644
index 0000000..ad7d611
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subq_s_w.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x7FFFFFFF;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subq_s.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subu_qb.c b/tests/tcg/mips/mips32-dsp/subu_qb.c
new file mode 100644
index 0000000..8806a17
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subu_qb.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x8BCF1357;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subu.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/subu_s_qb.c b/tests/tcg/mips/mips32-dsp/subu_s_qb.c
new file mode 100644
index 0000000..ea581fe
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/subu_s_qb.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x00001357;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subu_s.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dsp/wrdsp.c b/tests/tcg/mips/mips32-dsp/wrdsp.c
new file mode 100644
index 0000000..0a1ae62
--- /dev/null
+++ b/tests/tcg/mips/mips32-dsp/wrdsp.c
@@ -0,0 +1,54 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int dsp_i, dsp_o;
+ int ccond_i, outflag_i, efi_i, c_i, scount_i, pos_i;
+ int ccond_o, outflag_o, efi_o, c_o, scount_o, pos_o;
+ int ccond_r, outflag_r, efi_r, c_r, scount_r, pos_r;
+
+ ccond_i = 0x000000BC;/* 4 */
+ outflag_i = 0x0000001B;/* 3 */
+ efi_i = 0x00000001;/* 5 */
+ c_i = 0x00000001;/* 2 */
+ scount_i = 0x0000000F;/* 1 */
+ pos_i = 0x0000000C;/* 0 */
+
+ dsp_i = (ccond_i << 24) | \
+ (outflag_i << 16) | \
+ (efi_i << 14) | \
+ (c_i << 13) | \
+ (scount_i << 7) | \
+ pos_i;
+
+ ccond_r = ccond_i;
+ outflag_r = outflag_i;
+ efi_r = efi_i;
+ c_r = c_i;
+ scount_r = scount_i;
+ pos_r = pos_i;
+
+ __asm volatile
+ ("wrdsp %1, 0x3F\n\t"
+ "rddsp %0, 0x3F\n\t"
+ : "=r"(dsp_o)
+ : "r"(dsp_i)
+ );
+
+ ccond_o = (dsp_o >> 24) & 0xFF;
+ outflag_o = (dsp_o >> 16) & 0xFF;
+ efi_o = (dsp_o >> 14) & 0x01;
+ c_o = (dsp_o >> 14) & 0x01;
+ scount_o = (dsp_o >> 7) & 0x3F;
+ pos_o = dsp_o & 0x1F;
+
+ assert(ccond_o == ccond_r);
+ assert(outflag_o == outflag_r);
+ assert(efi_o == efi_r);
+ assert(c_o == c_r);
+ assert(scount_o == scount_r);
+ assert(pos_o == pos_r);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/Makefile b/tests/tcg/mips/mips32-dspr2/Makefile
new file mode 100644
index 0000000..68b5649
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/Makefile
@@ -0,0 +1,71 @@
+-include ../../config-host.mak
+
+CROSS=mipsel-unknown-linux-gnu-
+
+SIM=qemu-mipsel
+
+CC = $(CROSS)gcc
+CFLAGS = -march=mips32r2 -mgp32 -mdspr2 -static
+
+TESTCASES = absq_s_qb.tst
+TESTCASES += addqh_ph.tst
+TESTCASES += addqh_r_ph.tst
+TESTCASES += addqh_r_w.tst
+TESTCASES += addqh_w.tst
+TESTCASES += adduh_qb.tst
+TESTCASES += adduh_r_qb.tst
+TESTCASES += addu_ph.tst
+TESTCASES += addu_s_ph.tst
+TESTCASES += append.tst
+TESTCASES += balign.tst
+TESTCASES += cmpgdu_eq_qb.tst
+TESTCASES += cmpgdu_le_qb.tst
+TESTCASES += cmpgdu_lt_qb.tst
+TESTCASES += dpaqx_sa_w_ph.tst
+TESTCASES += dpa_w_ph.tst
+TESTCASES += dpax_w_ph.tst
+TESTCASES += dpaqx_s_w_ph.tst
+TESTCASES += dpsqx_sa_w_ph.tst
+TESTCASES += dpsqx_s_w_ph.tst
+TESTCASES += dps_w_ph.tst
+TESTCASES += dpsx_w_ph.tst
+TESTCASES += muleq_s_w_phl.tst
+TESTCASES += mul_ph.tst
+TESTCASES += mulq_rs_w.tst
+TESTCASES += mulq_s_ph.tst
+TESTCASES += mulq_s_w.tst
+TESTCASES += mulsaq_s_w_ph.tst
+TESTCASES += mulsa_w_ph.tst
+TESTCASES += mul_s_ph.tst
+TESTCASES += precr_qb_ph.tst
+TESTCASES += precr_sra_ph_w.tst
+TESTCASES += precr_sra_r_ph_w.tst
+TESTCASES += prepend.tst
+TESTCASES += shra_qb.tst
+TESTCASES += shra_r_qb.tst
+TESTCASES += shrav_qb.tst
+TESTCASES += shrav_r_qb.tst
+TESTCASES += shrl_ph.tst
+TESTCASES += shrlv_ph.tst
+TESTCASES += subqh_ph.tst
+TESTCASES += subqh_r_ph.tst
+TESTCASES += subqh_r_w.tst
+TESTCASES += subqh_w.tst
+TESTCASES += subuh_qb.tst
+TESTCASES += subuh_r_qb.tst
+TESTCASES += subu_ph.tst
+TESTCASES += subu_s_ph.tst
+
+all: $(TESTCASES)
+
+%.tst: %.c
+ $(CC) $(CFLAGS) $< -o $@
+
+check: $(TESTCASES)
+ @for case in $(TESTCASES); do \
+ echo $(SIM) ./$$case;\
+ $(SIM) ./$$case; \
+ done
+
+clean:
+ $(RM) -rf $(TESTCASES)
diff --git a/tests/tcg/mips/mips32-dspr2/absq_s_qb.c b/tests/tcg/mips/mips32-dspr2/absq_s_qb.c
new file mode 100644
index 0000000..416855e
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/absq_s_qb.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int input, result;
+ int hope;
+
+ input = 0x701BA35E;
+ hope = 0x701B5D5E;
+
+ __asm volatile
+ ("absq_s.qb %0, %1\n\t"
+ : "=r"(result)
+ : "r"(input)
+ );
+ assert(result == hope);
+
+
+ input = 0x801BA35E;
+ hope = 0x7F1B5D5E;
+
+ __asm volatile
+ ("absq_s.qb %0, %1\n\t"
+ : "=r"(result)
+ : "r"(input)
+ );
+ assert(result == hope);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_ph.c b/tests/tcg/mips/mips32-dspr2/addqh_ph.c
new file mode 100644
index 0000000..fac3c2c
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x706A13FE;
+ rt = 0x13065174;
+ result = 0x41B832B9;
+ __asm volatile
+ ("addqh.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0x01000100;
+ rt = 0x02000100;
+ result = 0x01800100;
+ __asm volatile
+ ("addqh.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c b/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
new file mode 100644
index 0000000..03cc135
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_r_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x706A13FE;
+ rt = 0x13065174;
+ result = 0x41B832B9;
+ __asm volatile
+ ("addqh_r.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0x01000100;
+ rt = 0x02000100;
+ result = 0x01800100;
+ __asm volatile
+ ("addqh_r.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_r_w.c b/tests/tcg/mips/mips32-dspr2/addqh_r_w.c
new file mode 100644
index 0000000..efe214d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_r_w.c
@@ -0,0 +1,34 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x00000010;
+ rt = 0x00000001;
+ result = 0x00000009;
+
+ __asm volatile
+ ("addqh_r.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ rs = 0xFFFFFFFE;
+ rt = 0x00000001;
+ result = 0x00000000;
+
+ __asm volatile
+ ("addqh_r.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addqh_w.c b/tests/tcg/mips/mips32-dspr2/addqh_w.c
new file mode 100644
index 0000000..ab3f1f5
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addqh_w.c
@@ -0,0 +1,34 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x00000010;
+ rt = 0x00000001;
+ result = 0x00000008;
+
+ __asm volatile
+ ("addqh.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ rs = 0xFFFFFFFE;
+ rt = 0x00000001;
+ result = 0xFFFFFFFF;
+
+ __asm volatile
+ ("addqh.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addu_ph.c b/tests/tcg/mips/mips32-dspr2/addu_ph.c
new file mode 100644
index 0000000..d479024
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addu_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010001;
+ result = 0x01000100;
+ __asm volatile
+ ("addu.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0x00011112;
+ __asm volatile
+ ("addu.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/addu_s_ph.c b/tests/tcg/mips/mips32-dspr2/addu_s_ph.c
new file mode 100644
index 0000000..18c26e1
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/addu_s_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x00FE00FE;
+ rt = 0x00020001;
+ result = 0x010000FF;
+ __asm volatile
+ ("addu_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF1111;
+ rt = 0x00020001;
+ result = 0xFFFF1112;
+ __asm volatile
+ ("addu_s.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/adduh_qb.c b/tests/tcg/mips/mips32-dspr2/adduh_qb.c
new file mode 100644
index 0000000..adb5da3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/adduh_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0xFF0055AA;
+ rt = 0x0113421B;
+ result = 0x80094B62;
+ __asm volatile
+ ("adduh.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF0FFF;
+ rt = 0x00010111;
+ result = 0x7F800888;
+ __asm volatile
+ ("adduh.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c b/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
new file mode 100644
index 0000000..67c8f20
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/adduh_r_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0xFF0055AA;
+ rt = 0x01112211;
+ result = 0x80093C5E;
+ __asm volatile
+ ("adduh_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0xFFFF0FFF;
+ rt = 0x00010111;
+ result = 0x80800888;
+ __asm volatile
+ ("adduh_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/append.c b/tests/tcg/mips/mips32-dspr2/append.c
new file mode 100644
index 0000000..1ba72fb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/append.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int result;
+
+ rs = 0xFF0055AA;
+ rt = 0x0113421B;
+ result = 0x02268436;
+ __asm volatile
+ ("append %0, %1, 0x01\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(rt == result);
+
+ rs = 0xFFFF0FFF;
+ rt = 0x00010111;
+ result = 0x0010111F;
+ __asm volatile
+ ("append %0, %1, 0x04\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(rt == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/balign.c b/tests/tcg/mips/mips32-dspr2/balign.c
new file mode 100644
index 0000000..d936fc2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/balign.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int result;
+
+ rs = 0xFF0055AA;
+ rt = 0x0113421B;
+ result = 0x13421BFF;
+ __asm volatile
+ ("balign %0, %1, 0x01\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(rt == result);
+
+ rs = 0xFFFF0FFF;
+ rt = 0x00010111;
+ result = 0x11FFFF0F;
+ __asm volatile
+ ("balign %0, %1, 0x03\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(rt == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
new file mode 100644
index 0000000..628b332
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_eq_qb.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x02;
+ __asm volatile
+ ("cmpgdu.eq.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(rd == result);
+ assert(dsp == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x0F;
+ __asm volatile
+ ("cmpgdu.eq.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(rd == result);
+ assert(dsp == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
new file mode 100644
index 0000000..bcdef50
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_le_qb.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x0F;
+ __asm volatile
+ ("cmpgdu.le.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(rd == result);
+ assert(dsp == result);
+
+ rs = 0x11777066;
+ rt = 0x11707066;
+ result = 0x0B;
+ __asm volatile
+ ("cmpgdu.le.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(rd == result);
+ assert(dsp == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c b/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
new file mode 100644
index 0000000..28f320f
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/cmpgdu_lt_qb.c
@@ -0,0 +1,37 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int dsp;
+ int result;
+
+ rs = 0x11777066;
+ rt = 0x55AA70FF;
+ result = 0x0D;
+ __asm volatile
+ ("cmpgdu.lt.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(rd == result);
+ assert(dsp == result);
+
+ rs = 0x11777066;
+ rt = 0x11777066;
+ result = 0x00;
+ __asm volatile
+ ("cmpgdu.lt.qb %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 24) & 0x0F;
+ assert(rd == result);
+ assert(dsp == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
new file mode 100644
index 0000000..f2e8085
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpa_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010002;
+ resulth = 0x05;
+ resultl = 0x0302;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpa.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
new file mode 100644
index 0000000..5e77cd3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpaqx_s_w_ph.c
@@ -0,0 +1,57 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 5, acl = 5;
+ int resulth, resultl, resultdsp;
+
+ rs = 0x800000FF;
+ rt = 0x00018000;
+ resulth = 0x05;
+ resultl = 0x80000202;
+ resultdsp = 0x01;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpaqx_s.w.ph $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2 \n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ ach = 5;
+ acl = 5;
+ rs = 0x00FF00FF;
+ rt = 0x00010002;
+ resulth = 0x05;
+ resultl = 0x05FF;
+ /***********************************************************
+ * Because of we set outflag at last time, although this
+ * time we set nothing, but it is stay the last time value.
+ **********************************************************/
+ resultdsp = 0x01;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpaqx_s.w.ph $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2 \n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
new file mode 100644
index 0000000..e00e433
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpaqx_sa_w_ph.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 5, acl = 5;
+ int resulth, resultl, resultdsp;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010002;
+ resulth = 0x05;
+ resultl = 0x05FF;
+ resultdsp = 0x00;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpaqx_sa.w.ph $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2 \n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
new file mode 100644
index 0000000..69917f3
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpax_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010002;
+ resulth = 0x05;
+ resultl = 0x0302;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpax.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dps_w_ph.c b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c
new file mode 100644
index 0000000..c801476
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dps_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0x00FF00FF;
+ rt = 0x00010002;
+ resulth = 0x04;
+ resultl = 0xFFFFFD08;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dps.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
new file mode 100644
index 0000000..f08f162
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpsqx_s_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 5, acl = 5;
+ int resulth, resultl, resultdsp;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x04;
+ resultl = 0xAEA3E09B;
+ resultdsp = 0x00;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsqx_s.w.ph $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2\n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
new file mode 100644
index 0000000..3e192e2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpsqx_sa_w_ph.c
@@ -0,0 +1,31 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, dsp;
+ int ach = 5, acl = 5;
+ int resulth, resultl, resultdsp;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x00;
+ resultl = 0x7FFFFFFF;
+ resultdsp = 0x01;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsqx_sa.w.ph $ac1, %3, %4\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ "rddsp %2\n\t"
+ : "+r"(ach), "+r"(acl), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 17) & 0x01;
+ assert(dsp == resultdsp);
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
new file mode 100644
index 0000000..c695423
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/dpsx_w_ph.c
@@ -0,0 +1,27 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int ach = 5, acl = 5;
+ int resulth, resultl;
+
+ rs = 0xBC0123AD;
+ rt = 0x01643721;
+ resulth = 0x04;
+ resultl = 0xD751F050;
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "dpsx.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1 \n\t"
+ "mflo %1, $ac1 \n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mul_ph.c b/tests/tcg/mips/mips32-dspr2/mul_ph.c
new file mode 100644
index 0000000..28d0cac
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mul_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x03FB1234;
+ rt = 0x0BCC4321;
+ result = 0xF504F4B4;
+ resultdsp = 1;
+
+ __asm volatile
+ ("mul.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mul_s_ph.c b/tests/tcg/mips/mips32-dspr2/mul_s_ph.c
new file mode 100644
index 0000000..19f48ca
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mul_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x03FB1234;
+ rt = 0x0BCC4321;
+ result = 0x7fff7FFF;
+ resultdsp = 1;
+
+ __asm volatile
+ ("mul_s.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c b/tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
new file mode 100644
index 0000000..94e7512
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/muleq_s_w_phl.c
@@ -0,0 +1,40 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80001234;
+ rt = 0x80004321;
+ result = 0x7FFFFFFF;
+ resultdsp = 1;
+
+ __asm volatile
+ ("muleq_s.w.phl %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ rs = 0x12340000;
+ rt = 0x43210000;
+ result = 0x98be968;
+ resultdsp = 1;
+
+ __asm volatile
+ ("muleq_s.w.phl %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c b/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
new file mode 100644
index 0000000..0081bab
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulq_rs_w.c
@@ -0,0 +1,36 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80001234;
+ rt = 0x80004321;
+ result = 0x80005555;
+
+ __asm volatile
+ ("mulq_rs.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0x80000000;
+ rt = 0x80000000;
+ result = 0x7FFFFFFF;
+ resultdsp = 1;
+
+ __asm volatile
+ ("mulq_rs.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c b/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
new file mode 100644
index 0000000..edf2ed0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulq_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80001234;
+ rt = 0x80004321;
+ result = 0x7FFF098B;
+ resultdsp = 1;
+
+ __asm volatile
+ ("mulq_s.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulq_s_w.c b/tests/tcg/mips/mips32-dspr2/mulq_s_w.c
new file mode 100644
index 0000000..951a5ce
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulq_s_w.c
@@ -0,0 +1,36 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x80001234;
+ rt = 0x80004321;
+ result = 0x80005555;
+
+ __asm volatile
+ ("mulq_s.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ rs = 0x80000000;
+ rt = 0x80000000;
+ result = 0x7FFFFFFF;
+ resultdsp = 1;
+
+ __asm volatile
+ ("mulq_s.w %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 21) & 0x01;
+ assert(rd == result);
+ assert(dsp == resultdsp);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c b/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
new file mode 100644
index 0000000..73e46c6
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulsa_w_ph.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, ach, acl;
+ int resulth, resultl;
+
+ ach = 0x05;
+ acl = 0x00BBDDCC;
+ rs = 0x80001234;
+ rt = 0x80004321;
+ resulth = 0x05;
+ resultl = 0x3BF5E918;
+
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "mulsa.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c b/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
new file mode 100644
index 0000000..2ec2629
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/mulsaq_s_w_ph.c
@@ -0,0 +1,29 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt, ach, acl;
+ int resulth, resultl;
+
+ ach = 0x05;
+ acl = 0x00BBDDCC;
+ rs = 0x80001234;
+ rt = 0x80004321;
+ resulth = 0x05;
+ resultl = 0x772ff463;
+
+ __asm volatile
+ ("mthi %0, $ac1\n\t"
+ "mtlo %1, $ac1\n\t"
+ "mulsaq_s.w.ph $ac1, %2, %3\n\t"
+ "mfhi %0, $ac1\n\t"
+ "mflo %1, $ac1\n\t"
+ : "+r"(ach), "+r"(acl)
+ : "r"(rs), "r"(rt)
+ );
+ assert(ach == resulth);
+ assert(acl == resultl);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c b/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
new file mode 100644
index 0000000..887c2c2
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/precr_qb_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x34786521;
+
+ __asm volatile
+ ("precr.qb.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(result == rd);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c b/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
new file mode 100644
index 0000000..4665210
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/precr_sra_ph_w.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x43215678;
+
+ __asm volatile
+ ("precr_sra.ph.w %0, %1, 0x00\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(result == rt);
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0xFFFF0000;
+
+ __asm volatile
+ ("precr_sra.ph.w %0, %1, 0x1F\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c b/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
new file mode 100644
index 0000000..922b67d
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/precr_sra_r_ph_w.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x43215678;
+
+ __asm volatile
+ ("precr_sra_r.ph.w %0, %1, 0x00\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(result == rt);
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0xFFFF0000;
+
+ __asm volatile
+ ("precr_sra_r.ph.w %0, %1, 0x1F\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(result == rt);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/prepend.c b/tests/tcg/mips/mips32-dspr2/prepend.c
new file mode 100644
index 0000000..017a92a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/prepend.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x87654321;
+ __asm volatile
+ ("prepend %0, %1, 0x00\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(rt == result);
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0xACF10ECA;
+ __asm volatile
+ ("prepend %0, %1, 0x0F\n\t"
+ : "+r"(rt)
+ : "r"(rs)
+ );
+ assert(rt == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shra_qb.c b/tests/tcg/mips/mips32-dspr2/shra_qb.c
new file mode 100644
index 0000000..d2e04da
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shra_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x02060A0F;
+
+ __asm volatile
+ ("shra.qb %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x87654321;
+ result = 0xF00C0804;
+
+ __asm volatile
+ ("shra.qb %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shra_r_qb.c b/tests/tcg/mips/mips32-dspr2/shra_r_qb.c
new file mode 100644
index 0000000..f8176ac
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shra_r_qb.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x02070B0F;
+
+ __asm volatile
+ ("shra_r.qb %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ rt = 0x87654321;
+ result = 0xF10D0804;
+
+ __asm volatile
+ ("shra_r.qb %0, %1, 0x03\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrav_qb.c b/tests/tcg/mips/mips32-dspr2/shrav_qb.c
new file mode 100644
index 0000000..0037735
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrav_qb.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x03;
+ rt = 0x12345678;
+ result = 0x02060A0F;
+
+ __asm volatile
+ ("shrav.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ rs = 0x03;
+ rt = 0x87654321;
+ result = 0xF00C0804;
+
+ __asm volatile
+ ("shrav.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c b/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
new file mode 100644
index 0000000..088e414
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrav_r_qb.c
@@ -0,0 +1,32 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x03;
+ rt = 0x12345678;
+ result = 0x02070B0F;
+
+ __asm volatile
+ ("shrav_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ rs = 0x03;
+ rt = 0x87654321;
+ result = 0xF10D0804;
+
+ __asm volatile
+ ("shrav_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrl_ph.c b/tests/tcg/mips/mips32-dspr2/shrl_ph.c
new file mode 100644
index 0000000..6cddebc
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrl_ph.c
@@ -0,0 +1,20 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rt;
+ int result;
+
+ rt = 0x12345678;
+ result = 0x009102B3;
+
+ __asm volatile
+ ("shrl.ph %0, %1, 0x05\n\t"
+ : "=r"(rd)
+ : "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/shrlv_ph.c b/tests/tcg/mips/mips32-dspr2/shrlv_ph.c
new file mode 100644
index 0000000..fb869ad
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/shrlv_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x05;
+ rt = 0x12345678;
+ result = 0x009102B3;
+
+ __asm volatile
+ ("shrlv.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rt), "r"(rs)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_ph.c b/tests/tcg/mips/mips32-dspr2/subqh_ph.c
new file mode 100644
index 0000000..444344a
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x456709AB;
+
+ __asm volatile
+ ("subqh.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c b/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
new file mode 100644
index 0000000..1a9aaa9
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_r_ph.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x456809AC;
+
+ __asm volatile
+ ("subqh_r.ph %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_r_w.c b/tests/tcg/mips/mips32-dspr2/subqh_r_w.c
new file mode 100644
index 0000000..db14b39
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_r_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x456789AC;
+
+ __asm volatile
+ ("subqh_r.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subqh_w.c b/tests/tcg/mips/mips32-dspr2/subqh_w.c
new file mode 100644
index 0000000..896b7d0
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subqh_w.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x456789AB;
+
+ __asm volatile
+ ("subqh.w %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subu_ph.c b/tests/tcg/mips/mips32-dspr2/subu_ph.c
new file mode 100644
index 0000000..c0f3658
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subu_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x7531ECA9;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subu.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subu_s_ph.c b/tests/tcg/mips/mips32-dspr2/subu_s_ph.c
new file mode 100644
index 0000000..1605deb
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subu_s_ph.c
@@ -0,0 +1,25 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt, dsp;
+ int result, resultdsp;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0x75310000;
+ resultdsp = 0x01;
+
+ __asm volatile
+ ("subu_s.ph %0, %2, %3\n\t"
+ "rddsp %1\n\t"
+ : "=r"(rd), "=r"(dsp)
+ : "r"(rs), "r"(rt)
+ );
+ dsp = (dsp >> 20) & 0x01;
+ assert(dsp == resultdsp);
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subuh_qb.c b/tests/tcg/mips/mips32-dspr2/subuh_qb.c
new file mode 100644
index 0000000..f077982
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subuh_qb.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0xC5E7092B;
+
+ __asm volatile
+ ("subuh.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
diff --git a/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c b/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
new file mode 100644
index 0000000..d661d75
--- /dev/null
+++ b/tests/tcg/mips/mips32-dspr2/subuh_r_qb.c
@@ -0,0 +1,21 @@
+#include<stdio.h>
+#include<assert.h>
+
+int main()
+{
+ int rd, rs, rt;
+ int result;
+
+ rs = 0x12345678;
+ rt = 0x87654321;
+ result = 0xC6E80A2C;
+
+ __asm volatile
+ ("subuh_r.qb %0, %1, %2\n\t"
+ : "=r"(rd)
+ : "r"(rs), "r"(rt)
+ );
+ assert(rd == result);
+
+ return 0;
+}
--
1.7.5.4
^ permalink raw reply related [flat|nested] 33+ messages in thread