From: Aurelien Jarno <aurelien@aurel32.net>
To: Jia Liu <proljc@gmail.com>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions
Date: Thu, 23 Aug 2012 15:31:24 +0200 [thread overview]
Message-ID: <20120823133124.GB3553@ohm.aurel32.net> (raw)
In-Reply-To: <1345531999-17872-2-git-send-email-proljc@gmail.com>
On Tue, Aug 21, 2012 at 02:53:07PM +0800, Jia Liu wrote:
> Add internal functions using by MIPS ASE DSP instructions.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
> target-mips/Makefile.objs | 2 +-
> target-mips/dsp_helper.c | 1277 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 1278 insertions(+), 1 deletion(-)
> create mode 100644 target-mips/dsp_helper.c
Looks fine to me.
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
> diff --git a/target-mips/Makefile.objs b/target-mips/Makefile.objs
> index 2e0e093..55b252d 100644
> --- a/target-mips/Makefile.objs
> +++ b/target-mips/Makefile.objs
> @@ -1,4 +1,4 @@
> -obj-y += translate.o op_helper.o helper.o cpu.o
> +obj-y += translate.o dsp_helper.o op_helper.o helper.o cpu.o
> obj-$(CONFIG_SOFTMMU) += machine.o
>
> $(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
> diff --git a/target-mips/dsp_helper.c b/target-mips/dsp_helper.c
> new file mode 100644
> index 0000000..a7d6c7e
> --- /dev/null
> +++ b/target-mips/dsp_helper.c
> @@ -0,0 +1,1277 @@
> +/*
> + * MIPS ASE DSP Instruction emulation helpers for QEMU.
> + *
> + * Copyright (c) 2012 Jia Liu <proljc@gmail.com>
> + * Dongxue Zhang <elat.era@gmail.com>
> + * 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"
> +
> +/*** MIPS DSP internal functions begin ***/
> +static inline int not_word_value(target_long value)
> +{
> + target_ulong temp;
> +
> + temp = (target_long)(int32_t)(value & 0xFFFFFFFF);
> + if (value == temp) {
> + return 0;
> + } else {
> + return 1;
> + }
> +}
> +
> +static inline void set_DSPControl_overflow_flag(CPUMIPSState *env,
> + uint32_t flag, int position)
> +{
> + env->active_tc.DSPControl |= (target_ulong)flag << position;
> +}
> +
> +static inline void set_DSPControl_carryflag(CPUMIPSState *env, uint32_t flag)
> +{
> + env->active_tc.DSPControl |= (target_ulong)flag << 13;
> +}
> +
> +static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
> +{
> + uint32_t flag;
> +
> + flag = (env->active_tc.DSPControl >> 13) & 0x01;
> +
> + return flag;
> +}
> +
> +static inline void set_DSPControl_24(CPUMIPSState *env, uint32_t flag, int len)
> +{
> + uint32_t filter;
> +
> + filter = ((0x01 << len) - 1) << 24;
> + filter = ~filter;
> +
> + env->active_tc.DSPControl &= filter;
> + env->active_tc.DSPControl |= (target_ulong)flag << 24;
> +}
> +
> +static inline uint32_t get_DSPControl_24(CPUMIPSState *env, int len)
> +{
> + uint32_t cond;
> + uint32_t filter;
> +
> + filter = (0x01 << len) - 1;
> +
> + cond = (env->active_tc.DSPControl >> 24) & filter;
> +
> + return cond;
> +}
> +
> +static inline void set_DSPControl_pos(CPUMIPSState *env, uint32_t pos)
> +{
> + target_ulong dspc;
> +
> + dspc = env->active_tc.DSPControl;
> +#ifndef TARGET_MIPS64
> + dspc = dspc & 0xFFFFFFC0;
> + dspc |= pos;
> +#else
> + dspc = dspc & 0xFFFFFF80;
> + dspc |= pos;
> +#endif
> + env->active_tc.DSPControl = dspc;
> +}
> +
> +static inline uint32_t get_DSPControl_pos(CPUMIPSState *env)
> +{
> + target_ulong dspc;
> + uint32_t pos;
> +
> + dspc = env->active_tc.DSPControl;
> +
> +#ifndef TARGET_MIPS64
> + pos = dspc & 0x3F;
> +#else
> + pos = dspc & 0x7F;
> +#endif
> +
> + return pos;
> +}
> +
> +static inline void set_DSPControl_efi(CPUMIPSState *env, 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(CPUMIPSState *env, uint8_t a)
> +{
> + int8_t temp;
> + temp = a;
> +
> + if (a == 0x80) {
> + set_DSPControl_overflow_flag(env, 1, 20);
> + temp = 0x7f;
> + } else {
> + if ((a & 0x80) == 0x80) {
> + temp = -temp;
> + }
> + }
> +
> + return temp;
> +}
> +
> +static inline int16_t mipsdsp_sat_abs_u16(CPUMIPSState *env, uint16_t a)
> +{
> + int16_t temp;
> + temp = a;
> +
> + if (a == 0x8000) {
> + set_DSPControl_overflow_flag(env, 1, 20);
> + temp = 0x7fff;
> + } else {
> + if ((a & 0x8000) == 0x8000) {
> + temp = -temp;
> + }
> + }
> +
> + return temp;
> +}
> +
> +static inline int32_t mipsdsp_sat_abs_u32(CPUMIPSState *env, uint32_t a)
> +{
> + int32_t temp;
> + temp = a;
> +
> + if (a == 0x80000000) {
> + set_DSPControl_overflow_flag(env, 1, 20);
> + temp = 0x7FFFFFFF;
> + } else {
> + if ((a & 0x80000000) == 0x80000000) {
> + temp = -temp;
> + }
> + }
> +
> + return temp;
> +}
> +
> +/* get sum value */
> +static inline int16_t mipsdsp_add_i16(CPUMIPSState *env, 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(env, 1, 20);
> + }
> +
> + return tempS;
> +}
> +
> +static inline int16_t mipsdsp_sat_add_i16(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> +
> + return tempS;
> +}
> +
> +static inline int32_t mipsdsp_sat_add_i32(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> +
> + return tempI;
> +}
> +
> +static inline uint8_t mipsdsp_add_u8(CPUMIPSState *env, 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(env, 1, 20);
> + }
> +
> + return result;
> +}
> +
> +static inline uint16_t mipsdsp_add_u16(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> +
> + return result;
> +}
> +
> +static inline uint8_t mipsdsp_sat_add_u8(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> +
> + return result;
> +}
> +
> +static inline uint16_t mipsdsp_sat_add_u16(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> +
> + return result;
> +}
> +
> +static inline int32_t mipsdsp_sat32_acc_q31(CPUMIPSState *env,
> + int32_t acc, int32_t a)
> +{
> + int64_t tempA, temp;
> + int32_t temp32, temp31, result;
> + int64_t temp_sum;
> +
> +#ifndef TARGET_MIPS64
> + temp = ((uint64_t)env->active_tc.HI[acc] << 32) |
> + (uint64_t)env->active_tc.LO[acc];
> +#else
> + temp = (uint64_t)env->active_tc.LO[acc];
> +#endif
> + tempA = (int64_t)a;
> +
> + temp_sum = tempA + temp;
> +
> + temp32 = (temp_sum >> 32) & 0x01;
> + temp31 = (temp_sum >> 31) & 0x01;
> + result = temp_sum & 0xFFFFFFFF;
> +
> + if (temp32 != temp31) {
> + if (temp32 == 0) {
> + result = 0x80000000;
> + } else {
> + result = 0x7FFFFFFF;
> + }
> + set_DSPControl_overflow_flag(env, 1, 16 + acc);
> + }
> +
> + return result;
> +}
> +
> +/* a[0] is LO, a[1] is HI. */
> +static inline void mipsdsp_sat64_acc_add_q63(CPUMIPSState *env,
> + int64_t *ret,
> + int32_t ac,
> + int64_t *a)
> +{
> + uint32_t temp64, temp63;
> + int64_t temp[3];
> + int64_t acc[3];
> + int64_t temp_sum;
> +
> + temp[0] = a[0];
> + temp[1] = a[1];
> + if (((temp[1] >> 63) & 0x01) == 0) {
> + temp[2] = 0x00;
> + } else {
> + temp[2] = 0xFFFFFFFFFFFFFFFFull;
> + }
> +
> + acc[0] = env->active_tc.LO[ac];
> + acc[1] = env->active_tc.HI[ac];
> + if (((acc[1] >> 63) & 0x01) == 0) {
> + acc[2] = 0x00;
> + } else {
> + acc[2] = 0xFFFFFFFFFFFFFFFFull;
> + }
> +
> + temp_sum = temp[0] + acc[0];
> + if (((uint64_t)temp_sum < (uint64_t)temp[0]) &&
> + ((uint64_t)temp_sum < (uint64_t)acc[0])) {
> + temp[1] += 1;
> + if (temp[1] == 0) {
> + temp[2] += 1;
> + }
> + }
> + temp[0] = temp_sum;
> +
> + temp_sum = temp[1] + acc[1];
> + if (((uint64_t)temp_sum < (uint64_t)temp[1]) &&
> + ((uint64_t)temp_sum < (uint64_t)acc[1])) {
> + temp[2] += 1;
> + }
> +
> + temp[1] = temp_sum;
> + temp[2] += acc[2];
> + temp64 = temp[1] & 0x01;
> + temp63 = (temp[0] >> 63) & 0x01;
> +
> + if (temp64 != temp63) {
> + if (temp64 == 1) {
> + ret[0] = 0x8000000000000000ull;
> + ret[1] = 0xFFFFFFFFFFFFFFFFull;
> + } else {
> + ret[0] = 0x0;
> + ret[1] = 0x7FFFFFFFFFFFFFFFull;
> + }
> + set_DSPControl_overflow_flag(env, 1, 16 + ac);
> + } else {
> + ret[0] = temp[0];
> + ret[1] = temp[1];
> + }
> +}
> +
> +/* a[0] is LO, a[1] is HI. */
> +static inline void mipsdsp_sat64_acc_sub_q63(CPUMIPSState *env,
> + int64_t *ret,
> + int32_t ac,
> + int64_t *a)
> +{
> + uint32_t temp64, temp63;
> + int64_t temp[3];
> + int64_t acc[3];
> + int64_t temp_sum;
> +
> + temp[0] = a[0];
> + temp[1] = a[1];
> + if (((temp[1] >> 63) & 0x01) == 0) {
> + temp[2] = 0x00;
> + } else {
> + temp[2] = 0xFFFFFFFFFFFFFFFFull;
> + }
> +
> + acc[0] = env->active_tc.LO[ac];
> + acc[1] = env->active_tc.HI[ac];
> + if (((acc[1] >> 63) & 0x01) == 0) {
> + acc[2] = 0x00;
> + } else {
> + acc[2] = 0xFFFFFFFFFFFFFFFFull;
> + }
> +
> + temp_sum = acc[0] - temp[0];
> + if ((uint64_t)temp_sum > (uint64_t)acc[0]) {
> + acc[1] -= 1;
> + if (acc[1] == 0xFFFFFFFFFFFFFFFFull) {
> + acc[2] -= 1;
> + }
> + }
> + acc[0] = temp_sum;
> +
> + temp_sum = acc[1] - temp[1];
> + if ((uint64_t)temp_sum > (uint64_t)acc[1]) {
> + acc[2] -= 1;
> + }
> + acc[1] = temp_sum;
> + acc[2] -= temp[2];
> +
> + temp64 = acc[1] & 0x01;
> + temp63 = (acc[0] >> 63) & 0x01;
> +
> + if (temp64 != temp63) {
> + if (temp64 == 1) {
> + ret[0] = 0x8000000000000000ull;
> + ret[1] = 0xFFFFFFFFFFFFFFFFull;
> + } else {
> + ret[0] = 0x0;
> + ret[1] = 0x7FFFFFFFFFFFFFFFull;
> + }
> + set_DSPControl_overflow_flag(env, 1, 16 + ac);
> + } else {
> + ret[0] = acc[0];
> + ret[1] = acc[1];
> + }
> +}
> +
> +static inline int32_t mipsdsp_mul_i16_i16(CPUMIPSState *env,
> + 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(env, 1, 21);
> + }
> + temp &= 0x0000FFFF;
> +
> + return temp;
> +}
> +
> +static inline int32_t mipsdsp_sat16_mul_i16_i16(CPUMIPSState *env,
> + 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(env, 1, 21);
> + } else if (temp < 0x00007FFF) {
> + temp = 0xFFFF8000;
> + set_DSPControl_overflow_flag(env, 1, 21);
> + }
> + temp &= 0x0000FFFF;
> +
> + return temp;
> +}
> +
> +static inline int32_t mipsdsp_mul_q15_q15_overflowflag21(CPUMIPSState *env,
> + 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(env, 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(CPUMIPSState *env,
> + 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(env, 1, 23);
> + }
> +
> + return temp;
> +}
> +
> +/* 128 bits long. p[0] is LO, p[1] is HI. */
> +static inline void mipsdsp__rashift_short_acc(CPUMIPSState *env,
> + 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;
> + }
> +}
> +
> +/* 128 bits long. p[0] is LO, p[1] is HI */
> +static inline void mipsdsp_rashift_acc(CPUMIPSState *env,
> + uint64_t *p,
> + uint32_t ac,
> + uint32_t shift)
> +{
> + uint64_t tempB, tempA;
> +
> + tempB = env->active_tc.HI[ac];
> + tempA = env->active_tc.LO[ac];
> + shift = shift & 0x1F;
> +
> + if (shift == 0) {
> + p[1] = tempB;
> + p[0] = tempA;
> + } else {
> + p[0] = (tempB << (64 - shift)) | (tempA >> shift);
> + p[1] = (int64_t)tempB >> shift;
> + }
> +}
> +
> +/* FIXME
> + * if ( shift5..0 = 0 ) then
> + * temp128..0 ← ( HI[ac]0 || LO[ac]63..0 || 0 )
> + * else
> + * sign ← HI[ac]63
> + * temp128..0 ←
> + * signshift || (( HI[ac]63..0 || LO[ac]63..0 ) >> shift5..0) ||
> + * LO[ac]shift-1
> + * endif
> + * return temp128..0
> + * endfunction _shiftAccRightArithmetic
> + */
> +/* 128 bits long. p[0] is LO, p[1] is HI , p[2] is sign of HI.*/
> +static inline void mipsdsp__rashift_acc(CPUMIPSState *env,
> + uint64_t *p,
> + uint32_t ac,
> + uint32_t shift)
> +{
> + uint64_t tempB, tempA;
> +
> + tempB = env->active_tc.HI[ac];
> + tempA = env->active_tc.LO[ac];
> + shift = shift & 0x3F;
> +
> + if (shift == 0) {
> + p[2] = tempB >> 63;
> + p[1] = (tempB << 1) | (tempA >> 63);
> + p[0] = tempA << 1;
> + } else {
> + p[0] = (tempB << (64 - shift)) | (tempA >> shift);
> + p[1] = (int64_t)tempB >> shift;
> + if (((tempB >> 63) & 0x01) == 1) {
> + p[2] = 0xFfffFfffFfffFfffull;
> + } else {
> + p[2] = 0x0;
> + }
> + }
> +}
> +
> +static inline int32_t mipsdsp_mul_q15_q15(CPUMIPSState *env,
> + 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(env, 1, 16 + ac);
> + } else {
> + temp = ((uint32_t)tempA * (uint32_t)tempB) << 1;
> + }
> +
> + return temp;
> +}
> +
> +static inline int64_t mipsdsp_mul_q31_q31(CPUMIPSState *env,
> + 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(env, 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(CPUMIPSState *env,
> + uint8_t a, uint16_t b)
> +{
> + uint16_t tempS;
> + uint32_t tempI, tempA, tempB;
> +
> + tempA = a;
> + tempB = b;
> + tempI = tempA * tempB;
> + if (tempI > 0x0000FFFF) {
> + tempI = 0x0000FFFF;
> + set_DSPControl_overflow_flag(env, 1, 21);
> + }
> + tempS = tempI & 0x0000FFFF;
> +
> + return tempS;
> +}
> +
> +static inline uint64_t mipsdsp_mul_u32_u32(CPUMIPSState *env,
> + uint32_t a, uint32_t b)
> +{
> + uint64_t temp;
> +
> + temp = (uint64_t)a * (uint64_t)b;
> +
> + return temp;
> +}
> +
> +static inline int16_t mipsdsp_rndq15_mul_q15_q15(CPUMIPSState *env,
> + uint16_t a, uint16_t b)
> +{
> + uint16_t result;
> + uint32_t temp;
> +
> + if ((a == 0x8000) && (b == 0x8000)) {
> + temp = 0x7FFF0000;
> + set_DSPControl_overflow_flag(env, 1, 21);
> + } else {
> + temp = (a * b) << 1;
> + temp = temp + 0x00008000;
> + }
> + result = (temp & 0xFFFF0000) >> 16;
> +
> + return result;
> +}
> +
> +static inline int32_t mipsdsp_sat16_mul_q15_q15(CPUMIPSState *env,
> + 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(env, 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(CPUMIPSState *env,
> + 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(env, 1, 22);
> + }
> + result = (temp >> 16) & 0xFFFF;
> +
> + return result;
> +}
> +
> +static inline uint8_t mipsdsp_sat8_reduce_precision(CPUMIPSState *env,
> + 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(env, 1, 22);
> + } else {
> + result = (mag >> 7) & 0xFFFF;
> + }
> + } else {
> + result = 0x00;
> + set_DSPControl_overflow_flag(env, 1, 22);
> + }
> +
> + return result;
> +}
> +
> +static inline uint8_t mipsdsp_lshift8(CPUMIPSState *env, 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(env, 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(CPUMIPSState *env,
> + 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(env, 1, 22);
> + }
> + }
> +
> + return temp;
> +}
> +
> +
> +static inline uint32_t mipsdsp_lshift32(CPUMIPSState *env,
> + uint32_t a, uint8_t s)
> +{
> + uint32_t temp, discard;
> +
> + if (s == 0) {
> + temp = a;
> + } else {
> + temp = a << s;
> + discard = (int32_t)a >> (31 - (s - 1));
> +
> + if ((discard != 0x00000000) && (discard != 0xFFFFFFFF)) {
> + set_DSPControl_overflow_flag(env, 1, 22);
> + }
> + }
> +
> + return temp;
> +}
> +
> +static inline uint16_t mipsdsp_sat16_lshift(CPUMIPSState *env,
> + 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(env, 1, 22);
> + }
> + }
> +
> + return temp;
> +}
> +
> +static inline uint32_t mipsdsp_sat32_lshift(CPUMIPSState *env,
> + 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(env, 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_rashift32(uint32_t a, uint8_t s)
> +{
> + int32_t i, temp;
> +
> + i = a;
> + if (s == 0) {
> + temp = a;
> + } else {
> + temp = i >> s;
> + }
> +
> + return temp;
> +}
> +
> +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(CPUMIPSState *env, 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(env, 1, 20);
> + }
> + result = temp & 0x0000FFFF;
> +
> + return result;
> +}
> +
> +static inline uint16_t mipsdsp_sat16_sub(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> + result = temp & 0x0000FFFF;
> +
> + return result;
> +}
> +
> +static inline uint32_t mipsdsp_sat32_sub(CPUMIPSState *env,
> + 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(env, 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(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> + result = temp & 0x0000FFFF;
> + return result;
> +}
> +
> +static inline uint16_t mipsdsp_satu16_sub_u16_u16(CPUMIPSState *env,
> + 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(env, 1, 20);
> + }
> + result = temp & 0x0000FFFF;
> +
> + return result;
> +}
> +
> +static inline uint8_t mipsdsp_sub_u8(CPUMIPSState *env, 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) {
> + set_DSPControl_overflow_flag(env, 1, 20);
> + }
> + result = temp & 0x00FF;
> +
> + return result;
> +}
> +
> +static inline uint8_t mipsdsp_satu8_sub(CPUMIPSState *env, 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(env, 1, 20);
> + }
> + result = temp & 0x00FF;
> +
> + return result;
> +}
> +
> +static inline uint32_t mipsdsp_sub32(CPUMIPSState *env, int32_t a, int32_t b)
> +{
> + uint32_t result, temp32, temp31;
> + int64_t temp;
> +
> + temp = (int64_t)a - (int64_t)b;
> + temp32 = (temp >> 32) & 0x01;
> + temp31 = (temp >> 31) & 0x01;
> + if (temp32 != temp31) {
> + set_DSPControl_overflow_flag(env, 1, 20);
> + }
> + result = temp & 0xFFFFFFFF;
> +
> + return result;
> +}
> +
> +static inline int32_t mipsdsp_add_i32(CPUMIPSState *env, int32_t a, int32_t b)
> +{
> + int32_t result;
> + int32_t temp32, temp31;
> + int64_t aL, bL;
> + int64_t temp;
> +
> + aL = (int64_t)a;
> + bL = (int64_t)b;
> + temp = aL + bL;
> +
> + temp32 = (temp >> 32) & 0x01;
> + temp31 = (temp >> 31) & 0x01;
> + if (temp32 != temp31) {
> + set_DSPControl_overflow_flag(env, 1, 20);
> + }
> + result = temp & 0xFFFFFFFF;
> +
> + return result;
> +}
> +/*** MIPS DSP internal functions end ***/
> --
> 1.7.9.5
>
>
--
Aurelien Jarno GPG: 1024D/F1BCDB73
aurelien@aurel32.net http://www.aurel32.net
next prev parent reply other threads:[~2012-08-23 13:32 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-21 6:53 [Qemu-devel] [PATCH v6 00/13] QEMU MIPS ASE DSP support Jia Liu
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 01/13] target-mips-ase-dsp: Add internal functions Jia Liu
2012-08-23 13:31 ` Aurelien Jarno [this message]
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 02/13] target-mips-ase-dsp: Use correct acc value to index cpu_HI/cpu_LO rather than using a fix number Jia Liu
2012-08-23 13:33 ` Aurelien Jarno
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 03/13] target-mips-ase-dsp: Add branch instructions Jia Liu
2012-08-23 14:18 ` Aurelien Jarno
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 04/13] target-mips-ase-dsp: Add load instructions Jia Liu
2012-08-23 14:23 ` Aurelien Jarno
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 05/13] target-mips-ase-dsp: Add arithmetic instructions Jia Liu
2012-08-23 14:28 ` Aurelien Jarno
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 06/13] target-mips-ase-dsp: Add GPR Based shift instructions Jia Liu
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 07/13] target-mips-ase-dsp: Add multiply instructions Jia Liu
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 08/13] target-mips-ase-dsp: Add bit/manipulation instructions Jia Liu
2012-08-23 14:48 ` Aurelien Jarno
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 09/13] target-mips-ase-dsp: Add compare pick instructions Jia Liu
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 10/13] target-mips-ase-dsp: Add MIPS ASE DSP Accumulator and DSPControl Access instructions Jia Liu
2012-08-21 6:53 ` [Qemu-devel] [PATCH v6 11/13] target-mips-ase-dsp: Add MIPS[32|64] ASE DSP[R1|R2] generic cpu model Jia Liu
2012-08-21 9:32 ` [Qemu-devel] [PATCH v6 12/13] target-mips-ase-dsp: Add testcases Jia Liu
2012-08-21 9:34 ` [Qemu-devel] [PATCH v6 13/13] target-mips-ase-dsp: Change TODO Jia Liu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120823133124.GB3553@ohm.aurel32.net \
--to=aurelien@aurel32.net \
--cc=proljc@gmail.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.