* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
#include "cpu.h"
-#include "helper.h"
+#include "exec/helper-proto.h"
+#include "qemu/bitops.h"
/* As the byte ordering doesn't matter, i.e. all columns are treated
identically, these unions can be used directly. */
env->active_tc.DSPControl |= (target_ulong)flag << position;
}
-static inline void set_DSPControl_carryflag(uint32_t flag, CPUMIPSState *env)
+static inline void set_DSPControl_carryflag(bool flag, CPUMIPSState *env)
{
- env->active_tc.DSPControl |= (target_ulong)flag << 13;
+ env->active_tc.DSPControl &= ~(1 << 13);
+ env->active_tc.DSPControl |= flag << 13;
}
static inline uint32_t get_DSPControl_carryflag(CPUMIPSState *env)
env->active_tc.DSPControl |= (target_ulong)flag << 24;
}
-static inline uint32_t get_DSPControl_24(int len, CPUMIPSState *env)
-{
- uint32_t filter;
-
- filter = (0x01 << len) - 1;
-
- return (env->active_tc.DSPControl >> 24) & filter;
-}
-
static inline void set_DSPControl_pos(uint32_t pos, CPUMIPSState *env)
{
target_ulong dspc;
dspc = env->active_tc.DSPControl;
#ifndef TARGET_MIPS64
dspc = dspc & 0xFFFFFFC0;
- dspc |= pos;
+ dspc |= (pos & 0x3F);
#else
dspc = dspc & 0xFFFFFF80;
- dspc |= pos;
+ dspc |= (pos & 0x7F);
#endif
env->active_tc.DSPControl = dspc;
}
return result;
}
+#ifdef TARGET_MIPS64
/* a[0] is LO, a[1] is HI. */
static inline void mipsdsp_sat64_acc_add_q63(int64_t *ret,
int32_t ac,
set_DSPControl_overflow_flag(1, 16 + ac, env);
}
}
+#endif
static inline int32_t mipsdsp_mul_i16_i16(int16_t a, int16_t b,
CPUMIPSState *env)
return a * b;
}
+#ifdef TARGET_MIPS64
static inline int32_t mipsdsp_mul_i32_i32(int32_t a, int32_t b)
{
return a * b;
}
+#endif
static inline int32_t mipsdsp_sat16_mul_i16_i16(int16_t a, int16_t b,
CPUMIPSState *env)
temp = 0x7FFFFFFF;
set_DSPControl_overflow_flag(1, 21, env);
} else {
- temp = ((int32_t)(int16_t)a * (int32_t)(int16_t)b) << 1;
+ temp = ((int16_t)a * (int16_t)b) << 1;
}
return temp;
return a >> mov;
}
+#ifdef TARGET_MIPS64
static inline int32_t mipsdsp_rashift32(int32_t a, target_ulong mov)
{
return a >> mov;
}
+#endif
static inline int16_t mipsdsp_rshift1_add_q16(int16_t a, int16_t b)
{
return (temp >> 1) & 0x00FF;
}
+#ifdef TARGET_MIPS64
static inline uint8_t mipsdsp_rshift1_sub_u8(uint8_t a, uint8_t b)
{
uint16_t temp;
return (temp >> 1) & 0x00FF;
}
+#endif
/* 128 bits long. p[0] is LO, p[1] is HI. */
static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
p[1] = (acc >> 63) & 0x01;
}
+#ifdef TARGET_MIPS64
/* 128 bits long. p[0] is LO, p[1] is HI */
static inline void mipsdsp_rashift_acc(uint64_t *p,
uint32_t ac,
}
}
}
+#endif
static inline int32_t mipsdsp_mul_q15_q15(int32_t ac, uint16_t a, uint16_t b,
CPUMIPSState *env)
temp = (0x01ull << 63) - 1;
set_DSPControl_overflow_flag(1, 16 + ac, env);
} else {
- temp = ((uint64_t)a * (uint64_t)b) << 1;
+ temp = ((int64_t)(int32_t)a * (int32_t)b) << 1;
}
return temp;
return tempI & 0x0000FFFF;
}
+#ifdef TARGET_MIPS64
static inline uint64_t mipsdsp_mul_u32_u32(uint32_t a, uint32_t b)
{
return (uint64_t)a * (uint64_t)b;
}
+#endif
static inline int16_t mipsdsp_rndq15_mul_q15_q15(uint16_t a, uint16_t b,
CPUMIPSState *env)
temp = 0x7FFF0000;
set_DSPControl_overflow_flag(1, 21, env);
} else {
- temp = (a * b) << 1;
+ temp = ((int16_t)a * (int16_t)b) << 1;
temp = temp + 0x00008000;
}
static inline uint16_t mipsdsp_trunc16_sat16_round(int32_t a,
CPUMIPSState *env)
{
- int64_t temp;
+ uint16_t temp;
- temp = (int32_t)a + 0x00008000;
- if (a > (int)0x7fff8000) {
- temp = 0x7FFFFFFF;
+ /*
+ * The value 0x00008000 will be added to the input Q31 value, and the code
+ * needs to check if the addition causes an overflow. Since a positive value
+ * is added, overflow can happen in one direction only.
+ */
+ if (a > 0x7FFF7FFF) {
+ temp = 0x7FFF;
set_DSPControl_overflow_flag(1, 22, env);
+ } else {
+ temp = ((a + 0x8000) >> 16) & 0xFFFF;
}
- return (temp >> 16) & 0xFFFF;
+ return temp;
}
static inline uint8_t mipsdsp_sat8_reduce_precision(uint16_t a,
static inline uint8_t mipsdsp_lshift8(uint8_t a, uint8_t s, CPUMIPSState *env)
{
- uint8_t sign;
uint8_t discard;
- if (s == 0) {
- return a;
- } else {
- sign = (a >> 7) & 0x01;
- if (sign != 0) {
- discard = (((0x01 << (8 - s)) - 1) << s) |
- ((a >> (6 - (s - 1))) & ((0x01 << s) - 1));
- } else {
- discard = a >> (6 - (s - 1));
- }
+ if (s != 0) {
+ discard = a >> (8 - s);
if (discard != 0x00) {
set_DSPControl_overflow_flag(1, 22, env);
}
- return a << s;
}
+ return a << s;
}
static inline uint16_t mipsdsp_lshift16(uint16_t a, uint8_t s,
CPUMIPSState *env)
{
- uint8_t sign;
uint16_t discard;
- if (s == 0) {
- return a;
- } else {
- sign = (a >> 15) & 0x01;
- if (sign != 0) {
- discard = (((0x01 << (16 - s)) - 1) << s) |
- ((a >> (14 - (s - 1))) & ((0x01 << s) - 1));
- } else {
- discard = a >> (14 - (s - 1));
- }
+ if (s != 0) {
+ discard = (int16_t)a >> (15 - s);
if ((discard != 0x0000) && (discard != 0xFFFF)) {
set_DSPControl_overflow_flag(1, 22, env);
}
- return a << s;
}
+ return a << s;
}
-
+#ifdef TARGET_MIPS64
static inline uint32_t mipsdsp_lshift32(uint32_t a, uint8_t s,
CPUMIPSState *env)
{
return a << s;
}
}
+#endif
static inline uint16_t mipsdsp_sat16_lshift(uint16_t a, uint8_t s,
CPUMIPSState *env)
return temp & 0x00FF;
}
+#ifdef TARGET_MIPS64
static inline uint32_t mipsdsp_sub32(int32_t a, int32_t b, CPUMIPSState *env)
{
int32_t temp;
return temp;
}
+#endif
static inline int32_t mipsdsp_cmp_eq(int32_t a, int32_t b)
{
target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
{ \
DSP32Value dt; \
- unsigned int i, n; \
+ unsigned int i; \
\
- n = sizeof(DSP32Value) / sizeof(dt.element[0]); \
dt.sw[0] = rt; \
\
- for (i = 0; i < n; i++) { \
+ for (i = 0; i < ARRAY_SIZE(dt.element); i++) { \
dt.element[i] = mipsdsp_##func(dt.element[i], env); \
} \
\
target_ulong helper_##name(target_ulong rt, CPUMIPSState *env) \
{ \
DSP64Value dt; \
- unsigned int i, n; \
+ unsigned int i; \
\
- n = sizeof(DSP64Value) / sizeof(dt.element[0]); \
dt.sl[0] = rt; \
\
- for (i = 0; i < n; i++) { \
+ for (i = 0; i < ARRAY_SIZE(dt.element); i++) { \
dt.element[i] = mipsdsp_##func(dt.element[i], env); \
} \
\
target_ulong helper_##name(target_ulong rs, target_ulong rt) \
{ \
DSP32Value ds, dt; \
- unsigned int i, n; \
+ unsigned int i; \
\
- n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
ds.sw[0] = rs; \
dt.sw[0] = rt; \
\
- for (i = 0; i < n; i++) { \
+ for (i = 0; i < ARRAY_SIZE(ds.element); i++) { \
ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
} \
\
CPUMIPSState *env) \
{ \
DSP32Value ds, dt; \
- unsigned int i, n; \
+ unsigned int i; \
\
- n = sizeof(DSP32Value) / sizeof(ds.element[0]); \
ds.sw[0] = rs; \
dt.sw[0] = rt; \
\
- for (i = 0 ; i < n ; i++) { \
+ for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \
ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
} \
\
target_ulong helper_##name(target_ulong rs, target_ulong rt) \
{ \
DSP64Value ds, dt; \
- unsigned int i, n; \
+ unsigned int i; \
\
- n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
ds.sl[0] = rs; \
dt.sl[0] = rt; \
\
- for (i = 0 ; i < n ; i++) { \
+ for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \
ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i]); \
} \
\
CPUMIPSState *env) \
{ \
DSP64Value ds, dt; \
- unsigned int i, n; \
+ unsigned int i; \
\
- n = sizeof(DSP64Value) / sizeof(ds.element[0]); \
ds.sl[0] = rs; \
dt.sl[0] = rt; \
\
- for (i = 0 ; i < n ; i++) { \
+ for (i = 0 ; i < ARRAY_SIZE(ds.element); i++) { \
ds.element[i] = mipsdsp_##func(ds.element[i], dt.element[i], env); \
} \
\
target_ulong helper_addsc(target_ulong rs, target_ulong rt, CPUMIPSState *env)
{
uint64_t temp, tempRs, tempRt;
- int32_t flag;
+ bool flag;
tempRs = (uint64_t)rs & MIPSDSP_LLO;
tempRt = (uint64_t)rt & MIPSDSP_LLO;
return (target_ulong)rd;
}
-#define BIT_INSV(name, posfilter, sizefilter, ret_type) \
+#define BIT_INSV(name, posfilter, ret_type) \
target_ulong helper_##name(CPUMIPSState *env, target_ulong rs, \
target_ulong rt) \
{ \
uint32_t pos, size, msb, lsb; \
- target_ulong filter; \
- target_ulong temp, temprs, temprt; \
+ uint32_t const sizefilter = 0x3F; \
+ target_ulong temp; \
target_ulong dspc; \
\
dspc = env->active_tc.DSPControl; \
return rt; \
} \
\
- filter = ((int32_t)0x01 << size) - 1; \
- filter = filter << pos; \
- temprs = (rs << pos) & filter; \
- temprt = rt & ~filter; \
- temp = temprs | temprt; \
+ temp = deposit64(rt, pos, size, rs); \
\
return (target_long)(ret_type)temp; \
}
-BIT_INSV(insv, 0x1F, 0x1F, int32_t);
+BIT_INSV(insv, 0x1F, int32_t);
#ifdef TARGET_MIPS64
-BIT_INSV(dinsv, 0x7F, 0x3F, target_long);
+BIT_INSV(dinsv, 0x7F, target_long);
#endif
#undef BIT_INSV
if (sub >= -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);
+ temp = (acc >> (start_pos - size)) & (~0U >> (31 - size));
set_DSPControl_efi(0, env);
} else {
set_DSPControl_efi(1, env);
if (sub >= -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);
+ temp = extract64(acc, start_pos - size, size + 1);
- set_DSPControl_pos(start_pos - (size + 1), env);
+ set_DSPControl_pos(sub, env);
set_DSPControl_efi(0, env);
} else {
set_DSPControl_efi(1, env);
void helper_wrdsp(target_ulong rs, target_ulong mask_num, CPUMIPSState *env)
{
- return cpu_wrdsp(rs, mask_num, env);
+ cpu_wrdsp(rs, mask_num, env);
}
uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env)