mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
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
This commit is contained in:
parent
1c7b3754f6
commit
76a66253e5
19 changed files with 7671 additions and 2596 deletions
|
@ -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);
|
||||
}
|
||||
RETURN();
|
||||
}
|
||||
|
||||
PPC_OP(glue(stmw, MEMSUFFIX))
|
||||
{
|
||||
int src = PARAM(1);
|
||||
|
||||
for (; src < 32; src++, T0 += 4) {
|
||||
glue(stl, MEMSUFFIX)(T0, ugpr(src));
|
||||
}
|
||||
glue(do_lmw, MEMSUFFIX)(PARAM1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
PPC_OP(glue(lmw_le, MEMSUFFIX))
|
||||
{
|
||||
int dst = PARAM(1);
|
||||
glue(do_lmw_le, MEMSUFFIX)(PARAM1);
|
||||
RETURN();
|
||||
}
|
||||
|
||||
for (; dst < 32; dst++, T0 += 4) {
|
||||
ugpr(dst) = glue(ld32r, MEMSUFFIX)(T0);
|
||||
}
|
||||
PPC_OP(glue(stmw, MEMSUFFIX))
|
||||
{
|
||||
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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue