aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/helper.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 14:57:11 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-01-04 14:57:11 +0000
commitfb0eaffc6d9982b5eee439b8461851bd18bf35ce (patch)
tree2ca3095648df44d4813b4dd56202de4f9d1efcfa /target-ppc/helper.c
parent07ad1b93a365a15c77b5848bba0f6a3399bce076 (diff)
PowerPC fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@483 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/helper.c')
-rw-r--r--target-ppc/helper.c145
1 files changed, 75 insertions, 70 deletions
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 87e54111e2..b263d6535f 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -121,67 +121,67 @@ void do_store_msr (uint32_t msr_value)
}
/* The 32 MSB of the target fpr are undefined. They'll be zero... */
-uint32_t do_load_fpscr (void)
+/* Floating point operations helpers */
+void do_load_fpscr (void)
{
- return (fpscr_fx << FPSCR_FX) |
- (fpscr_fex << FPSCR_FEX) |
- (fpscr_vx << FPSCR_VX) |
- (fpscr_ox << FPSCR_OX) |
- (fpscr_ux << FPSCR_UX) |
- (fpscr_zx << FPSCR_ZX) |
- (fpscr_xx << FPSCR_XX) |
- (fpscr_vsxnan << FPSCR_VXSNAN) |
- (fpscr_vxisi << FPSCR_VXISI) |
- (fpscr_vxidi << FPSCR_VXIDI) |
- (fpscr_vxzdz << FPSCR_VXZDZ) |
- (fpscr_vximz << FPSCR_VXIMZ) |
- (fpscr_fr << FPSCR_FR) |
- (fpscr_fi << FPSCR_FI) |
- (fpscr_fprf << FPSCR_FPRF) |
- (fpscr_vxsoft << FPSCR_VXSOFT) |
- (fpscr_vxsqrt << FPSCR_VXSQRT) |
- (fpscr_oe << FPSCR_OE) |
- (fpscr_ue << FPSCR_UE) |
- (fpscr_ze << FPSCR_ZE) |
- (fpscr_xe << FPSCR_XE) |
- (fpscr_ni << FPSCR_NI) |
- (fpscr_rn << FPSCR_RN);
+ /* The 32 MSB of the target fpr are undefined.
+ * They'll be zero...
+ */
+ union {
+ double d;
+ struct {
+ uint32_t u[2];
+ } s;
+ } u;
+ int i;
+
+ u.s.u[0] = 0;
+ u.s.u[1] = 0;
+ for (i = 0; i < 8; i++)
+ u.s.u[1] |= env->fpscr[i] << (4 * i);
+ FT0 = u.d;
}
-/* We keep only 32 bits of input... */
-/* For now, this is COMPLETELY BUGGY ! */
-void do_store_fpscr (uint8_t mask, uint32_t fp)
+void do_store_fpscr (uint32_t mask)
{
+ /*
+ * We use only the 32 LSB of the incoming fpr
+ */
+ union {
+ double d;
+ struct {
+ uint32_t u[2];
+ } s;
+ } u;
int i;
- for (i = 0; i < 7; i++) {
- if ((mask & (1 << i)) == 0)
- fp &= ~(0xf << (4 * i));
+ u.d = FT0;
+ if (mask & 0x80)
+ env->fpscr[0] = (env->fpscr[0] & 0x9) | ((u.s.u[1] >> 28) & ~0x9);
+ for (i = 1; i < 7; i++) {
+ if (mask & (1 << (7 - i)))
+ env->fpscr[i] = (u.s.u[1] >> (4 * (7 - i))) & 0xF;
+ }
+ /* TODO: update FEX & VX */
+ /* Set rounding mode */
+ switch (env->fpscr[0] & 0x3) {
+ case 0:
+ /* Best approximation (round to nearest) */
+ fesetround(FE_TONEAREST);
+ break;
+ case 1:
+ /* Smaller magnitude (round toward zero) */
+ fesetround(FE_TOWARDZERO);
+ break;
+ case 2:
+ /* Round toward +infinite */
+ fesetround(FE_UPWARD);
+ break;
+ case 3:
+ /* Round toward -infinite */
+ fesetround(FE_DOWNWARD);
+ break;
}
- if ((mask & 80) != 0)
- fpscr_fx = (fp >> FPSCR_FX) & 0x01;
- fpscr_fex = (fp >> FPSCR_FEX) & 0x01;
- fpscr_vx = (fp >> FPSCR_VX) & 0x01;
- fpscr_ox = (fp >> FPSCR_OX) & 0x01;
- fpscr_ux = (fp >> FPSCR_UX) & 0x01;
- fpscr_zx = (fp >> FPSCR_ZX) & 0x01;
- fpscr_xx = (fp >> FPSCR_XX) & 0x01;
- fpscr_vsxnan = (fp >> FPSCR_VXSNAN) & 0x01;
- fpscr_vxisi = (fp >> FPSCR_VXISI) & 0x01;
- fpscr_vxidi = (fp >> FPSCR_VXIDI) & 0x01;
- fpscr_vxzdz = (fp >> FPSCR_VXZDZ) & 0x01;
- fpscr_vximz = (fp >> FPSCR_VXIMZ) & 0x01;
- fpscr_fr = (fp >> FPSCR_FR) & 0x01;
- fpscr_fi = (fp >> FPSCR_FI) & 0x01;
- fpscr_fprf = (fp >> FPSCR_FPRF) & 0x1F;
- fpscr_vxsoft = (fp >> FPSCR_VXSOFT) & 0x01;
- fpscr_vxsqrt = (fp >> FPSCR_VXSQRT) & 0x01;
- fpscr_oe = (fp >> FPSCR_OE) & 0x01;
- fpscr_ue = (fp >> FPSCR_UE) & 0x01;
- fpscr_ze = (fp >> FPSCR_ZE) & 0x01;
- fpscr_xe = (fp >> FPSCR_XE) & 0x01;
- fpscr_ni = (fp >> FPSCR_NI) & 0x01;
- fpscr_rn = (fp >> FPSCR_RN) & 0x03;
}
int32_t do_sraw(int32_t value, uint32_t shift)
@@ -220,20 +220,14 @@ void do_lsw (uint32_t reg, int count, uint32_t src)
int sh;
for (; count > 3; count -= 4, src += 4) {
- if (reg == 32)
- reg = 0;
ugpr(reg++) = ld32(src);
+ if (T2 == 32)
+ T2 = 0;
}
if (count > 0) {
- for (sh = 24, tmp = 0; count > 0; count--, src++, sh -= 8) {
- if (reg == 32)
- reg = 0;
- tmp |= ld8(src) << sh;
- if (sh == 0) {
- sh = 32;
- ugpr(reg++) = tmp;
tmp = 0;
- }
+ for (sh = 24; count > 0; count--, src++, sh -= 8) {
+ tmp |= ld8(src) << sh;
}
ugpr(reg) = tmp;
}
@@ -244,19 +238,30 @@ void do_stsw (uint32_t reg, int count, uint32_t dest)
int sh;
for (; count > 3; count -= 4, dest += 4) {
+ st32(dest, ugpr(reg++));
if (reg == 32)
reg = 0;
- st32(dest, ugpr(reg++));
}
if (count > 0) {
for (sh = 24; count > 0; count--, dest++, sh -= 8) {
- if (reg == 32)
- reg = 0;
st8(dest, (ugpr(reg) >> sh) & 0xFF);
- if (sh == 0) {
- sh = 32;
- reg++;
}
}
+}
+
+void do_dcbz (void)
+{
+ int i;
+
+ /* Assume cache line size is 32 */
+ for (i = 0; i < 8; i++) {
+ st32(T0, 0);
+ T0 += 4;
}
}
+
+/* Instruction cache invalidation helper */
+void do_icbi (void)
+{
+ tb_invalidate_page(T0);
+}