diff options
author | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-07 08:32:30 +0000 |
---|---|---|
committer | j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-03-07 08:32:30 +0000 |
commit | 76a66253e5e48f1744f689041c1c21cedcaff630 (patch) | |
tree | c1003bd73ab8e2cbfe4a05c5b3f497bc2573fa4e /target-ppc/op_mem.h | |
parent | 1c7b3754f68382941a1921e578ead25d97d116fb (diff) | |
download | qemu-76a66253e5e48f1744f689041c1c21cedcaff630.tar.gz qemu-76a66253e5e48f1744f689041c1c21cedcaff630.tar.bz2 qemu-76a66253e5e48f1744f689041c1c21cedcaff630.zip |
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.h | 142 |
1 files changed, 94 insertions, 48 deletions
diff --git a/target-ppc/op_mem.h b/target-ppc/op_mem.h index 9b3f721e5f..a084b31943 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 |