aboutsummaryrefslogtreecommitdiffstats
path: root/target-ppc/op_mem.h
diff options
context:
space:
mode:
authorj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-03-07 08:32:30 +0000
committerj_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>2007-03-07 08:32:30 +0000
commit76a66253e5e48f1744f689041c1c21cedcaff630 (patch)
treec1003bd73ab8e2cbfe4a05c5b3f497bc2573fa4e /target-ppc/op_mem.h
parent1c7b3754f68382941a1921e578ead25d97d116fb (diff)
Great PowerPC emulation code resynchronisation and improvments:
- Add status file to make regression tracking easier - Move all micro-operations helpers definitions into a separate header: should never be seen outside of op.c - Update copyrights - Add new / missing PowerPC CPU definitions - Add definitions for PowerPC BookE - Add support for PowerPC 6xx/7xx software driven TLBs Allow use of PowerPC 603 as an example - Add preliminary code for POWER, POWER2, PowerPC 403, 405, 440, 601, 602 and BookE support - Avoid compiling priviledged only resources support for user-mode emulation - Remove unused helpers / micro-ops / dead code - Add instructions usage statistics dump: useful to figure which instructions need strong optimizations. - Micro-operation fixes: * add missing RETURN in some micro-ops * fix prototypes * use softfloat routines for all floating-point operations * fix tlbie instruction * move some huge micro-operations into helpers - emulation fixes: * fix inverted opcodes for fcmpo / fcmpu * condition register update is always to be done after the whole instruction has completed * add missing NIP updates when calling helpers that may generate an exception - optimizations and improvments: * optimize very often used instructions (li, mr, rlwixx...) * remove specific micro-ops for rarely used instructions * add routines for addresses computations to avoid bugs due to multiple different implementations * fix TB linking: do not reset T0 at the end of every TB. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2473 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/op_mem.h')
-rw-r--r--target-ppc/op_mem.h142
1 files changed, 94 insertions, 48 deletions
diff --git a/target-ppc/op_mem.h b/target-ppc/op_mem.h
index 9b3f721e5..a084b3194 100644
--- a/target-ppc/op_mem.h
+++ b/target-ppc/op_mem.h
@@ -1,6 +1,22 @@
-/* External helpers */
-void glue(do_lsw, MEMSUFFIX) (int dst);
-void glue(do_stsw, MEMSUFFIX) (int src);
+/*
+ * PowerPC emulation micro-operations for qemu.
+ *
+ * Copyright (c) 2003-2007 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
static inline uint16_t glue(ld16r, MEMSUFFIX) (target_ulong EA)
{
@@ -11,7 +27,7 @@ static inline uint16_t glue(ld16r, MEMSUFFIX) (target_ulong EA)
static inline int32_t glue(ld16rs, MEMSUFFIX) (target_ulong EA)
{
int16_t tmp = glue(lduw, MEMSUFFIX)(EA);
- return ((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
+ return (int16_t)((tmp & 0xFF00) >> 8) | ((tmp & 0x00FF) << 8);
}
static inline uint32_t glue(ld32r, MEMSUFFIX) (target_ulong EA)
@@ -80,41 +96,25 @@ PPC_ST_OP(wbr_le, stl);
/*** Integer load and store multiple ***/
PPC_OP(glue(lmw, MEMSUFFIX))
{
- int dst = PARAM(1);
-
- for (; dst < 32; dst++, T0 += 4) {
- ugpr(dst) = glue(ldl, MEMSUFFIX)(T0);
- }
+ glue(do_lmw, MEMSUFFIX)(PARAM1);
RETURN();
}
-PPC_OP(glue(stmw, MEMSUFFIX))
+PPC_OP(glue(lmw_le, MEMSUFFIX))
{
- int src = PARAM(1);
-
- for (; src < 32; src++, T0 += 4) {
- glue(stl, MEMSUFFIX)(T0, ugpr(src));
- }
+ glue(do_lmw_le, MEMSUFFIX)(PARAM1);
RETURN();
}
-PPC_OP(glue(lmw_le, MEMSUFFIX))
+PPC_OP(glue(stmw, MEMSUFFIX))
{
- int dst = PARAM(1);
-
- for (; dst < 32; dst++, T0 += 4) {
- ugpr(dst) = glue(ld32r, MEMSUFFIX)(T0);
- }
+ glue(do_stmw, MEMSUFFIX)(PARAM1);
RETURN();
}
PPC_OP(glue(stmw_le, MEMSUFFIX))
{
- int src = PARAM(1);
-
- for (; src < 32; src++, T0 += 4) {
- glue(st32r, MEMSUFFIX)(T0, ugpr(src));
- }
+ glue(do_stmw_le, MEMSUFFIX)(PARAM1);
RETURN();
}
@@ -125,7 +125,6 @@ PPC_OP(glue(lswi, MEMSUFFIX))
RETURN();
}
-void glue(do_lsw_le, MEMSUFFIX) (int dst);
PPC_OP(glue(lswi_le, MEMSUFFIX))
{
glue(do_lsw_le, MEMSUFFIX)(PARAM(1));
@@ -139,9 +138,9 @@ PPC_OP(glue(lswi_le, MEMSUFFIX))
*/
PPC_OP(glue(lswx, MEMSUFFIX))
{
- if (T1 > 0) {
- if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
- (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
+ if (unlikely(T1 > 0)) {
+ if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
+ (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
} else {
glue(do_lsw, MEMSUFFIX)(PARAM(1));
@@ -152,9 +151,9 @@ PPC_OP(glue(lswx, MEMSUFFIX))
PPC_OP(glue(lswx_le, MEMSUFFIX))
{
- if (T1 > 0) {
- if ((PARAM(1) < PARAM(2) && (PARAM(1) + T1) > PARAM(2)) ||
- (PARAM(1) < PARAM(3) && (PARAM(1) + T1) > PARAM(3))) {
+ if (unlikely(T1 > 0)) {
+ if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) ||
+ (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) {
do_raise_exception_err(EXCP_PROGRAM, EXCP_INVAL | EXCP_INVAL_LSWX);
} else {
glue(do_lsw_le, MEMSUFFIX)(PARAM(1));
@@ -169,7 +168,6 @@ PPC_OP(glue(stsw, MEMSUFFIX))
RETURN();
}
-void glue(do_stsw_le, MEMSUFFIX) (int src);
PPC_OP(glue(stsw_le, MEMSUFFIX))
{
glue(do_stsw_le, MEMSUFFIX)(PARAM(1));
@@ -180,7 +178,7 @@ PPC_OP(glue(stsw_le, MEMSUFFIX))
#define PPC_STF_OP(name, op) \
PPC_OP(glue(glue(st, name), MEMSUFFIX)) \
{ \
- glue(op, MEMSUFFIX)(T0, FT1); \
+ glue(op, MEMSUFFIX)(T0, FT0); \
RETURN(); \
}
@@ -228,7 +226,7 @@ PPC_STF_OP(fs_le, stflr);
#define PPC_LDF_OP(name, op) \
PPC_OP(glue(glue(l, name), MEMSUFFIX)) \
{ \
- FT1 = glue(op, MEMSUFFIX)(T0); \
+ FT0 = glue(op, MEMSUFFIX)(T0); \
RETURN(); \
}
@@ -277,22 +275,22 @@ PPC_LDF_OP(fs_le, ldflr);
/* Load and set reservation */
PPC_OP(glue(lwarx, MEMSUFFIX))
{
- if (T0 & 0x03) {
+ if (unlikely(T0 & 0x03)) {
do_raise_exception(EXCP_ALIGN);
} else {
- T1 = glue(ldl, MEMSUFFIX)(T0);
- regs->reserve = T0;
+ T1 = glue(ldl, MEMSUFFIX)(T0);
+ regs->reserve = T0;
}
RETURN();
}
PPC_OP(glue(lwarx_le, MEMSUFFIX))
{
- if (T0 & 0x03) {
+ if (unlikely(T0 & 0x03)) {
do_raise_exception(EXCP_ALIGN);
} else {
- T1 = glue(ld32r, MEMSUFFIX)(T0);
- regs->reserve = T0;
+ T1 = glue(ld32r, MEMSUFFIX)(T0);
+ regs->reserve = T0;
}
RETURN();
}
@@ -300,33 +298,33 @@ PPC_OP(glue(lwarx_le, MEMSUFFIX))
/* Store with reservation */
PPC_OP(glue(stwcx, MEMSUFFIX))
{
- if (T0 & 0x03) {
+ if (unlikely(T0 & 0x03)) {
do_raise_exception(EXCP_ALIGN);
} else {
- if (regs->reserve != T0) {
+ if (unlikely(regs->reserve != T0)) {
env->crf[0] = xer_ov;
} else {
glue(stl, MEMSUFFIX)(T0, T1);
env->crf[0] = xer_ov | 0x02;
}
}
- regs->reserve = 0;
+ regs->reserve = -1;
RETURN();
}
PPC_OP(glue(stwcx_le, MEMSUFFIX))
{
- if (T0 & 0x03) {
+ if (unlikely(T0 & 0x03)) {
do_raise_exception(EXCP_ALIGN);
} else {
- if (regs->reserve != T0) {
+ if (unlikely(regs->reserve != T0)) {
env->crf[0] = xer_ov;
} else {
glue(st32r, MEMSUFFIX)(T0, T1);
env->crf[0] = xer_ov | 0x02;
}
}
- regs->reserve = 0;
+ regs->reserve = -1;
RETURN();
}
@@ -340,6 +338,17 @@ PPC_OP(glue(dcbz, MEMSUFFIX))
glue(stl, MEMSUFFIX)(T0 + 0x14, 0);
glue(stl, MEMSUFFIX)(T0 + 0x18, 0);
glue(stl, MEMSUFFIX)(T0 + 0x1C, 0);
+#if DCACHE_LINE_SIZE == 64
+ /* XXX: cache line size should be 64 for POWER & PowerPC 601 */
+ glue(stl, MEMSUFFIX)(T0 + 0x20UL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x24UL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x28UL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x2CUL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x30UL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x34UL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x38UL, 0);
+ glue(stl, MEMSUFFIX)(T0 + 0x3CUL, 0);
+#endif
RETURN();
}
@@ -368,4 +377,41 @@ PPC_OP(glue(ecowx_le, MEMSUFFIX))
RETURN();
}
+/* XXX: those micro-ops need tests ! */
+/* PowerPC 601 specific instructions (POWER bridge) */
+void OPPROTO glue(op_POWER_lscbx, MEMSUFFIX) (void)
+{
+ /* When byte count is 0, do nothing */
+ if (likely(T1 > 0)) {
+ glue(do_POWER_lscbx, MEMSUFFIX)(PARAM1, PARAM2, PARAM3);
+ }
+ RETURN();
+}
+
+/* POWER2 quad load and store */
+/* XXX: TAGs are not managed */
+void OPPROTO glue(op_POWER2_lfq, MEMSUFFIX) (void)
+{
+ glue(do_POWER2_lfq, MEMSUFFIX)();
+ RETURN();
+}
+
+void glue(op_POWER2_lfq_le, MEMSUFFIX) (void)
+{
+ glue(do_POWER2_lfq_le, MEMSUFFIX)();
+ RETURN();
+}
+
+void OPPROTO glue(op_POWER2_stfq, MEMSUFFIX) (void)
+{
+ glue(do_POWER2_stfq, MEMSUFFIX)();
+ RETURN();
+}
+
+void OPPROTO glue(op_POWER2_stfq_le, MEMSUFFIX) (void)
+{
+ glue(do_POWER2_stfq_le, MEMSUFFIX)();
+ RETURN();
+}
+
#undef MEMSUFFIX