Merge branch 'rth/vis2' of git://repo.or.cz/qemu/rth

* 'rth/vis2' of git://repo.or.cz/qemu/rth:
  target-sparc: Implement FALIGNDATA inline.
  target-sparc: Implement BMASK/BSHUFFLE.
  target-sparc: Implement ALIGNADDR* inline.
  target-sparc: Implement EDGE* instructions.
  target-sparc: Implement fpack{16,32,fix}.
  target-sparc: Implement PDIST.
  target-sparc: Do exceptions management fully inside the helpers.
  target-sparc: Change fpr representation to doubles.
  target-sparc: Undo cpu_fpr rename.
  target-sparc: Extract float128 move to a function.
  target-sparc: Extract common code for floating-point operations.
  target-sparc: Make FPU/VIS helpers const when possible.
  target-sparc: Pass float64 parameters instead of dt0/1 temporaries.
  target-sparc: Add accessors for double-precision fpr access.
  target-sparc: Mark fprs dirty in store accessor.
  target-sparc: Add accessors for single-precision fpr access.
This commit is contained in:
Blue Swirl 2011-10-27 20:27:07 +00:00
commit b5a12aa204
11 changed files with 1402 additions and 1045 deletions

View File

@ -814,7 +814,11 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64) #if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
if (n < 64) { if (n < 64) {
/* fprs */ /* fprs */
GET_REG32(*((uint32_t *)&env->fpr[n - 32])); if (n & 1) {
GET_REG32(env->fpr[(n - 32) / 2].l.lower);
} else {
GET_REG32(env->fpr[(n - 32) / 2].l.upper);
}
} }
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) { switch (n) {
@ -831,15 +835,15 @@ static int cpu_gdb_read_register(CPUState *env, uint8_t *mem_buf, int n)
#else #else
if (n < 64) { if (n < 64) {
/* f0-f31 */ /* f0-f31 */
GET_REG32(*((uint32_t *)&env->fpr[n - 32])); if (n & 1) {
GET_REG32(env->fpr[(n - 32) / 2].l.lower);
} else {
GET_REG32(env->fpr[(n - 32) / 2].l.upper);
}
} }
if (n < 80) { if (n < 80) {
/* f32-f62 (double width, even numbers only) */ /* f32-f62 (double width, even numbers only) */
uint64_t val; GET_REG64(env->fpr[(n - 32) / 2].ll);
val = (uint64_t)*((uint32_t *)&env->fpr[(n - 64) * 2 + 32]) << 32;
val |= *((uint32_t *)&env->fpr[(n - 64) * 2 + 33]);
GET_REG64(val);
} }
switch (n) { switch (n) {
case 80: GET_REGL(env->pc); case 80: GET_REGL(env->pc);
@ -878,7 +882,12 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
#if defined(TARGET_ABI32) || !defined(TARGET_SPARC64) #if defined(TARGET_ABI32) || !defined(TARGET_SPARC64)
else if (n < 64) { else if (n < 64) {
/* fprs */ /* fprs */
*((uint32_t *)&env->fpr[n - 32]) = tmp; /* f0-f31 */
if (n & 1) {
env->fpr[(n - 32) / 2].l.lower = tmp;
} else {
env->fpr[(n - 32) / 2].l.upper = tmp;
}
} else { } else {
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
switch (n) { switch (n) {
@ -896,12 +905,16 @@ static int cpu_gdb_write_register(CPUState *env, uint8_t *mem_buf, int n)
#else #else
else if (n < 64) { else if (n < 64) {
/* f0-f31 */ /* f0-f31 */
env->fpr[n] = ldfl_p(mem_buf); tmp = ldl_p(mem_buf);
if (n & 1) {
env->fpr[(n - 32) / 2].l.lower = tmp;
} else {
env->fpr[(n - 32) / 2].l.upper = tmp;
}
return 4; return 4;
} else if (n < 80) { } else if (n < 80) {
/* f32-f62 (double width, even numbers only) */ /* f32-f62 (double width, even numbers only) */
*((uint32_t *)&env->fpr[(n - 64) * 2 + 32]) = tmp >> 32; env->fpr[(n - 32) / 2].ll = tmp;
*((uint32_t *)&env->fpr[(n - 64) * 2 + 33]) = tmp;
} else { } else {
switch (n) { switch (n) {
case 80: env->pc = tmp; break; case 80: env->pc = tmp; break;

View File

@ -2296,12 +2296,14 @@ void sparc64_set_context(CPUSPARCState *env)
*/ */
err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs)); err |= __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs));
{ {
uint32_t *src, *dst; uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; for (i = 0; i < 64; i++, src++) {
dst = env->fpr; if (i & 1) {
/* XXX: check that the CPU storage is the same as user context */ err |= __get_user(env->fpr[i/2].l.lower, src);
for (i = 0; i < 64; i++, dst++, src++) } else {
err |= __get_user(*dst, src); err |= __get_user(env->fpr[i/2].l.upper, src);
}
}
} }
err |= __get_user(env->fsr, err |= __get_user(env->fsr,
&(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr)); &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr));
@ -2390,12 +2392,14 @@ void sparc64_get_context(CPUSPARCState *env)
err |= __put_user(i7, &(mcp->mc_i7)); err |= __put_user(i7, &(mcp->mc_i7));
{ {
uint32_t *src, *dst; uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs;
src = env->fpr; for (i = 0; i < 64; i++, dst++) {
dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; if (i & 1) {
/* XXX: check that the CPU storage is the same as user context */ err |= __put_user(env->fpr[i/2].l.lower, dst);
for (i = 0; i < 64; i++, dst++, src++) } else {
err |= __put_user(*src, dst); err |= __put_user(env->fpr[i/2].l.upper, dst);
}
}
} }
err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); err |= __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr));
err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); err |= __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr));

View File

@ -3471,55 +3471,55 @@ static const MonitorDef monitor_defs[] = {
#endif #endif
{ "tbr", offsetof(CPUState, tbr) }, { "tbr", offsetof(CPUState, tbr) },
{ "fsr", offsetof(CPUState, fsr) }, { "fsr", offsetof(CPUState, fsr) },
{ "f0", offsetof(CPUState, fpr[0]) }, { "f0", offsetof(CPUState, fpr[0].l.upper) },
{ "f1", offsetof(CPUState, fpr[1]) }, { "f1", offsetof(CPUState, fpr[0].l.lower) },
{ "f2", offsetof(CPUState, fpr[2]) }, { "f2", offsetof(CPUState, fpr[1].l.upper) },
{ "f3", offsetof(CPUState, fpr[3]) }, { "f3", offsetof(CPUState, fpr[1].l.lower) },
{ "f4", offsetof(CPUState, fpr[4]) }, { "f4", offsetof(CPUState, fpr[2].l.upper) },
{ "f5", offsetof(CPUState, fpr[5]) }, { "f5", offsetof(CPUState, fpr[2].l.lower) },
{ "f6", offsetof(CPUState, fpr[6]) }, { "f6", offsetof(CPUState, fpr[3].l.upper) },
{ "f7", offsetof(CPUState, fpr[7]) }, { "f7", offsetof(CPUState, fpr[3].l.lower) },
{ "f8", offsetof(CPUState, fpr[8]) }, { "f8", offsetof(CPUState, fpr[4].l.upper) },
{ "f9", offsetof(CPUState, fpr[9]) }, { "f9", offsetof(CPUState, fpr[4].l.lower) },
{ "f10", offsetof(CPUState, fpr[10]) }, { "f10", offsetof(CPUState, fpr[5].l.upper) },
{ "f11", offsetof(CPUState, fpr[11]) }, { "f11", offsetof(CPUState, fpr[5].l.lower) },
{ "f12", offsetof(CPUState, fpr[12]) }, { "f12", offsetof(CPUState, fpr[6].l.upper) },
{ "f13", offsetof(CPUState, fpr[13]) }, { "f13", offsetof(CPUState, fpr[6].l.lower) },
{ "f14", offsetof(CPUState, fpr[14]) }, { "f14", offsetof(CPUState, fpr[7].l.upper) },
{ "f15", offsetof(CPUState, fpr[15]) }, { "f15", offsetof(CPUState, fpr[7].l.lower) },
{ "f16", offsetof(CPUState, fpr[16]) }, { "f16", offsetof(CPUState, fpr[8].l.upper) },
{ "f17", offsetof(CPUState, fpr[17]) }, { "f17", offsetof(CPUState, fpr[8].l.lower) },
{ "f18", offsetof(CPUState, fpr[18]) }, { "f18", offsetof(CPUState, fpr[9].l.upper) },
{ "f19", offsetof(CPUState, fpr[19]) }, { "f19", offsetof(CPUState, fpr[9].l.lower) },
{ "f20", offsetof(CPUState, fpr[20]) }, { "f20", offsetof(CPUState, fpr[10].l.upper) },
{ "f21", offsetof(CPUState, fpr[21]) }, { "f21", offsetof(CPUState, fpr[10].l.lower) },
{ "f22", offsetof(CPUState, fpr[22]) }, { "f22", offsetof(CPUState, fpr[11].l.upper) },
{ "f23", offsetof(CPUState, fpr[23]) }, { "f23", offsetof(CPUState, fpr[11].l.lower) },
{ "f24", offsetof(CPUState, fpr[24]) }, { "f24", offsetof(CPUState, fpr[12].l.upper) },
{ "f25", offsetof(CPUState, fpr[25]) }, { "f25", offsetof(CPUState, fpr[12].l.lower) },
{ "f26", offsetof(CPUState, fpr[26]) }, { "f26", offsetof(CPUState, fpr[13].l.upper) },
{ "f27", offsetof(CPUState, fpr[27]) }, { "f27", offsetof(CPUState, fpr[13].l.lower) },
{ "f28", offsetof(CPUState, fpr[28]) }, { "f28", offsetof(CPUState, fpr[14].l.upper) },
{ "f29", offsetof(CPUState, fpr[29]) }, { "f29", offsetof(CPUState, fpr[14].l.lower) },
{ "f30", offsetof(CPUState, fpr[30]) }, { "f30", offsetof(CPUState, fpr[15].l.upper) },
{ "f31", offsetof(CPUState, fpr[31]) }, { "f31", offsetof(CPUState, fpr[15].l.lower) },
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
{ "f32", offsetof(CPUState, fpr[32]) }, { "f32", offsetof(CPUState, fpr[16]) },
{ "f34", offsetof(CPUState, fpr[34]) }, { "f34", offsetof(CPUState, fpr[17]) },
{ "f36", offsetof(CPUState, fpr[36]) }, { "f36", offsetof(CPUState, fpr[18]) },
{ "f38", offsetof(CPUState, fpr[38]) }, { "f38", offsetof(CPUState, fpr[19]) },
{ "f40", offsetof(CPUState, fpr[40]) }, { "f40", offsetof(CPUState, fpr[20]) },
{ "f42", offsetof(CPUState, fpr[42]) }, { "f42", offsetof(CPUState, fpr[21]) },
{ "f44", offsetof(CPUState, fpr[44]) }, { "f44", offsetof(CPUState, fpr[22]) },
{ "f46", offsetof(CPUState, fpr[46]) }, { "f46", offsetof(CPUState, fpr[23]) },
{ "f48", offsetof(CPUState, fpr[48]) }, { "f48", offsetof(CPUState, fpr[24]) },
{ "f50", offsetof(CPUState, fpr[50]) }, { "f50", offsetof(CPUState, fpr[25]) },
{ "f52", offsetof(CPUState, fpr[52]) }, { "f52", offsetof(CPUState, fpr[26]) },
{ "f54", offsetof(CPUState, fpr[54]) }, { "f54", offsetof(CPUState, fpr[27]) },
{ "f56", offsetof(CPUState, fpr[56]) }, { "f56", offsetof(CPUState, fpr[28]) },
{ "f58", offsetof(CPUState, fpr[58]) }, { "f58", offsetof(CPUState, fpr[29]) },
{ "f60", offsetof(CPUState, fpr[60]) }, { "f60", offsetof(CPUState, fpr[30]) },
{ "f62", offsetof(CPUState, fpr[62]) }, { "f62", offsetof(CPUState, fpr[31]) },
{ "asi", offsetof(CPUState, asi) }, { "asi", offsetof(CPUState, asi) },
{ "pstate", offsetof(CPUState, pstate) }, { "pstate", offsetof(CPUState, pstate) },
{ "cansave", offsetof(CPUState, cansave) }, { "cansave", offsetof(CPUState, cansave) },

View File

@ -3,16 +3,17 @@
#include "config.h" #include "config.h"
#include "qemu-common.h" #include "qemu-common.h"
#include "bswap.h"
#if !defined(TARGET_SPARC64) #if !defined(TARGET_SPARC64)
#define TARGET_LONG_BITS 32 #define TARGET_LONG_BITS 32
#define TARGET_FPREGS 32 #define TARGET_DPREGS 16
#define TARGET_PAGE_BITS 12 /* 4k */ #define TARGET_PAGE_BITS 12 /* 4k */
#define TARGET_PHYS_ADDR_SPACE_BITS 36 #define TARGET_PHYS_ADDR_SPACE_BITS 36
#define TARGET_VIRT_ADDR_SPACE_BITS 32 #define TARGET_VIRT_ADDR_SPACE_BITS 32
#else #else
#define TARGET_LONG_BITS 64 #define TARGET_LONG_BITS 64
#define TARGET_FPREGS 64 #define TARGET_DPREGS 32
#define TARGET_PAGE_BITS 13 /* 8k */ #define TARGET_PAGE_BITS 13 /* 8k */
#define TARGET_PHYS_ADDR_SPACE_BITS 41 #define TARGET_PHYS_ADDR_SPACE_BITS 41
# ifdef TARGET_ABI32 # ifdef TARGET_ABI32
@ -395,7 +396,7 @@ typedef struct CPUSPARCState {
uint32_t psr; /* processor state register */ uint32_t psr; /* processor state register */
target_ulong fsr; /* FPU state register */ target_ulong fsr; /* FPU state register */
float32 fpr[TARGET_FPREGS]; /* floating point registers */ CPU_DoubleU fpr[TARGET_DPREGS]; /* floating point registers */
uint32_t cwp; /* index of current register window (extracted uint32_t cwp; /* index of current register window (extracted
from PSR) */ from PSR) */
#if !defined(TARGET_SPARC64) || defined(TARGET_ABI32) #if !defined(TARGET_SPARC64) || defined(TARGET_ABI32)
@ -463,7 +464,6 @@ typedef struct CPUSPARCState {
uint64_t prom_addr; uint64_t prom_addr;
#endif #endif
/* temporary float registers */ /* temporary float registers */
float64 dt0, dt1;
float128 qt0, qt1; float128 qt0, qt1;
float_status fp_status; float_status fp_status;
#if defined(TARGET_SPARC64) #if defined(TARGET_SPARC64)

View File

@ -813,11 +813,11 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
} }
} }
cpu_fprintf(f, "\nFloating Point Registers:\n"); cpu_fprintf(f, "\nFloating Point Registers:\n");
for (i = 0; i < TARGET_FPREGS; i++) { for (i = 0; i < TARGET_DPREGS; i++) {
if ((i & 3) == 0) { if ((i & 3) == 0) {
cpu_fprintf(f, "%%f%02d:", i); cpu_fprintf(f, "%%f%02d:", i * 2);
} }
cpu_fprintf(f, " %016f", *(float *)&env->fpr[i]); cpu_fprintf(f, " %016" PRIx64, env->fpr[i].ll);
if ((i & 3) == 3) { if ((i & 3) == 3) {
cpu_fprintf(f, "\n"); cpu_fprintf(f, "\n");
} }

View File

@ -20,26 +20,74 @@
#include "cpu.h" #include "cpu.h"
#include "helper.h" #include "helper.h"
#define DT0 (env->dt0)
#define DT1 (env->dt1)
#define QT0 (env->qt0) #define QT0 (env->qt0)
#define QT1 (env->qt1) #define QT1 (env->qt1)
static void check_ieee_exceptions(CPUState *env)
{
target_ulong status;
status = get_float_exception_flags(&env->fp_status);
if (status) {
/* Copy IEEE 754 flags into FSR */
if (status & float_flag_invalid) {
env->fsr |= FSR_NVC;
}
if (status & float_flag_overflow) {
env->fsr |= FSR_OFC;
}
if (status & float_flag_underflow) {
env->fsr |= FSR_UFC;
}
if (status & float_flag_divbyzero) {
env->fsr |= FSR_DZC;
}
if (status & float_flag_inexact) {
env->fsr |= FSR_NXC;
}
if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
/* Unmasked exception, generate a trap */
env->fsr |= FSR_FTT_IEEE_EXCP;
helper_raise_exception(env, TT_FP_EXCP);
} else {
/* Accumulate exceptions */
env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
}
}
}
static inline void clear_float_exceptions(CPUState *env)
{
set_float_exception_flags(0, &env->fp_status);
}
#define F_HELPER(name, p) void helper_f##name##p(CPUState *env) #define F_HELPER(name, p) void helper_f##name##p(CPUState *env)
#define F_BINOP(name) \ #define F_BINOP(name) \
float32 helper_f ## name ## s (CPUState * env, float32 src1,\ float32 helper_f ## name ## s (CPUState *env, float32 src1, \
float32 src2) \ float32 src2) \
{ \ { \
return float32_ ## name (src1, src2, &env->fp_status); \ float32 ret; \
clear_float_exceptions(env); \
ret = float32_ ## name (src1, src2, &env->fp_status); \
check_ieee_exceptions(env); \
return ret; \
} \ } \
F_HELPER(name, d) \ float64 helper_f ## name ## d (CPUState * env, float64 src1,\
float64 src2) \
{ \ { \
DT0 = float64_ ## name (DT0, DT1, &env->fp_status); \ float64 ret; \
clear_float_exceptions(env); \
ret = float64_ ## name (src1, src2, &env->fp_status); \
check_ieee_exceptions(env); \
return ret; \
} \ } \
F_HELPER(name, q) \ F_HELPER(name, q) \
{ \ { \
clear_float_exceptions(env); \
QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \ QT0 = float128_ ## name (QT0, QT1, &env->fp_status); \
check_ieee_exceptions(env); \
} }
F_BINOP(add); F_BINOP(add);
@ -48,18 +96,24 @@ F_BINOP(mul);
F_BINOP(div); F_BINOP(div);
#undef F_BINOP #undef F_BINOP
void helper_fsmuld(CPUState *env, float32 src1, float32 src2) float64 helper_fsmuld(CPUState *env, float32 src1, float32 src2)
{ {
DT0 = float64_mul(float32_to_float64(src1, &env->fp_status), float64 ret;
clear_float_exceptions(env);
ret = float64_mul(float32_to_float64(src1, &env->fp_status),
float32_to_float64(src2, &env->fp_status), float32_to_float64(src2, &env->fp_status),
&env->fp_status); &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fdmulq(CPUState *env) void helper_fdmulq(CPUState *env, float64 src1, float64 src2)
{ {
QT0 = float128_mul(float64_to_float128(DT0, &env->fp_status), clear_float_exceptions(env);
float64_to_float128(DT1, &env->fp_status), QT0 = float128_mul(float64_to_float128(src1, &env->fp_status),
float64_to_float128(src2, &env->fp_status),
&env->fp_status); &env->fp_status);
check_ieee_exceptions(env);
} }
float32 helper_fnegs(float32 src) float32 helper_fnegs(float32 src)
@ -68,9 +122,9 @@ float32 helper_fnegs(float32 src)
} }
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
F_HELPER(neg, d) float64 helper_fnegd(float64 src)
{ {
DT0 = float64_chs(DT1); return float64_chs(src);
} }
F_HELPER(neg, q) F_HELPER(neg, q)
@ -82,98 +136,158 @@ F_HELPER(neg, q)
/* Integer to float conversion. */ /* Integer to float conversion. */
float32 helper_fitos(CPUState *env, int32_t src) float32 helper_fitos(CPUState *env, int32_t src)
{ {
return int32_to_float32(src, &env->fp_status); /* Inexact error possible converting int to float. */
float32 ret;
clear_float_exceptions(env);
ret = int32_to_float32(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fitod(CPUState *env, int32_t src) float64 helper_fitod(CPUState *env, int32_t src)
{ {
DT0 = int32_to_float64(src, &env->fp_status); /* No possible exceptions converting int to double. */
return int32_to_float64(src, &env->fp_status);
} }
void helper_fitoq(CPUState *env, int32_t src) void helper_fitoq(CPUState *env, int32_t src)
{ {
/* No possible exceptions converting int to long double. */
QT0 = int32_to_float128(src, &env->fp_status); QT0 = int32_to_float128(src, &env->fp_status);
} }
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
float32 helper_fxtos(CPUState *env) float32 helper_fxtos(CPUState *env, int64_t src)
{ {
return int64_to_float32(*((int64_t *)&DT1), &env->fp_status); float32 ret;
clear_float_exceptions(env);
ret = int64_to_float32(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
F_HELPER(xto, d) float64 helper_fxtod(CPUState *env, int64_t src)
{ {
DT0 = int64_to_float64(*((int64_t *)&DT1), &env->fp_status); float64 ret;
clear_float_exceptions(env);
ret = int64_to_float64(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
F_HELPER(xto, q) void helper_fxtoq(CPUState *env, int64_t src)
{ {
QT0 = int64_to_float128(*((int64_t *)&DT1), &env->fp_status); /* No possible exceptions converting long long to long double. */
QT0 = int64_to_float128(src, &env->fp_status);
} }
#endif #endif
#undef F_HELPER #undef F_HELPER
/* floating point conversion */ /* floating point conversion */
float32 helper_fdtos(CPUState *env) float32 helper_fdtos(CPUState *env, float64 src)
{ {
return float64_to_float32(DT1, &env->fp_status); float32 ret;
clear_float_exceptions(env);
ret = float64_to_float32(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fstod(CPUState *env, float32 src) float64 helper_fstod(CPUState *env, float32 src)
{ {
DT0 = float32_to_float64(src, &env->fp_status); float64 ret;
clear_float_exceptions(env);
ret = float32_to_float64(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
float32 helper_fqtos(CPUState *env) float32 helper_fqtos(CPUState *env)
{ {
return float128_to_float32(QT1, &env->fp_status); float32 ret;
clear_float_exceptions(env);
ret = float128_to_float32(QT1, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fstoq(CPUState *env, float32 src) void helper_fstoq(CPUState *env, float32 src)
{ {
clear_float_exceptions(env);
QT0 = float32_to_float128(src, &env->fp_status); QT0 = float32_to_float128(src, &env->fp_status);
check_ieee_exceptions(env);
} }
void helper_fqtod(CPUState *env) float64 helper_fqtod(CPUState *env)
{ {
DT0 = float128_to_float64(QT1, &env->fp_status); float64 ret;
clear_float_exceptions(env);
ret = float128_to_float64(QT1, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fdtoq(CPUState *env) void helper_fdtoq(CPUState *env, float64 src)
{ {
QT0 = float64_to_float128(DT1, &env->fp_status); clear_float_exceptions(env);
QT0 = float64_to_float128(src, &env->fp_status);
check_ieee_exceptions(env);
} }
/* Float to integer conversion. */ /* Float to integer conversion. */
int32_t helper_fstoi(CPUState *env, float32 src) int32_t helper_fstoi(CPUState *env, float32 src)
{ {
return float32_to_int32_round_to_zero(src, &env->fp_status); int32_t ret;
clear_float_exceptions(env);
ret = float32_to_int32_round_to_zero(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
int32_t helper_fdtoi(CPUState *env) int32_t helper_fdtoi(CPUState *env, float64 src)
{ {
return float64_to_int32_round_to_zero(DT1, &env->fp_status); int32_t ret;
clear_float_exceptions(env);
ret = float64_to_int32_round_to_zero(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
int32_t helper_fqtoi(CPUState *env) int32_t helper_fqtoi(CPUState *env)
{ {
return float128_to_int32_round_to_zero(QT1, &env->fp_status); int32_t ret;
clear_float_exceptions(env);
ret = float128_to_int32_round_to_zero(QT1, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
void helper_fstox(CPUState *env, float32 src) int64_t helper_fstox(CPUState *env, float32 src)
{ {
*((int64_t *)&DT0) = float32_to_int64_round_to_zero(src, &env->fp_status); int64_t ret;
clear_float_exceptions(env);
ret = float32_to_int64_round_to_zero(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fdtox(CPUState *env) int64_t helper_fdtox(CPUState *env, float64 src)
{ {
*((int64_t *)&DT0) = float64_to_int64_round_to_zero(DT1, &env->fp_status); int64_t ret;
clear_float_exceptions(env);
ret = float64_to_int64_round_to_zero(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fqtox(CPUState *env) int64_t helper_fqtox(CPUState *env)
{ {
*((int64_t *)&DT0) = float128_to_int64_round_to_zero(QT1, &env->fp_status); int64_t ret;
clear_float_exceptions(env);
ret = float128_to_int64_round_to_zero(QT1, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
#endif #endif
@ -183,9 +297,9 @@ float32 helper_fabss(float32 src)
} }
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
void helper_fabsd(CPUState *env) float64 helper_fabsd(float64 src)
{ {
DT0 = float64_abs(DT1); return float64_abs(src);
} }
void helper_fabsq(CPUState *env) void helper_fabsq(CPUState *env)
@ -196,17 +310,27 @@ void helper_fabsq(CPUState *env)
float32 helper_fsqrts(CPUState *env, float32 src) float32 helper_fsqrts(CPUState *env, float32 src)
{ {
return float32_sqrt(src, &env->fp_status); float32 ret;
clear_float_exceptions(env);
ret = float32_sqrt(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fsqrtd(CPUState *env) float64 helper_fsqrtd(CPUState *env, float64 src)
{ {
DT0 = float64_sqrt(DT1, &env->fp_status); float64 ret;
clear_float_exceptions(env);
ret = float64_sqrt(src, &env->fp_status);
check_ieee_exceptions(env);
return ret;
} }
void helper_fsqrtq(CPUState *env) void helper_fsqrtq(CPUState *env)
{ {
clear_float_exceptions(env);
QT0 = float128_sqrt(QT1, &env->fp_status); QT0 = float128_sqrt(QT1, &env->fp_status);
check_ieee_exceptions(env);
} }
#define GEN_FCMP(name, size, reg1, reg2, FS, E) \ #define GEN_FCMP(name, size, reg1, reg2, FS, E) \
@ -245,8 +369,8 @@ void helper_fsqrtq(CPUState *env)
break; \ break; \
} \ } \
} }
#define GEN_FCMPS(name, size, FS, E) \ #define GEN_FCMP_T(name, size, FS, E) \
void glue(helper_, name)(CPUState *env, float32 src1, float32 src2) \ void glue(helper_, name)(CPUState *env, size src1, size src2) \
{ \ { \
env->fsr &= FSR_FTT_NMASK; \ env->fsr &= FSR_FTT_NMASK; \
if (E && (glue(size, _is_any_nan)(src1) || \ if (E && (glue(size, _is_any_nan)(src1) || \
@ -282,80 +406,42 @@ void helper_fsqrtq(CPUState *env)
} \ } \
} }
GEN_FCMPS(fcmps, float32, 0, 0); GEN_FCMP_T(fcmps, float32, 0, 0);
GEN_FCMP(fcmpd, float64, DT0, DT1, 0, 0); GEN_FCMP_T(fcmpd, float64, 0, 0);
GEN_FCMPS(fcmpes, float32, 0, 1); GEN_FCMP_T(fcmpes, float32, 0, 1);
GEN_FCMP(fcmped, float64, DT0, DT1, 0, 1); GEN_FCMP_T(fcmped, float64, 0, 1);
GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0); GEN_FCMP(fcmpq, float128, QT0, QT1, 0, 0);
GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1); GEN_FCMP(fcmpeq, float128, QT0, QT1, 0, 1);
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
GEN_FCMPS(fcmps_fcc1, float32, 22, 0); GEN_FCMP_T(fcmps_fcc1, float32, 22, 0);
GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22, 0); GEN_FCMP_T(fcmpd_fcc1, float64, 22, 0);
GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0); GEN_FCMP(fcmpq_fcc1, float128, QT0, QT1, 22, 0);
GEN_FCMPS(fcmps_fcc2, float32, 24, 0); GEN_FCMP_T(fcmps_fcc2, float32, 24, 0);
GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24, 0); GEN_FCMP_T(fcmpd_fcc2, float64, 24, 0);
GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0); GEN_FCMP(fcmpq_fcc2, float128, QT0, QT1, 24, 0);
GEN_FCMPS(fcmps_fcc3, float32, 26, 0); GEN_FCMP_T(fcmps_fcc3, float32, 26, 0);
GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26, 0); GEN_FCMP_T(fcmpd_fcc3, float64, 26, 0);
GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0); GEN_FCMP(fcmpq_fcc3, float128, QT0, QT1, 26, 0);
GEN_FCMPS(fcmpes_fcc1, float32, 22, 1); GEN_FCMP_T(fcmpes_fcc1, float32, 22, 1);
GEN_FCMP(fcmped_fcc1, float64, DT0, DT1, 22, 1); GEN_FCMP_T(fcmped_fcc1, float64, 22, 1);
GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1); GEN_FCMP(fcmpeq_fcc1, float128, QT0, QT1, 22, 1);
GEN_FCMPS(fcmpes_fcc2, float32, 24, 1); GEN_FCMP_T(fcmpes_fcc2, float32, 24, 1);
GEN_FCMP(fcmped_fcc2, float64, DT0, DT1, 24, 1); GEN_FCMP_T(fcmped_fcc2, float64, 24, 1);
GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1); GEN_FCMP(fcmpeq_fcc2, float128, QT0, QT1, 24, 1);
GEN_FCMPS(fcmpes_fcc3, float32, 26, 1); GEN_FCMP_T(fcmpes_fcc3, float32, 26, 1);
GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); GEN_FCMP_T(fcmped_fcc3, float64, 26, 1);
GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1); GEN_FCMP(fcmpeq_fcc3, float128, QT0, QT1, 26, 1);
#endif #endif
#undef GEN_FCMPS #undef GEN_FCMP_T
#undef GEN_FCMP
void helper_check_ieee_exceptions(CPUState *env)
{
target_ulong status;
status = get_float_exception_flags(&env->fp_status);
if (status) {
/* Copy IEEE 754 flags into FSR */
if (status & float_flag_invalid) {
env->fsr |= FSR_NVC;
}
if (status & float_flag_overflow) {
env->fsr |= FSR_OFC;
}
if (status & float_flag_underflow) {
env->fsr |= FSR_UFC;
}
if (status & float_flag_divbyzero) {
env->fsr |= FSR_DZC;
}
if (status & float_flag_inexact) {
env->fsr |= FSR_NXC;
}
if ((env->fsr & FSR_CEXC_MASK) & ((env->fsr & FSR_TEM_MASK) >> 23)) {
/* Unmasked exception, generate a trap */
env->fsr |= FSR_FTT_IEEE_EXCP;
helper_raise_exception(env, TT_FP_EXCP);
} else {
/* Accumulate exceptions */
env->fsr |= (env->fsr & FSR_CEXC_MASK) << 5;
}
}
}
void helper_clear_float_exceptions(CPUState *env)
{
set_float_exception_flags(0, &env->fp_status);
}
static inline void set_fsr(CPUState *env) static inline void set_fsr(CPUState *env)
{ {

View File

@ -16,8 +16,7 @@ DEF_HELPER_1(rdccr, tl, env)
DEF_HELPER_2(wrccr, void, env, tl) DEF_HELPER_2(wrccr, void, env, tl)
DEF_HELPER_1(rdcwp, tl, env) DEF_HELPER_1(rdcwp, tl, env)
DEF_HELPER_2(wrcwp, void, env, tl) DEF_HELPER_2(wrcwp, void, env, tl)
DEF_HELPER_3(array8, tl, env, tl, tl) DEF_HELPER_FLAGS_2(array8, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
DEF_HELPER_3(alignaddr, tl, env, tl, tl)
DEF_HELPER_1(popc, tl, tl) DEF_HELPER_1(popc, tl, tl)
DEF_HELPER_3(ldda_asi, void, tl, int, int) DEF_HELPER_3(ldda_asi, void, tl, int, int)
DEF_HELPER_4(ldf_asi, void, tl, int, int, int) DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
@ -39,8 +38,6 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl) DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl) DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl) DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
DEF_HELPER_2(stdf, void, tl, int)
DEF_HELPER_2(lddf, void, tl, int)
DEF_HELPER_2(ldqf, void, tl, int) DEF_HELPER_2(ldqf, void, tl, int)
DEF_HELPER_2(stqf, void, tl, int) DEF_HELPER_2(stqf, void, tl, int)
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) #if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
@ -48,33 +45,31 @@ DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
DEF_HELPER_4(st_asi, void, tl, i64, int, int) DEF_HELPER_4(st_asi, void, tl, i64, int, int)
#endif #endif
DEF_HELPER_2(ldfsr, void, env, i32) DEF_HELPER_2(ldfsr, void, env, i32)
DEF_HELPER_1(check_ieee_exceptions, void, env) DEF_HELPER_FLAGS_1(fabss, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32)
DEF_HELPER_1(clear_float_exceptions, void, env)
DEF_HELPER_1(fabss, f32, f32)
DEF_HELPER_2(fsqrts, f32, env, f32) DEF_HELPER_2(fsqrts, f32, env, f32)
DEF_HELPER_1(fsqrtd, void, env) DEF_HELPER_2(fsqrtd, f64, env, f64)
DEF_HELPER_3(fcmps, void, env, f32, f32) DEF_HELPER_3(fcmps, void, env, f32, f32)
DEF_HELPER_1(fcmpd, void, env) DEF_HELPER_3(fcmpd, void, env, f64, f64)
DEF_HELPER_3(fcmpes, void, env, f32, f32) DEF_HELPER_3(fcmpes, void, env, f32, f32)
DEF_HELPER_1(fcmped, void, env) DEF_HELPER_3(fcmped, void, env, f64, f64)
DEF_HELPER_1(fsqrtq, void, env) DEF_HELPER_1(fsqrtq, void, env)
DEF_HELPER_1(fcmpq, void, env) DEF_HELPER_1(fcmpq, void, env)
DEF_HELPER_1(fcmpeq, void, env) DEF_HELPER_1(fcmpeq, void, env)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
DEF_HELPER_2(ldxfsr, void, env, i64) DEF_HELPER_2(ldxfsr, void, env, i64)
DEF_HELPER_1(fabsd, void, env) DEF_HELPER_FLAGS_1(fabsd, TCG_CALL_CONST | TCG_CALL_PURE, f64, f64)
DEF_HELPER_3(fcmps_fcc1, void, env, f32, f32) DEF_HELPER_3(fcmps_fcc1, void, env, f32, f32)
DEF_HELPER_3(fcmps_fcc2, void, env, f32, f32) DEF_HELPER_3(fcmps_fcc2, void, env, f32, f32)
DEF_HELPER_3(fcmps_fcc3, void, env, f32, f32) DEF_HELPER_3(fcmps_fcc3, void, env, f32, f32)
DEF_HELPER_1(fcmpd_fcc1, void, env) DEF_HELPER_3(fcmpd_fcc1, void, env, f64, f64)
DEF_HELPER_1(fcmpd_fcc2, void, env) DEF_HELPER_3(fcmpd_fcc2, void, env, f64, f64)
DEF_HELPER_1(fcmpd_fcc3, void, env) DEF_HELPER_3(fcmpd_fcc3, void, env, f64, f64)
DEF_HELPER_3(fcmpes_fcc1, void, env, f32, f32) DEF_HELPER_3(fcmpes_fcc1, void, env, f32, f32)
DEF_HELPER_3(fcmpes_fcc2, void, env, f32, f32) DEF_HELPER_3(fcmpes_fcc2, void, env, f32, f32)
DEF_HELPER_3(fcmpes_fcc3, void, env, f32, f32) DEF_HELPER_3(fcmpes_fcc3, void, env, f32, f32)
DEF_HELPER_1(fcmped_fcc1, void, env) DEF_HELPER_3(fcmped_fcc1, void, env, f64, f64)
DEF_HELPER_1(fcmped_fcc2, void, env) DEF_HELPER_3(fcmped_fcc2, void, env, f64, f64)
DEF_HELPER_1(fcmped_fcc3, void, env) DEF_HELPER_3(fcmped_fcc3, void, env, f64, f64)
DEF_HELPER_1(fabsq, void, env) DEF_HELPER_1(fabsq, void, env)
DEF_HELPER_1(fcmpq_fcc1, void, env) DEF_HELPER_1(fcmpq_fcc1, void, env)
DEF_HELPER_1(fcmpq_fcc2, void, env) DEF_HELPER_1(fcmpq_fcc2, void, env)
@ -86,77 +81,88 @@ DEF_HELPER_1(fcmpeq_fcc3, void, env)
DEF_HELPER_2(raise_exception, void, env, int) DEF_HELPER_2(raise_exception, void, env, int)
DEF_HELPER_0(shutdown, void) DEF_HELPER_0(shutdown, void)
#define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env) #define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
#define F_HELPER_DQ_0_1(name) \
F_HELPER_0_1(name ## d); \
F_HELPER_0_1(name ## q)
F_HELPER_DQ_0_1(add); DEF_HELPER_3(faddd, f64, env, f64, f64)
F_HELPER_DQ_0_1(sub); DEF_HELPER_3(fsubd, f64, env, f64, f64)
F_HELPER_DQ_0_1(mul); DEF_HELPER_3(fmuld, f64, env, f64, f64)
F_HELPER_DQ_0_1(div); DEF_HELPER_3(fdivd, f64, env, f64, f64)
F_HELPER_0_1(addq)
F_HELPER_0_1(subq)
F_HELPER_0_1(mulq)
F_HELPER_0_1(divq)
DEF_HELPER_3(fadds, f32, env, f32, f32) DEF_HELPER_3(fadds, f32, env, f32, f32)
DEF_HELPER_3(fsubs, f32, env, f32, f32) DEF_HELPER_3(fsubs, f32, env, f32, f32)
DEF_HELPER_3(fmuls, f32, env, f32, f32) DEF_HELPER_3(fmuls, f32, env, f32, f32)
DEF_HELPER_3(fdivs, f32, env, f32, f32) DEF_HELPER_3(fdivs, f32, env, f32, f32)
DEF_HELPER_3(fsmuld, void, env, f32, f32) DEF_HELPER_3(fsmuld, f64, env, f32, f32)
F_HELPER_0_1(dmulq); DEF_HELPER_3(fdmulq, void, env, f64, f64);
DEF_HELPER_1(fnegs, f32, f32) DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32)
DEF_HELPER_2(fitod, void, env, s32) DEF_HELPER_2(fitod, f64, env, s32)
DEF_HELPER_2(fitoq, void, env, s32) DEF_HELPER_2(fitoq, void, env, s32)
DEF_HELPER_2(fitos, f32, env, s32) DEF_HELPER_2(fitos, f32, env, s32)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
DEF_HELPER_1(fnegd, void, env) DEF_HELPER_FLAGS_1(fnegd, TCG_CALL_CONST | TCG_CALL_PURE, f64, f64)
DEF_HELPER_1(fnegq, void, env) DEF_HELPER_1(fnegq, void, env)
DEF_HELPER_1(fxtos, i32, env) DEF_HELPER_2(fxtos, f32, env, s64)
F_HELPER_DQ_0_1(xto); DEF_HELPER_2(fxtod, f64, env, s64)
DEF_HELPER_2(fxtoq, void, env, s64)
#endif #endif
DEF_HELPER_1(fdtos, f32, env) DEF_HELPER_2(fdtos, f32, env, f64)
DEF_HELPER_2(fstod, void, env, f32) DEF_HELPER_2(fstod, f64, env, f32)
DEF_HELPER_1(fqtos, f32, env) DEF_HELPER_1(fqtos, f32, env)
DEF_HELPER_2(fstoq, void, env, f32) DEF_HELPER_2(fstoq, void, env, f32)
F_HELPER_0_1(qtod); DEF_HELPER_1(fqtod, f64, env)
F_HELPER_0_1(dtoq); DEF_HELPER_2(fdtoq, void, env, f64)
DEF_HELPER_2(fstoi, s32, env, f32) DEF_HELPER_2(fstoi, s32, env, f32)
DEF_HELPER_1(fdtoi, s32, env) DEF_HELPER_2(fdtoi, s32, env, f64)
DEF_HELPER_1(fqtoi, s32, env) DEF_HELPER_1(fqtoi, s32, env)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
DEF_HELPER_2(fstox, void, env, i32) DEF_HELPER_2(fstox, s64, env, f32)
F_HELPER_0_1(dtox); DEF_HELPER_2(fdtox, s64, env, f64)
F_HELPER_0_1(qtox); DEF_HELPER_1(fqtox, s64, env)
F_HELPER_0_1(aligndata);
F_HELPER_0_1(pmerge); DEF_HELPER_FLAGS_2(fpmerge, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(mul8x16); DEF_HELPER_FLAGS_2(fmul8x16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(mul8x16al); DEF_HELPER_FLAGS_2(fmul8x16al, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(mul8x16au); DEF_HELPER_FLAGS_2(fmul8x16au, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(mul8sux16); DEF_HELPER_FLAGS_2(fmul8sux16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(mul8ulx16); DEF_HELPER_FLAGS_2(fmul8ulx16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(muld8sux16); DEF_HELPER_FLAGS_2(fmuld8sux16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(muld8ulx16); DEF_HELPER_FLAGS_2(fmuld8ulx16, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
F_HELPER_0_1(expand); DEF_HELPER_FLAGS_2(fexpand, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
#define VIS_HELPER(name) \ DEF_HELPER_FLAGS_3(pdist, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64, i64)
F_HELPER_0_1(name##16); \ DEF_HELPER_FLAGS_2(fpack16, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64, i64)
DEF_HELPER_3(f ## name ## 16s, i32, env, i32, i32) \ DEF_HELPER_FLAGS_3(fpack32, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64, i64)
F_HELPER_0_1(name##32); \ DEF_HELPER_FLAGS_2(fpackfix, TCG_CALL_CONST | TCG_CALL_PURE, i32, i64, i64)
DEF_HELPER_3(f ## name ## 32s, i32, env, i32, i32) DEF_HELPER_FLAGS_3(bshuffle, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64, i64)
#define VIS_HELPER(name) \
DEF_HELPER_FLAGS_2(f ## name ## 16, TCG_CALL_CONST | TCG_CALL_PURE, \
i64, i64, i64) \
DEF_HELPER_FLAGS_2(f ## name ## 16s, TCG_CALL_CONST | TCG_CALL_PURE, \
i32, i32, i32) \
DEF_HELPER_FLAGS_2(f ## name ## 32, TCG_CALL_CONST | TCG_CALL_PURE, \
i64, i64, i64) \
DEF_HELPER_FLAGS_2(f ## name ## 32s, TCG_CALL_CONST | TCG_CALL_PURE, \
i32, i32, i32)
VIS_HELPER(padd); VIS_HELPER(padd);
VIS_HELPER(psub); VIS_HELPER(psub);
#define VIS_CMPHELPER(name) \ #define VIS_CMPHELPER(name) \
DEF_HELPER_1(f##name##16, i64, env); \ DEF_HELPER_FLAGS_2(f##name##16, TCG_CALL_CONST | TCG_CALL_PURE, \
DEF_HELPER_1(f##name##32, i64, env) i64, i64, i64) \
DEF_HELPER_FLAGS_2(f##name##32, TCG_CALL_CONST | TCG_CALL_PURE, \
i64, i64, i64)
VIS_CMPHELPER(cmpgt); VIS_CMPHELPER(cmpgt);
VIS_CMPHELPER(cmpeq); VIS_CMPHELPER(cmpeq);
VIS_CMPHELPER(cmple); VIS_CMPHELPER(cmple);
VIS_CMPHELPER(cmpne); VIS_CMPHELPER(cmpne);
#endif #endif
#undef F_HELPER_0_1 #undef F_HELPER_0_1
#undef F_HELPER_DQ_0_1
#undef VIS_HELPER #undef VIS_HELPER
#undef VIS_CMPHELPER #undef VIS_CMPHELPER
DEF_HELPER_1(compute_psr, void, env); DEF_HELPER_1(compute_psr, void, env);

View File

@ -66,8 +66,6 @@
#endif #endif
#endif #endif
#define DT0 (env->dt0)
#define DT1 (env->dt1)
#define QT0 (env->qt0) #define QT0 (env->qt0)
#define QT1 (env->qt1) #define QT1 (env->qt1)
@ -2047,7 +2045,7 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
void helper_ldf_asi(target_ulong addr, int asi, int size, int rd) void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
{ {
unsigned int i; unsigned int i;
CPU_DoubleU u; target_ulong val;
helper_check_align(addr, 3); helper_check_align(addr, 3);
addr = asi_address_mask(env, asi, addr); addr = asi_address_mask(env, asi, addr);
@ -2062,13 +2060,11 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
return; return;
} }
helper_check_align(addr, 0x3f); helper_check_align(addr, 0x3f);
for (i = 0; i < 16; i++) { for (i = 0; i < 8; i++, rd += 2, addr += 8) {
*(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4, env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x8f, 8, 0);
0);
addr += 4;
} }
return; return;
case 0x16: /* UA2007 Block load primary, user privilege */ case 0x16: /* UA2007 Block load primary, user privilege */
case 0x17: /* UA2007 Block load secondary, user privilege */ case 0x17: /* UA2007 Block load secondary, user privilege */
case 0x1e: /* UA2007 Block load primary LE, user privilege */ case 0x1e: /* UA2007 Block load primary LE, user privilege */
@ -2082,13 +2078,11 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
return; return;
} }
helper_check_align(addr, 0x3f); helper_check_align(addr, 0x3f);
for (i = 0; i < 16; i++) { for (i = 0; i < 8; i++, rd += 2, addr += 4) {
*(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x19, 4, env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x19, 8, 0);
0);
addr += 4;
} }
return; return;
default: default:
break; break;
} }
@ -2096,20 +2090,19 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
switch (size) { switch (size) {
default: default:
case 4: case 4:
*((uint32_t *)&env->fpr[rd]) = helper_ld_asi(addr, asi, size, 0); val = helper_ld_asi(addr, asi, size, 0);
if (rd & 1) {
env->fpr[rd/2].l.lower = val;
} else {
env->fpr[rd/2].l.upper = val;
}
break; break;
case 8: case 8:
u.ll = helper_ld_asi(addr, asi, size, 0); env->fpr[rd/2].ll = helper_ld_asi(addr, asi, size, 0);
*((uint32_t *)&env->fpr[rd++]) = u.l.upper;
*((uint32_t *)&env->fpr[rd++]) = u.l.lower;
break; break;
case 16: case 16:
u.ll = helper_ld_asi(addr, asi, 8, 0); env->fpr[rd/2].ll = helper_ld_asi(addr, asi, 8, 0);
*((uint32_t *)&env->fpr[rd++]) = u.l.upper; env->fpr[rd/2 + 1].ll = helper_ld_asi(addr + 8, asi, 8, 0);
*((uint32_t *)&env->fpr[rd++]) = u.l.lower;
u.ll = helper_ld_asi(addr + 8, asi, 8, 0);
*((uint32_t *)&env->fpr[rd++]) = u.l.upper;
*((uint32_t *)&env->fpr[rd++]) = u.l.lower;
break; break;
} }
} }
@ -2117,8 +2110,7 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
void helper_stf_asi(target_ulong addr, int asi, int size, int rd) void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
{ {
unsigned int i; unsigned int i;
target_ulong val = 0; target_ulong val;
CPU_DoubleU u;
helper_check_align(addr, 3); helper_check_align(addr, 3);
addr = asi_address_mask(env, asi, addr); addr = asi_address_mask(env, asi, addr);
@ -2135,10 +2127,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
return; return;
} }
helper_check_align(addr, 0x3f); helper_check_align(addr, 0x3f);
for (i = 0; i < 16; i++) { for (i = 0; i < 8; i++, rd += 2, addr += 8) {
val = *(uint32_t *)&env->fpr[rd++]; helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x8f, 8);
helper_st_asi(addr, val, asi & 0x8f, 4);
addr += 4;
} }
return; return;
@ -2155,10 +2145,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
return; return;
} }
helper_check_align(addr, 0x3f); helper_check_align(addr, 0x3f);
for (i = 0; i < 16; i++) { for (i = 0; i < 8; i++, rd += 2, addr += 8) {
val = *(uint32_t *)&env->fpr[rd++]; helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x19, 8);
helper_st_asi(addr, val, asi & 0x19, 4);
addr += 4;
} }
return; return;
@ -2169,20 +2157,19 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
switch (size) { switch (size) {
default: default:
case 4: case 4:
helper_st_asi(addr, *(uint32_t *)&env->fpr[rd], asi, size); if (rd & 1) {
val = env->fpr[rd/2].l.lower;
} else {
val = env->fpr[rd/2].l.upper;
}
helper_st_asi(addr, val, asi, size);
break; break;
case 8: case 8:
u.l.upper = *(uint32_t *)&env->fpr[rd++]; helper_st_asi(addr, env->fpr[rd/2].ll, asi, size);
u.l.lower = *(uint32_t *)&env->fpr[rd++];
helper_st_asi(addr, u.ll, asi, size);
break; break;
case 16: case 16:
u.l.upper = *(uint32_t *)&env->fpr[rd++]; helper_st_asi(addr, env->fpr[rd/2].ll, asi, 8);
u.l.lower = *(uint32_t *)&env->fpr[rd++]; helper_st_asi(addr + 8, env->fpr[rd/2 + 1].ll, asi, 8);
helper_st_asi(addr, u.ll, asi, 8);
u.l.upper = *(uint32_t *)&env->fpr[rd++];
u.l.lower = *(uint32_t *)&env->fpr[rd++];
helper_st_asi(addr + 8, u.ll, asi, 8);
break; break;
} }
} }
@ -2214,56 +2201,6 @@ target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
} }
#endif /* TARGET_SPARC64 */ #endif /* TARGET_SPARC64 */
void helper_stdf(target_ulong addr, int mem_idx)
{
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
case MMU_USER_IDX:
stfq_user(addr, DT0);
break;
case MMU_KERNEL_IDX:
stfq_kernel(addr, DT0);
break;
#ifdef TARGET_SPARC64
case MMU_HYPV_IDX:
stfq_hypv(addr, DT0);
break;
#endif
default:
DPRINTF_MMU("helper_stdf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
stfq_raw(address_mask(env, addr), DT0);
#endif
}
void helper_lddf(target_ulong addr, int mem_idx)
{
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
case MMU_USER_IDX:
DT0 = ldfq_user(addr);
break;
case MMU_KERNEL_IDX:
DT0 = ldfq_kernel(addr);
break;
#ifdef TARGET_SPARC64
case MMU_HYPV_IDX:
DT0 = ldfq_hypv(addr);
break;
#endif
default:
DPRINTF_MMU("helper_lddf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
DT0 = ldfq_raw(address_mask(env, addr));
#endif
}
void helper_ldqf(target_ulong addr, int mem_idx) void helper_ldqf(target_ulong addr, int mem_idx)
{ {
/* XXX add 128 bit load */ /* XXX add 128 bit load */

View File

@ -21,13 +21,9 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_betls(f, &env->regbase[i]); qemu_put_betls(f, &env->regbase[i]);
/* FPU */ /* FPU */
for(i = 0; i < TARGET_FPREGS; i++) { for (i = 0; i < TARGET_DPREGS; i++) {
union { qemu_put_be32(f, env->fpr[i].l.upper);
float32 f; qemu_put_be32(f, env->fpr[i].l.lower);
uint32_t i;
} u;
u.f = env->fpr[i];
qemu_put_be32(f, u.i);
} }
qemu_put_betls(f, &env->pc); qemu_put_betls(f, &env->pc);
@ -128,13 +124,9 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_betls(f, &env->regbase[i]); qemu_get_betls(f, &env->regbase[i]);
/* FPU */ /* FPU */
for(i = 0; i < TARGET_FPREGS; i++) { for (i = 0; i < TARGET_DPREGS; i++) {
union { env->fpr[i].l.upper = qemu_get_be32(f);
float32 f; env->fpr[i].l.lower = qemu_get_be32(f);
uint32_t i;
} u;
u.i = qemu_get_be32(f);
env->fpr[i] = u.f;
} }
qemu_get_betls(f, &env->pc); qemu_get_betls(f, &env->pc);

File diff suppressed because it is too large Load Diff

View File

@ -20,11 +20,6 @@
#include "cpu.h" #include "cpu.h"
#include "helper.h" #include "helper.h"
#define DT0 (env->dt0)
#define DT1 (env->dt1)
#define QT0 (env->qt0)
#define QT1 (env->qt1)
/* This function uses non-native bit order */ /* This function uses non-native bit order */
#define GET_FIELD(X, FROM, TO) \ #define GET_FIELD(X, FROM, TO) \
((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1)) ((X) >> (63 - (TO)) & ((1ULL << ((TO) - (FROM) + 1)) - 1))
@ -33,8 +28,7 @@
#define GET_FIELD_SP(X, FROM, TO) \ #define GET_FIELD_SP(X, FROM, TO) \
GET_FIELD(X, 63 - (TO), 63 - (FROM)) GET_FIELD(X, 63 - (TO), 63 - (FROM))
target_ulong helper_array8(CPUState *env, target_ulong pixel_addr, target_ulong helper_array8(target_ulong pixel_addr, target_ulong cubesize)
target_ulong cubesize)
{ {
return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) | return (GET_FIELD_SP(pixel_addr, 60, 63) << (17 + 2 * cubesize)) |
(GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) | (GET_FIELD_SP(pixel_addr, 39, 39 + cubesize - 1) << (17 + cubesize)) |
@ -47,29 +41,6 @@ target_ulong helper_array8(CPUState *env, target_ulong pixel_addr,
GET_FIELD_SP(pixel_addr, 11, 12); GET_FIELD_SP(pixel_addr, 11, 12);
} }
target_ulong helper_alignaddr(CPUState *env, target_ulong addr,
target_ulong offset)
{
uint64_t tmp;
tmp = addr + offset;
env->gsr &= ~7ULL;
env->gsr |= tmp & 7ULL;
return tmp & ~7ULL;
}
void helper_faligndata(CPUState *env)
{
uint64_t tmp;
tmp = (*((uint64_t *)&DT0)) << ((env->gsr & 7) * 8);
/* on many architectures a shift of 64 does nothing */
if ((env->gsr & 7) != 0) {
tmp |= (*((uint64_t *)&DT1)) >> (64 - (env->gsr & 7) * 8);
}
*((uint64_t *)&DT0) = tmp;
}
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
#define VIS_B64(n) b[7 - (n)] #define VIS_B64(n) b[7 - (n)]
#define VIS_W64(n) w[3 - (n)] #define VIS_W64(n) w[3 - (n)]
@ -102,12 +73,12 @@ typedef union {
float32 f; float32 f;
} VIS32; } VIS32;
void helper_fpmerge(CPUState *env) uint64_t helper_fpmerge(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
/* Reverse calculation order to handle overlap */ /* Reverse calculation order to handle overlap */
d.VIS_B64(7) = s.VIS_B64(3); d.VIS_B64(7) = s.VIS_B64(3);
@ -119,16 +90,16 @@ void helper_fpmerge(CPUState *env)
d.VIS_B64(1) = s.VIS_B64(0); d.VIS_B64(1) = s.VIS_B64(0);
/* d.VIS_B64(0) = d.VIS_B64(0); */ /* d.VIS_B64(0) = d.VIS_B64(0); */
DT0 = d.d; return d.ll;
} }
void helper_fmul8x16(CPUState *env) uint64_t helper_fmul8x16(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \ tmp = (int32_t)d.VIS_SW64(r) * (int32_t)s.VIS_B64(r); \
@ -143,16 +114,16 @@ void helper_fmul8x16(CPUState *env)
PMUL(3); PMUL(3);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fmul8x16al(CPUState *env) uint64_t helper_fmul8x16al(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \ tmp = (int32_t)d.VIS_SW64(1) * (int32_t)s.VIS_B64(r); \
@ -167,16 +138,16 @@ void helper_fmul8x16al(CPUState *env)
PMUL(3); PMUL(3);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fmul8x16au(CPUState *env) uint64_t helper_fmul8x16au(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \ tmp = (int32_t)d.VIS_SW64(0) * (int32_t)s.VIS_B64(r); \
@ -191,16 +162,16 @@ void helper_fmul8x16au(CPUState *env)
PMUL(3); PMUL(3);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fmul8sux16(CPUState *env) uint64_t helper_fmul8sux16(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
@ -215,16 +186,16 @@ void helper_fmul8sux16(CPUState *env)
PMUL(3); PMUL(3);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fmul8ulx16(CPUState *env) uint64_t helper_fmul8ulx16(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
@ -239,16 +210,16 @@ void helper_fmul8ulx16(CPUState *env)
PMUL(3); PMUL(3);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fmuld8sux16(CPUState *env) uint64_t helper_fmuld8sux16(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \ tmp = (int32_t)d.VIS_SW64(r) * ((int32_t)s.VIS_SW64(r) >> 8); \
@ -262,16 +233,16 @@ void helper_fmuld8sux16(CPUState *env)
PMUL(0); PMUL(0);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fmuld8ulx16(CPUState *env) uint64_t helper_fmuld8ulx16(uint64_t src1, uint64_t src2)
{ {
VIS64 s, d; VIS64 s, d;
uint32_t tmp; uint32_t tmp;
s.d = DT0; s.ll = src1;
d.d = DT1; d.ll = src2;
#define PMUL(r) \ #define PMUL(r) \
tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \ tmp = (int32_t)d.VIS_SW64(r) * ((uint32_t)s.VIS_B64(r * 2)); \
@ -285,42 +256,41 @@ void helper_fmuld8ulx16(CPUState *env)
PMUL(0); PMUL(0);
#undef PMUL #undef PMUL
DT0 = d.d; return d.ll;
} }
void helper_fexpand(CPUState *env) uint64_t helper_fexpand(uint64_t src1, uint64_t src2)
{ {
VIS32 s; VIS32 s;
VIS64 d; VIS64 d;
s.l = (uint32_t)(*(uint64_t *)&DT0 & 0xffffffff); s.l = (uint32_t)src1;
d.d = DT1; d.ll = src2;
d.VIS_W64(0) = s.VIS_B32(0) << 4; d.VIS_W64(0) = s.VIS_B32(0) << 4;
d.VIS_W64(1) = s.VIS_B32(1) << 4; d.VIS_W64(1) = s.VIS_B32(1) << 4;
d.VIS_W64(2) = s.VIS_B32(2) << 4; d.VIS_W64(2) = s.VIS_B32(2) << 4;
d.VIS_W64(3) = s.VIS_B32(3) << 4; d.VIS_W64(3) = s.VIS_B32(3) << 4;
DT0 = d.d; return d.ll;
} }
#define VIS_HELPER(name, F) \ #define VIS_HELPER(name, F) \
void name##16(CPUState *env) \ uint64_t name##16(uint64_t src1, uint64_t src2) \
{ \ { \
VIS64 s, d; \ VIS64 s, d; \
\ \
s.d = DT0; \ s.ll = src1; \
d.d = DT1; \ d.ll = src2; \
\ \
d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \ d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0)); \
d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \ d.VIS_W64(1) = F(d.VIS_W64(1), s.VIS_W64(1)); \
d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \ d.VIS_W64(2) = F(d.VIS_W64(2), s.VIS_W64(2)); \
d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \ d.VIS_W64(3) = F(d.VIS_W64(3), s.VIS_W64(3)); \
\ \
DT0 = d.d; \ return d.ll; \
} \ } \
\ \
uint32_t name##16s(CPUState *env, uint32_t src1, \ uint32_t name##16s(uint32_t src1, uint32_t src2) \
uint32_t src2) \
{ \ { \
VIS32 s, d; \ VIS32 s, d; \
\ \
@ -333,21 +303,20 @@ void helper_fexpand(CPUState *env)
return d.l; \ return d.l; \
} \ } \
\ \
void name##32(CPUState *env) \ uint64_t name##32(uint64_t src1, uint64_t src2) \
{ \ { \
VIS64 s, d; \ VIS64 s, d; \
\ \
s.d = DT0; \ s.ll = src1; \
d.d = DT1; \ d.ll = src2; \
\ \
d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \ d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0)); \
d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \ d.VIS_L64(1) = F(d.VIS_L64(1), s.VIS_L64(1)); \
\ \
DT0 = d.d; \ return d.ll; \
} \ } \
\ \
uint32_t name##32s(CPUState *env, uint32_t src1, \ uint32_t name##32s(uint32_t src1, uint32_t src2) \
uint32_t src2) \
{ \ { \
VIS32 s, d; \ VIS32 s, d; \
\ \
@ -365,12 +334,12 @@ VIS_HELPER(helper_fpadd, FADD)
VIS_HELPER(helper_fpsub, FSUB) VIS_HELPER(helper_fpsub, FSUB)
#define VIS_CMPHELPER(name, F) \ #define VIS_CMPHELPER(name, F) \
uint64_t name##16(CPUState *env) \ uint64_t name##16(uint64_t src1, uint64_t src2) \
{ \ { \
VIS64 s, d; \ VIS64 s, d; \
\ \
s.d = DT0; \ s.ll = src1; \
d.d = DT1; \ d.ll = src2; \
\ \
d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \ d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \
d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \ d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \
@ -381,12 +350,12 @@ VIS_HELPER(helper_fpsub, FSUB)
return d.ll; \ return d.ll; \
} \ } \
\ \
uint64_t name##32(CPUState *env) \ uint64_t name##32(uint64_t src1, uint64_t src2) \
{ \ { \
VIS64 s, d; \ VIS64 s, d; \
\ \
s.d = DT0; \ s.ll = src1; \
d.d = DT1; \ d.ll = src2; \
\ \
d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \ d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \
d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \ d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \
@ -404,3 +373,117 @@ VIS_CMPHELPER(helper_fcmpgt, FCMPGT)
VIS_CMPHELPER(helper_fcmpeq, FCMPEQ) VIS_CMPHELPER(helper_fcmpeq, FCMPEQ)
VIS_CMPHELPER(helper_fcmple, FCMPLE) VIS_CMPHELPER(helper_fcmple, FCMPLE)
VIS_CMPHELPER(helper_fcmpne, FCMPNE) VIS_CMPHELPER(helper_fcmpne, FCMPNE)
uint64_t helper_pdist(uint64_t sum, uint64_t src1, uint64_t src2)
{
int i;
for (i = 0; i < 8; i++) {
int s1, s2;
s1 = (src1 >> (56 - (i * 8))) & 0xff;
s2 = (src2 >> (56 - (i * 8))) & 0xff;
/* Absolute value of difference. */
s1 -= s2;
if (s1 < 0) {
s1 = -s1;
}
sum += s1;
}
return sum;
}
uint32_t helper_fpack16(uint64_t gsr, uint64_t rs2)
{
int scale = (gsr >> 3) & 0xf;
uint32_t ret = 0;
int byte;
for (byte = 0; byte < 4; byte++) {
uint32_t val;
int16_t src = rs2 >> (byte * 16);
int32_t scaled = src << scale;
int32_t from_fixed = scaled >> 7;
val = (from_fixed < 0 ? 0 :
from_fixed > 255 ? 255 : from_fixed);
ret |= val << (8 * byte);
}
return ret;
}
uint64_t helper_fpack32(uint64_t gsr, uint64_t rs1, uint64_t rs2)
{
int scale = (gsr >> 3) & 0x1f;
uint64_t ret = 0;
int word;
ret = (rs1 << 8) & ~(0x000000ff000000ffULL);
for (word = 0; word < 2; word++) {
uint64_t val;
int32_t src = rs2 >> (word * 32);
int64_t scaled = (int64_t)src << scale;
int64_t from_fixed = scaled >> 23;
val = (from_fixed < 0 ? 0 :
(from_fixed > 255) ? 255 : from_fixed);
ret |= val << (32 * word);
}
return ret;
}
uint32_t helper_fpackfix(uint64_t gsr, uint64_t rs2)
{
int scale = (gsr >> 3) & 0x1f;
uint32_t ret = 0;
int word;
for (word = 0; word < 2; word++) {
uint32_t val;
int32_t src = rs2 >> (word * 32);
int64_t scaled = src << scale;
int64_t from_fixed = scaled >> 16;
val = (from_fixed < -32768 ? -32768 :
from_fixed > 32767 ? 32767 : from_fixed);
ret |= (val & 0xffff) << (word * 16);
}
return ret;
}
uint64 helper_bshuffle(uint64_t gsr, uint64_t src1, uint64_t src2)
{
union {
uint64_t ll[2];
uint8_t b[16];
} s;
VIS64 r;
uint32_t i, mask, host;
/* Set up S such that we can index across all of the bytes. */
#ifdef HOST_WORDS_BIGENDIAN
s.ll[0] = src1;
s.ll[1] = src2;
host = 0;
#else
s.ll[1] = src1;
s.ll[0] = src2;
host = 15;
#endif
mask = gsr >> 32;
for (i = 0; i < 8; ++i) {
unsigned e = (mask >> (28 - i*4)) & 0xf;
r.VIS_B64(i) = s.b[e ^ host];
}
return r.ll;
}