aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/op.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/op.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/op.c')
-rw-r--r--target-ppc/op.c174
1 files changed, 127 insertions, 47 deletions
diff --git a/target-ppc/op.c b/target-ppc/op.c
index e5ba004734..cf77d5ee28 100644
--- a/target-ppc/op.c
+++ b/target-ppc/op.c
@@ -27,6 +27,12 @@
#define Ts2 (int32_t)T2
#define FT0 (env->ft0)
+#define FT1 (env->ft1)
+#define FT2 (env->ft2)
+
+#define FTS0 ((float)env->ft0)
+#define FTS1 ((float)env->ft1)
+#define FTS2 ((float)env->ft2)
#define PPC_OP(name) void op_##name(void)
@@ -173,6 +179,13 @@ PPC_OP(set_Rc0_1)
RETURN();
}
+/* Set Rc1 (for floating point arithmetic) */
+PPC_OP(set_Rc1)
+{
+ env->crf[1] = regs->fpscr[7];
+ RETURN();
+}
+
PPC_OP(set_T0)
{
T0 = PARAM(1);
@@ -278,6 +291,25 @@ PPC_OP(load_lr)
RETURN();
}
+/* FPSCR */
+PPC_OP(load_fpscr)
+{
+ do_load_fpscr();
+ RETURN();
+}
+
+PPC_OP(store_fpscr)
+{
+ do_store_fpscr(PARAM(1));
+ RETURN();
+}
+
+PPC_OP(reset_scrfx)
+{
+ regs->fpscr[7] &= ~0x8;
+ RETURN();
+}
+
/* Set reservation */
PPC_OP(set_reservation)
{
@@ -988,7 +1020,7 @@ PPC_OP(xori)
/* rotate left word immediate then mask insert */
PPC_OP(rlwimi)
{
- T0 = rotl(T0, PARAM(1) & PARAM(2)) | (T0 & PARAM(3));
+ T0 = (rotl(T0, PARAM(1)) & PARAM(2)) | (T1 & PARAM(3));
RETURN();
}
@@ -1216,123 +1248,171 @@ PPC_OP(store_spr)
regs->spr[PARAM(1)] = T0;
}
-/* FPSCR */
-PPC_OP(load_fpscr)
-{
- T0 = do_load_fpscr();
-}
-
-PPC_OP(store_fpscr)
-{
- do_store_fpscr(PARAM(1), T0);
-}
-
/*** Floating-point store ***/
-static inline uint32_t dtos(uint64_t f)
-{
- unsigned int e, m, s;
- e = (((f >> 52) & 0x7ff) - 1022) + 126;
- s = (f >> 63);
- m = (f >> 29);
- return (s << 31) | (e << 23) | m;
-}
-
-static inline uint64_t stod(uint32_t f)
-{
- unsigned int e, m, s;
- e = ((f >> 23) & 0xff) - 126 + 1022;
- s = f >> 31;
- m = f & ((1 << 23) - 1);
- return ((uint64_t)s << 63) | ((uint64_t)e << 52) | ((uint64_t)m << 29);
-}
-
PPC_OP(stfd_z_FT0)
{
- st64(SPARAM(1), FT0);
+ stfq((void *)SPARAM(1), FT0);
}
PPC_OP(stfd_FT0)
{
T0 += SPARAM(1);
- st64(T0, FT0);
+ stfq((void *)T0, FT0);
}
PPC_OP(stfdx_z_FT0)
{
- st64(T0, FT0);
+ stfq((void *)T0, FT0);
}
PPC_OP(stfdx_FT0)
{
T0 += T1;
- st64(T0, FT0);
+ stfq((void *)T0, FT0);
}
-
PPC_OP(stfs_z_FT0)
{
- st32(SPARAM(1), dtos(FT0));
+ float tmp = FT0;
+ stfl((void *)SPARAM(1), tmp);
}
PPC_OP(stfs_FT0)
{
+ float tmp = FT0;
T0 += SPARAM(1);
- st32(T0, dtos(FT0));
+ stfl((void *)T0, tmp);
}
PPC_OP(stfsx_z_FT0)
{
- st32(T0, dtos(FT0));
+ float tmp = FT0;
+ stfl((void *)T0, tmp);
}
PPC_OP(stfsx_FT0)
{
+ float tmp = FT0;
T0 += T1;
- st32(T0, dtos(FT0));
+ stfl((void *)T0, tmp);
}
/*** Floating-point load ***/
PPC_OP(lfd_z_FT0)
{
- FT0 = ld64(SPARAM(1));
+ FT0 = ldfq((void *)SPARAM(1));
}
PPC_OP(lfd_FT0)
{
T0 += SPARAM(1);
- FT0 = ld64(T0);
+ FT0 = ldfq((void *)T0);
}
PPC_OP(lfdx_z_FT0)
{
- FT0 = ld64(T0);
+ FT0 = ldfq((void *)T0);
}
PPC_OP(lfdx_FT0)
{
T0 += T1;
- FT0 = ld64(T0);
+ FT0 = ldfq((void *)T0);
}
PPC_OP(lfs_z_FT0)
{
- FT0 = stod(ld32(SPARAM(1)));
+ float tmp = ldfl((void *)SPARAM(1));
+ FT0 = tmp;
}
PPC_OP(lfs_FT0)
{
+ float tmp;
T0 += SPARAM(1);
- FT0 = stod(ld32(T0));
+ tmp = ldfl((void *)T0);
+ FT0 = tmp;
}
PPC_OP(lfsx_z_FT0)
{
- FT0 = stod(ld32(T0));
+ float tmp;
+ tmp = ldfl((void *)T0);
+ FT0 = tmp;
}
PPC_OP(lfsx_FT0)
{
+ float tmp;
+ T0 += T1;
+ tmp = ldfl((void *)T0);
+ FT0 = tmp;
+}
+
+PPC_OP(lwarx_z)
+{
+ T1 = ld32(T0);
+ regs->reserve = T0;
+ RETURN();
+}
+
+PPC_OP(lwarx)
+{
+ T0 += T1;
+ T1 = ld32(T0);
+ regs->reserve = T0;
+ RETURN();
+}
+
+PPC_OP(stwcx_z)
+{
+ if (regs->reserve != T0) {
+ env->crf[0] = xer_ov;
+ } else {
+ st32(T0, T1);
+ env->crf[0] = xer_ov | 0x02;
+ }
+ regs->reserve = 0;
+ RETURN();
+}
+
+PPC_OP(stwcx)
+{
T0 += T1;
- FT0 = stod(ld32(T0));
+ if (regs->reserve != (T0 & ~0x03)) {
+ env->crf[0] = xer_ov;
+ } else {
+ st32(T0, T2);
+ env->crf[0] = xer_ov | 0x02;
+ }
+ regs->reserve = 0;
+ RETURN();
+}
+
+PPC_OP(dcbz_z)
+{
+ do_dcbz();
+ RETURN();
+}
+
+PPC_OP(dcbz)
+{
+ T0 += T1;
+ do_dcbz();
+ RETURN();
+}
+
+/* Instruction cache block invalidate */
+PPC_OP(icbi_z)
+{
+ do_icbi();
+ RETURN();
+}
+
+PPC_OP(icbi)
+{
+ T0 += T1;
+ do_icbi();
+ RETURN();
}