//#define DEBUG_EXCEPTIONS
//#define DEBUG_SOFTWARE_TLB
+#ifdef DEBUG_SOFTWARE_TLB
+# define LOG_SWTLB(...) qemu_log(__VA_ARGS__)
+#else
+# define LOG_SWTLB(...) do { } while (0)
+#endif
+
+
/*****************************************************************************/
/* Exceptions processing helpers */
}
/*****************************************************************************/
-/* Registers load and stores */
-target_ulong helper_load_cr (void)
-{
- return (env->crf[0] << 28) |
- (env->crf[1] << 24) |
- (env->crf[2] << 20) |
- (env->crf[3] << 16) |
- (env->crf[4] << 12) |
- (env->crf[5] << 8) |
- (env->crf[6] << 4) |
- (env->crf[7] << 0);
-}
-
-void helper_store_cr (target_ulong val, uint32_t mask)
-{
- int i, sh;
-
- for (i = 0, sh = 7; i < 8; i++, sh--) {
- if (mask & (1 << sh))
- env->crf[i] = (val >> (sh * 4)) & 0xFUL;
- }
-}
-
-/*****************************************************************************/
/* SPR accesses */
void helper_load_dump_spr (uint32_t sprn)
{
- if (loglevel != 0) {
- fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
+ qemu_log("Read SPR %d %03x => " ADDRX "\n",
sprn, sprn, env->spr[sprn]);
- }
}
void helper_store_dump_spr (uint32_t sprn)
{
- if (loglevel != 0) {
- fprintf(logfile, "Write SPR %d %03x <= " ADDRX "\n",
+ qemu_log("Write SPR %d %03x <= " ADDRX "\n",
sprn, sprn, env->spr[sprn]);
- }
}
target_ulong helper_load_tbl (void)
env->hflags_nmsr &= ~(1 << MSR_LE);
env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
env->hflags |= env->hflags_nmsr;
- if (loglevel != 0) {
- fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
+ qemu_log("%s: set endianness to %c => " ADDRX "\n",
__func__, val & 0x8 ? 'l' : 'b', env->hflags);
- }
}
env->spr[SPR_HID0] = (uint32_t)val;
}
/* fre - fre. */
uint64_t helper_fre (uint64_t arg)
{
- CPU_DoubleU fone, farg;
- fone.ll = 0x3FF0000000000000ULL; /* 1.0 */
+ CPU_DoubleU farg;
farg.ll = arg;
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
} else {
- farg.d = float64_div(fone.d, farg.d, &env->fp_status);
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
}
return farg.d;
}
/* fres - fres. */
uint64_t helper_fres (uint64_t arg)
{
- CPU_DoubleU fone, farg;
+ CPU_DoubleU farg;
float32 f32;
- fone.ll = 0x3FF0000000000000ULL; /* 1.0 */
farg.ll = arg;
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
} else {
- farg.d = float64_div(fone.d, farg.d, &env->fp_status);
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
f32 = float64_to_float32(farg.d, &env->fp_status);
farg.d = float32_to_float64(f32, &env->fp_status);
}
/* frsqrte - frsqrte. */
uint64_t helper_frsqrte (uint64_t arg)
{
- CPU_DoubleU fone, farg;
+ CPU_DoubleU farg;
float32 f32;
- fone.ll = 0x3FF0000000000000ULL; /* 1.0 */
farg.ll = arg;
if (unlikely(float64_is_signaling_nan(farg.d))) {
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
farg.d = float64_sqrt(farg.d, &env->fp_status);
- farg.d = float64_div(fone.d, farg.d, &env->fp_status);
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
f32 = float64_to_float32(farg.d, &env->fp_status);
farg.d = float32_to_float64(f32, &env->fp_status);
}
void helper_rfi (void)
{
do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
- ~((target_ulong)0xFFFF0000), 1);
+ ~((target_ulong)0x0), 1);
}
#if defined(TARGET_PPC64)
void helper_rfid (void)
{
do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
- ~((target_ulong)0xFFFF0000), 0);
+ ~((target_ulong)0x0), 0);
}
void helper_hrfid (void)
{
do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
- ~((target_ulong)0xFFFF0000), 0);
+ ~((target_ulong)0x0), 0);
}
#endif
#endif
target_ulong val = 0;
if (unlikely(env->dcr_env == NULL)) {
- if (loglevel != 0) {
- fprintf(logfile, "No DCR environment\n");
- }
+ qemu_log("No DCR environment\n");
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
- if (loglevel != 0) {
- fprintf(logfile, "DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
- }
+ qemu_log("DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
}
void helper_store_dcr (target_ulong dcrn, target_ulong val)
{
if (unlikely(env->dcr_env == NULL)) {
- if (loglevel != 0) {
- fprintf(logfile, "No DCR environment\n");
- }
+ qemu_log("No DCR environment\n");
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
- if (loglevel != 0) {
- fprintf(logfile, "DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
- }
+ qemu_log("DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
}
for (index = ARRAY_SIZE(r->element)-1; index >= 0; index--)
#endif
+/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
+ * execute the following block. */
+#define DO_HANDLE_NAN(result, x) \
+ if (float32_is_nan(x) || float32_is_signaling_nan(x)) { \
+ CPU_FloatU __f; \
+ __f.f = x; \
+ __f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
+ result = __f.f; \
+ } else
+
+#define HANDLE_NAN1(result, x) \
+ DO_HANDLE_NAN(result, x)
+#define HANDLE_NAN2(result, x, y) \
+ DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y)
+#define HANDLE_NAN3(result, x, y, z) \
+ DO_HANDLE_NAN(result, x) DO_HANDLE_NAN(result, y) DO_HANDLE_NAN(result, z)
+
/* Saturating arithmetic helpers. */
#define SATCVT(from, to, from_type, to_type, min, max, use_min, use_max) \
static always_inline to_type cvt##from##to (from_type x, int *sat) \
#undef I
#undef LVE
+void helper_mtvscr (ppc_avr_t *r)
+{
+#if defined(WORDS_BIGENDIAN)
+ env->vscr = r->u32[3];
+#else
+ env->vscr = r->u32[0];
+#endif
+ set_flush_to_zero(vscr_nj, &env->vec_status);
+}
+
void helper_vaddcuw (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{
int i;
#undef VARITH_DO
#undef VARITH
+#define VARITHFP(suffix, func) \
+ void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
+ r->f[i] = func(a->f[i], b->f[i], &env->vec_status); \
+ } \
+ } \
+ }
+VARITHFP(addfp, float32_add)
+VARITHFP(subfp, float32_sub)
+#undef VARITHFP
+
+#define VARITHSAT_CASE(type, op, cvt, element) \
+ { \
+ type result = (type)a->element[i] op (type)b->element[i]; \
+ r->element[i] = cvt(result, &sat); \
+ }
+
+#define VARITHSAT_DO(name, op, optype, cvt, element) \
+ void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ int sat = 0; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
+ switch (sizeof(r->element[0])) { \
+ case 1: VARITHSAT_CASE(optype, op, cvt, element); break; \
+ case 2: VARITHSAT_CASE(optype, op, cvt, element); break; \
+ case 4: VARITHSAT_CASE(optype, op, cvt, element); break; \
+ } \
+ } \
+ if (sat) { \
+ env->vscr |= (1 << VSCR_SAT); \
+ } \
+ }
+#define VARITHSAT_SIGNED(suffix, element, optype, cvt) \
+ VARITHSAT_DO(adds##suffix##s, +, optype, cvt, element) \
+ VARITHSAT_DO(subs##suffix##s, -, optype, cvt, element)
+#define VARITHSAT_UNSIGNED(suffix, element, optype, cvt) \
+ VARITHSAT_DO(addu##suffix##s, +, optype, cvt, element) \
+ VARITHSAT_DO(subu##suffix##s, -, optype, cvt, element)
+VARITHSAT_SIGNED(b, s8, int16_t, cvtshsb)
+VARITHSAT_SIGNED(h, s16, int32_t, cvtswsh)
+VARITHSAT_SIGNED(w, s32, int64_t, cvtsdsw)
+VARITHSAT_UNSIGNED(b, u8, uint16_t, cvtshub)
+VARITHSAT_UNSIGNED(h, u16, uint32_t, cvtswuh)
+VARITHSAT_UNSIGNED(w, u32, uint64_t, cvtsduw)
+#undef VARITHSAT_CASE
+#undef VARITHSAT_DO
+#undef VARITHSAT_SIGNED
+#undef VARITHSAT_UNSIGNED
+
#define VAVG_DO(name, element, etype) \
void helper_v##name (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
#undef VAVG_DO
#undef VAVG
+#define VCF(suffix, cvt, element) \
+ void helper_vcf##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ float32 t = cvt(b->element[i], &env->vec_status); \
+ r->f[i] = float32_scalbn (t, -uim, &env->vec_status); \
+ } \
+ }
+VCF(ux, uint32_to_float32, u32)
+VCF(sx, int32_to_float32, s32)
+#undef VCF
+
+#define VCMP_DO(suffix, compare, element, record) \
+ void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ uint32_t ones = (uint32_t)-1; \
+ uint32_t all = ones; \
+ uint32_t none = 0; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
+ uint32_t result = (a->element[i] compare b->element[i] ? ones : 0x0); \
+ switch (sizeof (a->element[0])) { \
+ case 4: r->u32[i] = result; break; \
+ case 2: r->u16[i] = result; break; \
+ case 1: r->u8[i] = result; break; \
+ } \
+ all &= result; \
+ none |= result; \
+ } \
+ if (record) { \
+ env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
+ } \
+ }
+#define VCMP(suffix, compare, element) \
+ VCMP_DO(suffix, compare, element, 0) \
+ VCMP_DO(suffix##_dot, compare, element, 1)
+VCMP(equb, ==, u8)
+VCMP(equh, ==, u16)
+VCMP(equw, ==, u32)
+VCMP(gtub, >, u8)
+VCMP(gtuh, >, u16)
+VCMP(gtuw, >, u32)
+VCMP(gtsb, >, s8)
+VCMP(gtsh, >, s16)
+VCMP(gtsw, >, s32)
+#undef VCMP_DO
+#undef VCMP
+
+#define VCMPFP_DO(suffix, compare, order, record) \
+ void helper_vcmp##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ uint32_t ones = (uint32_t)-1; \
+ uint32_t all = ones; \
+ uint32_t none = 0; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ uint32_t result; \
+ int rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status); \
+ if (rel == float_relation_unordered) { \
+ result = 0; \
+ } else if (rel compare order) { \
+ result = ones; \
+ } else { \
+ result = 0; \
+ } \
+ r->u32[i] = result; \
+ all &= result; \
+ none |= result; \
+ } \
+ if (record) { \
+ env->crf[6] = ((all != 0) << 3) | ((none == 0) << 1); \
+ } \
+ }
+#define VCMPFP(suffix, compare, order) \
+ VCMPFP_DO(suffix, compare, order, 0) \
+ VCMPFP_DO(suffix##_dot, compare, order, 1)
+VCMPFP(eqfp, ==, float_relation_equal)
+VCMPFP(gefp, !=, float_relation_less)
+VCMPFP(gtfp, ==, float_relation_greater)
+#undef VCMPFP_DO
+#undef VCMPFP
+
+static always_inline void vcmpbfp_internal (ppc_avr_t *r, ppc_avr_t *a,
+ ppc_avr_t *b, int record)
+{
+ int i;
+ int all_in = 0;
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) {
+ int le_rel = float32_compare_quiet(a->f[i], b->f[i], &env->vec_status);
+ if (le_rel == float_relation_unordered) {
+ r->u32[i] = 0xc0000000;
+ /* ALL_IN does not need to be updated here. */
+ } else {
+ float32 bneg = float32_chs(b->f[i]);
+ int ge_rel = float32_compare_quiet(a->f[i], bneg, &env->vec_status);
+ int le = le_rel != float_relation_greater;
+ int ge = ge_rel != float_relation_less;
+ r->u32[i] = ((!le) << 31) | ((!ge) << 30);
+ all_in |= (!le | !ge);
+ }
+ }
+ if (record) {
+ env->crf[6] = (all_in == 0) << 1;
+ }
+}
+
+void helper_vcmpbfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+{
+ vcmpbfp_internal(r, a, b, 0);
+}
+
+void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
+{
+ vcmpbfp_internal(r, a, b, 1);
+}
+
+#define VCT(suffix, satcvt, element) \
+ void helper_vct##suffix (ppc_avr_t *r, ppc_avr_t *b, uint32_t uim) \
+ { \
+ int i; \
+ int sat = 0; \
+ float_status s = env->vec_status; \
+ set_float_rounding_mode(float_round_to_zero, &s); \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ if (float32_is_nan(b->f[i]) || \
+ float32_is_signaling_nan(b->f[i])) { \
+ r->element[i] = 0; \
+ } else { \
+ float64 t = float32_to_float64(b->f[i], &s); \
+ int64_t j; \
+ t = float64_scalbn(t, uim, &s); \
+ j = float64_to_int64(t, &s); \
+ r->element[i] = satcvt(j, &sat); \
+ } \
+ } \
+ if (sat) { \
+ env->vscr |= (1 << VSCR_SAT); \
+ } \
+ }
+VCT(uxs, cvtsduw, u32)
+VCT(sxs, cvtsdsw, s32)
+#undef VCT
+
+void helper_vmaddfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) {
+ HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
+ /* Need to do the computation in higher precision and round
+ * once at the end. */
+ float64 af, bf, cf, t;
+ af = float32_to_float64(a->f[i], &env->vec_status);
+ bf = float32_to_float64(b->f[i], &env->vec_status);
+ cf = float32_to_float64(c->f[i], &env->vec_status);
+ t = float64_mul(af, cf, &env->vec_status);
+ t = float64_add(t, bf, &env->vec_status);
+ r->f[i] = float64_to_float32(t, &env->vec_status);
+ }
+ }
+}
+
void helper_vmhaddshs (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int sat = 0;
#undef VMINMAX_DO
#undef VMINMAX
+#define VMINMAXFP(suffix, rT, rF) \
+ void helper_v##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ HANDLE_NAN2(r->f[i], a->f[i], b->f[i]) { \
+ if (float32_lt_quiet(a->f[i], b->f[i], &env->vec_status)) { \
+ r->f[i] = rT->f[i]; \
+ } else { \
+ r->f[i] = rF->f[i]; \
+ } \
+ } \
+ } \
+ }
+VMINMAXFP(minfp, a, b)
+VMINMAXFP(maxfp, b, a)
+#undef VMINMAXFP
+
void helper_vmladduhm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
int i;
}
#if defined(WORDS_BIGENDIAN)
#define MRGHI 0
-#define MRGL0 1
+#define MRGLO 1
#else
#define MRGHI 1
#define MRGLO 0
#undef VMUL_DO
#undef VMUL
+void helper_vnmsubfp (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) {
+ HANDLE_NAN3(r->f[i], a->f[i], b->f[i], c->f[i]) {
+ /* Need to do the computation is higher precision and round
+ * once at the end. */
+ float64 af, bf, cf, t;
+ af = float32_to_float64(a->f[i], &env->vec_status);
+ bf = float32_to_float64(b->f[i], &env->vec_status);
+ cf = float32_to_float64(c->f[i], &env->vec_status);
+ t = float64_mul(af, cf, &env->vec_status);
+ t = float64_sub(t, bf, &env->vec_status);
+ t = float64_chs(t);
+ r->f[i] = float64_to_float32(t, &env->vec_status);
+ }
+ }
+}
+
void helper_vperm (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
ppc_avr_t result;
#undef VPK
#undef PKBIG
+void helper_vrefp (ppc_avr_t *r, ppc_avr_t *b)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) {
+ HANDLE_NAN1(r->f[i], b->f[i]) {
+ r->f[i] = float32_div(float32_one, b->f[i], &env->vec_status);
+ }
+ }
+}
+
+#define VRFI(suffix, rounding) \
+ void helper_vrfi##suffix (ppc_avr_t *r, ppc_avr_t *b) \
+ { \
+ int i; \
+ float_status s = env->vec_status; \
+ set_float_rounding_mode(rounding, &s); \
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
+ HANDLE_NAN1(r->f[i], b->f[i]) { \
+ r->f[i] = float32_round_to_int (b->f[i], &s); \
+ } \
+ } \
+ }
+VRFI(n, float_round_nearest_even)
+VRFI(m, float_round_down)
+VRFI(p, float_round_up)
+VRFI(z, float_round_to_zero)
+#undef VRFI
+
#define VROTATE(suffix, element) \
void helper_vrl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
VROTATE(w, u32)
#undef VROTATE
+void helper_vrsqrtefp (ppc_avr_t *r, ppc_avr_t *b)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) {
+ HANDLE_NAN1(r->f[i], b->f[i]) {
+ float32 t = float32_sqrt(b->f[i], &env->vec_status);
+ r->f[i] = float32_div(float32_one, t, &env->vec_status);
+ }
+ }
+}
+
void helper_vsel (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{
r->u64[0] = (a->u64[0] & ~c->u64[0]) | (b->u64[0] & c->u64[0]);
r->u64[1] = (a->u64[1] & ~c->u64[1]) | (b->u64[1] & c->u64[1]);
}
+void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(r->f); i++) {
+ HANDLE_NAN1(r->f[i], b->f[i]) {
+ r->f[i] = float32_log2(b->f[i], &env->vec_status);
+ }
+ }
+}
+
+#if defined(WORDS_BIGENDIAN)
+#define LEFT 0
+#define RIGHT 1
+#else
+#define LEFT 1
+#define RIGHT 0
+#endif
+/* The specification says that the results are undefined if all of the
+ * shift counts are not identical. We check to make sure that they are
+ * to conform to what real hardware appears to do. */
+#define VSHIFT(suffix, leftp) \
+ void helper_vs##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
+ { \
+ int shift = b->u8[LO_IDX*15] & 0x7; \
+ int doit = 1; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \
+ doit = doit && ((b->u8[i] & 0x7) == shift); \
+ } \
+ if (doit) { \
+ if (shift == 0) { \
+ *r = *a; \
+ } else if (leftp) { \
+ uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \
+ r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \
+ r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \
+ } else { \
+ uint64_t carry = a->u64[HI_IDX] << (64 - shift); \
+ r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \
+ r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \
+ } \
+ } \
+ }
+VSHIFT(l, LEFT)
+VSHIFT(r, RIGHT)
+#undef VSHIFT
+#undef LEFT
+#undef RIGHT
+
#define VSL(suffix, element) \
void helper_vsl##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
#undef SPLAT_ELEMENT
#undef _SPLAT_MASKED
+#define VSPLTI(suffix, element, splat_type) \
+ void helper_vspltis##suffix (ppc_avr_t *r, uint32_t splat) \
+ { \
+ splat_type x = (int8_t)(splat << 3) >> 3; \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
+ r->element[i] = x; \
+ } \
+ }
+VSPLTI(b, s8, int8_t)
+VSPLTI(h, s16, int16_t)
+VSPLTI(w, s32, int32_t)
+#undef VSPLTI
+
#define VSR(suffix, element) \
void helper_vsr##suffix (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \
#undef UPKHI
#undef UPKLO
+#undef DO_HANDLE_NAN
+#undef HANDLE_NAN1
+#undef HANDLE_NAN2
+#undef HANDLE_NAN3
#undef VECTOR_FOR_INORDER_I
#undef HI_IDX
#undef LO_IDX
{
CPU_FloatU u;
- u.f = int32_to_float32(val, &env->spe_status);
+ u.f = int32_to_float32(val, &env->vec_status);
return u.l;
}
{
CPU_FloatU u;
- u.f = uint32_to_float32(val, &env->spe_status);
+ u.f = uint32_to_float32(val, &env->vec_status);
return u.l;
}
if (unlikely(float32_is_nan(u.f)))
return 0;
- return float32_to_int32(u.f, &env->spe_status);
+ return float32_to_int32(u.f, &env->vec_status);
}
static always_inline uint32_t efsctui (uint32_t val)
if (unlikely(float32_is_nan(u.f)))
return 0;
- return float32_to_uint32(u.f, &env->spe_status);
+ return float32_to_uint32(u.f, &env->vec_status);
}
static always_inline uint32_t efsctsiz (uint32_t val)
if (unlikely(float32_is_nan(u.f)))
return 0;
- return float32_to_int32_round_to_zero(u.f, &env->spe_status);
+ return float32_to_int32_round_to_zero(u.f, &env->vec_status);
}
static always_inline uint32_t efsctuiz (uint32_t val)
if (unlikely(float32_is_nan(u.f)))
return 0;
- return float32_to_uint32_round_to_zero(u.f, &env->spe_status);
+ return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
}
static always_inline uint32_t efscfsf (uint32_t val)
CPU_FloatU u;
float32 tmp;
- u.f = int32_to_float32(val, &env->spe_status);
- tmp = int64_to_float32(1ULL << 32, &env->spe_status);
- u.f = float32_div(u.f, tmp, &env->spe_status);
+ u.f = int32_to_float32(val, &env->vec_status);
+ tmp = int64_to_float32(1ULL << 32, &env->vec_status);
+ u.f = float32_div(u.f, tmp, &env->vec_status);
return u.l;
}
CPU_FloatU u;
float32 tmp;
- u.f = uint32_to_float32(val, &env->spe_status);
- tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
- u.f = float32_div(u.f, tmp, &env->spe_status);
+ u.f = uint32_to_float32(val, &env->vec_status);
+ tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
+ u.f = float32_div(u.f, tmp, &env->vec_status);
return u.l;
}
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
return 0;
- tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
- u.f = float32_mul(u.f, tmp, &env->spe_status);
+ tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
+ u.f = float32_mul(u.f, tmp, &env->vec_status);
- return float32_to_int32(u.f, &env->spe_status);
+ return float32_to_int32(u.f, &env->vec_status);
}
static always_inline uint32_t efsctuf (uint32_t val)
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
return 0;
- tmp = uint64_to_float32(1ULL << 32, &env->spe_status);
- u.f = float32_mul(u.f, tmp, &env->spe_status);
+ tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
+ u.f = float32_mul(u.f, tmp, &env->vec_status);
- return float32_to_uint32(u.f, &env->spe_status);
+ return float32_to_uint32(u.f, &env->vec_status);
}
#define HELPER_SPE_SINGLE_CONV(name) \
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- u1.f = float32_add(u1.f, u2.f, &env->spe_status);
+ u1.f = float32_add(u1.f, u2.f, &env->vec_status);
return u1.l;
}
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- u1.f = float32_sub(u1.f, u2.f, &env->spe_status);
+ u1.f = float32_sub(u1.f, u2.f, &env->vec_status);
return u1.l;
}
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- u1.f = float32_mul(u1.f, u2.f, &env->spe_status);
+ u1.f = float32_mul(u1.f, u2.f, &env->vec_status);
return u1.l;
}
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- u1.f = float32_div(u1.f, u2.f, &env->spe_status);
+ u1.f = float32_div(u1.f, u2.f, &env->vec_status);
return u1.l;
}
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- return float32_lt(u1.f, u2.f, &env->spe_status) ? 4 : 0;
+ return float32_lt(u1.f, u2.f, &env->vec_status) ? 4 : 0;
}
static always_inline uint32_t efststgt (uint32_t op1, uint32_t op2)
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- return float32_le(u1.f, u2.f, &env->spe_status) ? 0 : 4;
+ return float32_le(u1.f, u2.f, &env->vec_status) ? 0 : 4;
}
static always_inline uint32_t efststeq (uint32_t op1, uint32_t op2)
CPU_FloatU u1, u2;
u1.l = op1;
u2.l = op2;
- return float32_eq(u1.f, u2.f, &env->spe_status) ? 4 : 0;
+ return float32_eq(u1.f, u2.f, &env->vec_status) ? 4 : 0;
}
static always_inline uint32_t efscmplt (uint32_t op1, uint32_t op2)
{
CPU_DoubleU u;
- u.d = int32_to_float64(val, &env->spe_status);
+ u.d = int32_to_float64(val, &env->vec_status);
return u.ll;
}
{
CPU_DoubleU u;
- u.d = int64_to_float64(val, &env->spe_status);
+ u.d = int64_to_float64(val, &env->vec_status);
return u.ll;
}
{
CPU_DoubleU u;
- u.d = uint32_to_float64(val, &env->spe_status);
+ u.d = uint32_to_float64(val, &env->vec_status);
return u.ll;
}
{
CPU_DoubleU u;
- u.d = uint64_to_float64(val, &env->spe_status);
+ u.d = uint64_to_float64(val, &env->vec_status);
return u.ll;
}
if (unlikely(float64_is_nan(u.d)))
return 0;
- return float64_to_int32(u.d, &env->spe_status);
+ return float64_to_int32(u.d, &env->vec_status);
}
uint32_t helper_efdctui (uint64_t val)
if (unlikely(float64_is_nan(u.d)))
return 0;
- return float64_to_uint32(u.d, &env->spe_status);
+ return float64_to_uint32(u.d, &env->vec_status);
}
uint32_t helper_efdctsiz (uint64_t val)
if (unlikely(float64_is_nan(u.d)))
return 0;
- return float64_to_int32_round_to_zero(u.d, &env->spe_status);
+ return float64_to_int32_round_to_zero(u.d, &env->vec_status);
}
uint64_t helper_efdctsidz (uint64_t val)
if (unlikely(float64_is_nan(u.d)))
return 0;
- return float64_to_int64_round_to_zero(u.d, &env->spe_status);
+ return float64_to_int64_round_to_zero(u.d, &env->vec_status);
}
uint32_t helper_efdctuiz (uint64_t val)
if (unlikely(float64_is_nan(u.d)))
return 0;
- return float64_to_uint32_round_to_zero(u.d, &env->spe_status);
+ return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
}
uint64_t helper_efdctuidz (uint64_t val)
if (unlikely(float64_is_nan(u.d)))
return 0;
- return float64_to_uint64_round_to_zero(u.d, &env->spe_status);
+ return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
}
uint64_t helper_efdcfsf (uint32_t val)
CPU_DoubleU u;
float64 tmp;
- u.d = int32_to_float64(val, &env->spe_status);
- tmp = int64_to_float64(1ULL << 32, &env->spe_status);
- u.d = float64_div(u.d, tmp, &env->spe_status);
+ u.d = int32_to_float64(val, &env->vec_status);
+ tmp = int64_to_float64(1ULL << 32, &env->vec_status);
+ u.d = float64_div(u.d, tmp, &env->vec_status);
return u.ll;
}
CPU_DoubleU u;
float64 tmp;
- u.d = uint32_to_float64(val, &env->spe_status);
- tmp = int64_to_float64(1ULL << 32, &env->spe_status);
- u.d = float64_div(u.d, tmp, &env->spe_status);
+ u.d = uint32_to_float64(val, &env->vec_status);
+ tmp = int64_to_float64(1ULL << 32, &env->vec_status);
+ u.d = float64_div(u.d, tmp, &env->vec_status);
return u.ll;
}
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
return 0;
- tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
- u.d = float64_mul(u.d, tmp, &env->spe_status);
+ tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
+ u.d = float64_mul(u.d, tmp, &env->vec_status);
- return float64_to_int32(u.d, &env->spe_status);
+ return float64_to_int32(u.d, &env->vec_status);
}
uint32_t helper_efdctuf (uint64_t val)
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
return 0;
- tmp = uint64_to_float64(1ULL << 32, &env->spe_status);
- u.d = float64_mul(u.d, tmp, &env->spe_status);
+ tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
+ u.d = float64_mul(u.d, tmp, &env->vec_status);
- return float64_to_uint32(u.d, &env->spe_status);
+ return float64_to_uint32(u.d, &env->vec_status);
}
uint32_t helper_efscfd (uint64_t val)
CPU_FloatU u2;
u1.ll = val;
- u2.f = float64_to_float32(u1.d, &env->spe_status);
+ u2.f = float64_to_float32(u1.d, &env->vec_status);
return u2.l;
}
CPU_FloatU u1;
u1.l = val;
- u2.d = float32_to_float64(u1.f, &env->spe_status);
+ u2.d = float32_to_float64(u1.f, &env->vec_status);
return u2.ll;
}
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- u1.d = float64_add(u1.d, u2.d, &env->spe_status);
+ u1.d = float64_add(u1.d, u2.d, &env->vec_status);
return u1.ll;
}
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- u1.d = float64_sub(u1.d, u2.d, &env->spe_status);
+ u1.d = float64_sub(u1.d, u2.d, &env->vec_status);
return u1.ll;
}
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- u1.d = float64_mul(u1.d, u2.d, &env->spe_status);
+ u1.d = float64_mul(u1.d, u2.d, &env->vec_status);
return u1.ll;
}
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- u1.d = float64_div(u1.d, u2.d, &env->spe_status);
+ u1.d = float64_div(u1.d, u2.d, &env->vec_status);
return u1.ll;
}
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- return float64_lt(u1.d, u2.d, &env->spe_status) ? 4 : 0;
+ return float64_lt(u1.d, u2.d, &env->vec_status) ? 4 : 0;
}
uint32_t helper_efdtstgt (uint64_t op1, uint64_t op2)
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- return float64_le(u1.d, u2.d, &env->spe_status) ? 0 : 4;
+ return float64_le(u1.d, u2.d, &env->vec_status) ? 0 : 4;
}
uint32_t helper_efdtsteq (uint64_t op1, uint64_t op2)
CPU_DoubleU u1, u2;
u1.ll = op1;
u2.ll = op2;
- return float64_eq(u1.d, u2.d, &env->spe_status) ? 4 : 0;
+ return float64_eq(u1.d, u2.d, &env->vec_status) ? 4 : 0;
}
uint32_t helper_efdcmplt (uint64_t op1, uint64_t op2)
/* Segment registers load and store */
target_ulong helper_load_sr (target_ulong sr_num)
{
+#if defined(TARGET_PPC64)
+ if (env->mmu_model & POWERPC_MMU_64)
+ return ppc_load_sr(env, sr_num);
+#endif
return env->sr[sr_num];
}
return ppc_load_slb(env, slb_nr);
}
-void helper_store_slb (target_ulong slb_nr, target_ulong rs)
+void helper_store_slb (target_ulong rb, target_ulong rs)
{
- ppc_store_slb(env, slb_nr, rs);
+ ppc_store_slb(env, rb, rs);
}
void helper_slbia (void)
EPN = env->spr[SPR_DMISS];
}
way = (env->spr[SPR_SRR1] >> 17) & 1;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
+ LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
" PTE1 " ADDRX " way %d\n",
__func__, new_EPN, EPN, CMP, RPN, way);
- }
-#endif
/* Store this TLB */
ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
way, is_code, CMP, RPN);
CMP = env->spr[SPR_PTEHI];
EPN = env->spr[SPR_TLBMISS] & ~0x3;
way = env->spr[SPR_TLBMISS] & 0x3;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
+ LOG_SWTLB("%s: EPN " ADDRX " " ADDRX " PTE0 " ADDRX
" PTE1 " ADDRX " way %d\n",
__func__, new_EPN, EPN, CMP, RPN, way);
- }
-#endif
/* Store this TLB */
ppc6xx_tlb_store(env, (uint32_t)(new_EPN & TARGET_PAGE_MASK),
way, is_code, CMP, RPN);
ppcemb_tlb_t *tlb;
target_ulong page, end;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
- }
-#endif
+ LOG_SWTLB("%s entry %d val " ADDRX "\n", __func__, (int)entry, val);
entry &= 0x3F;
tlb = &env->tlb[entry].tlbe;
/* Invalidate previous TLB (if it's valid) */
if (tlb->prot & PAGE_VALID) {
end = tlb->EPN + tlb->size;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
+ LOG_SWTLB("%s: invalidate old TLB %d start " ADDRX
" end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
- }
-#endif
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
tlb_flush_page(env, page);
}
}
tlb->PID = env->spr[SPR_40x_PID]; /* PID */
tlb->attr = val & 0xFF;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
+ LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
" size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
(int)entry, tlb->RPN, tlb->EPN, tlb->size,
tlb->prot & PAGE_READ ? 'r' : '-',
tlb->prot & PAGE_WRITE ? 'w' : '-',
tlb->prot & PAGE_EXEC ? 'x' : '-',
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
- }
-#endif
/* Invalidate new TLB (if valid) */
if (tlb->prot & PAGE_VALID) {
end = tlb->EPN + tlb->size;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
+ LOG_SWTLB("%s: invalidate TLB %d start " ADDRX
" end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
- }
-#endif
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
tlb_flush_page(env, page);
}
{
ppcemb_tlb_t *tlb;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
- }
-#endif
+ LOG_SWTLB("%s entry %i val " ADDRX "\n", __func__, (int)entry, val);
entry &= 0x3F;
tlb = &env->tlb[entry].tlbe;
tlb->RPN = val & 0xFFFFFC00;
tlb->prot |= PAGE_EXEC;
if (val & 0x100)
tlb->prot |= PAGE_WRITE;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
+ LOG_SWTLB("%s: set up TLB %d RPN " PADDRX " EPN " ADDRX
" size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
(int)entry, tlb->RPN, tlb->EPN, tlb->size,
tlb->prot & PAGE_READ ? 'r' : '-',
tlb->prot & PAGE_WRITE ? 'w' : '-',
tlb->prot & PAGE_EXEC ? 'x' : '-',
tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
- }
-#endif
}
target_ulong helper_4xx_tlbsx (target_ulong address)
target_ulong EPN, RPN, size;
int do_flush_tlbs;
-#if defined (DEBUG_SOFTWARE_TLB)
- if (loglevel != 0) {
- fprintf(logfile, "%s word %d entry %d value " ADDRX "\n",
+ LOG_SWTLB("%s word %d entry %d value " ADDRX "\n",
__func__, word, (int)entry, value);
- }
-#endif
do_flush_tlbs = 0;
entry &= 0x3F;
tlb = &env->tlb[entry].tlbe;