X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=target-ppc%2Fop_helper.c;h=56fab9cb06438f7f2326aca61c48169e2a9b21cc;hb=db241f403213807a3ab9ea9eb88649dcbf71dba4;hp=6cf47a357678072c6e75011ec92e2fbfc4f2a790;hpb=56fdd213efe5c542efba00fb504781c8953c0988;p=qemu diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 6cf47a3..56fab9c 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -54,30 +54,6 @@ void helper_raise_exception (uint32_t exception) } /*****************************************************************************/ -/* 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) { @@ -1671,20 +1647,20 @@ static always_inline void do_rfi (target_ulong nip, target_ulong msr, 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 @@ -2220,6 +2196,119 @@ 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; @@ -2456,6 +2545,25 @@ VMUL(uh, u16, u32) #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; @@ -2532,6 +2640,16 @@ VPK(uwum, u32, u16, I, 0) #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) \ { \ @@ -2565,6 +2683,17 @@ VROTATE(h, u16) 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]); @@ -2594,7 +2723,7 @@ void helper_vlogefp (ppc_avr_t *r, ppc_avr_t *b) #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*0x15] & 0x7; \ + int shift = b->u8[LO_IDX*15] & 0x7; \ int doit = 1; \ int i; \ for (i = 0; i < ARRAY_SIZE(r->u8); i++) { \ @@ -3599,6 +3728,10 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) /* 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]; } @@ -3614,9 +3747,9 @@ target_ulong helper_load_slb (target_ulong slb_nr) 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)