提交 45d827d2 编写于 作者: A aurel32

target-ppc: convert SPR accesses to TCG

Signed-off-by: NAurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5910 c046a42c-6fe2-441c-8c8c-71466251a162
上级 fa0d32c4
......@@ -1605,39 +1605,31 @@ case "$target_cpu" in
;;
ppc)
echo "TARGET_ARCH=ppc" >> $config_mak
echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
;;
ppcemb)
echo "TARGET_ARCH=ppcemb" >> $config_mak
echo "TARGET_ABI_DIR=ppc" >> $config_mak
echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPCEMB 1" >> $config_h
echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
;;
ppc64)
echo "TARGET_ARCH=ppc64" >> $config_mak
echo "TARGET_ABI_DIR=ppc" >> $config_mak
echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPC64 1" >> $config_h
echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
;;
ppc64abi32)
echo "TARGET_ARCH=ppc64" >> $config_mak
echo "TARGET_ABI_DIR=ppc" >> $config_mak
echo "TARGET_ARCH2=ppc64abi32" >> $config_mak
echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPC64 1" >> $config_h
echo "#define TARGET_ABI32 1" >> $config_h
echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
;;
sh4|sh4eb)
echo "TARGET_ARCH=sh4" >> $config_mak
......
......@@ -295,13 +295,13 @@ typedef union ppc_tlb_t ppc_tlb_t;
/* SPR access micro-ops generations callbacks */
struct ppc_spr_t {
void (*uea_read)(void *opaque, int spr_num);
void (*uea_write)(void *opaque, int spr_num);
void (*uea_read)(void *opaque, int gpr_num, int spr_num);
void (*uea_write)(void *opaque, int spr_num, int gpr_num);
#if !defined(CONFIG_USER_ONLY)
void (*oea_read)(void *opaque, int spr_num);
void (*oea_write)(void *opaque, int spr_num);
void (*hea_read)(void *opaque, int spr_num);
void (*hea_write)(void *opaque, int spr_num);
void (*oea_read)(void *opaque, int gpr_num, int spr_num);
void (*oea_write)(void *opaque, int spr_num, int gpr_num);
void (*hea_read)(void *opaque, int gpr_num, int spr_num);
void (*hea_write)(void *opaque, int spr_num, int gpr_num);
#endif
const char *name;
};
......@@ -529,10 +529,6 @@ struct CPUPPCState {
/* First are the most commonly used resources
* during translated code execution
*/
#if TARGET_LONG_BITS > HOST_LONG_BITS
target_ulong t0;
#endif
/* general purpose registers */
target_ulong gpr[32];
#if !defined(TARGET_PPC64)
......@@ -689,28 +685,19 @@ void ppc_hw_interrupt (CPUPPCState *env);
void dump_stack (CPUPPCState *env);
#if !defined(CONFIG_USER_ONLY)
target_ulong do_load_ibatu (CPUPPCState *env, int nr);
target_ulong do_load_ibatl (CPUPPCState *env, int nr);
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value);
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value);
target_ulong do_load_dbatu (CPUPPCState *env, int nr);
target_ulong do_load_dbatl (CPUPPCState *env, int nr);
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value);
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value);
target_ulong do_load_sdr1 (CPUPPCState *env);
void do_store_sdr1 (CPUPPCState *env, target_ulong value);
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value);
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value);
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value);
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value);
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value);
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value);
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value);
#if defined(TARGET_PPC64)
target_ulong ppc_load_asr (CPUPPCState *env);
void ppc_store_asr (CPUPPCState *env, target_ulong value);
target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr);
void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs);
#endif /* defined(TARGET_PPC64) */
#if 0 // Unused
target_ulong do_load_sr (CPUPPCState *env, int srnum);
#endif
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value);
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value);
#endif /* !defined(CONFIG_USER_ONLY) */
void ppc_store_msr (CPUPPCState *env, target_ulong value);
......
......@@ -32,20 +32,7 @@
#define USE_PRECISE_EMULATION 0
register struct CPUPPCState *env asm(AREG0);
#if TARGET_LONG_BITS > HOST_LONG_BITS
/* no registers can be used */
#define T0 (env->t0)
#define TDX "%016" PRIx64
#else
register target_ulong T0 asm(AREG1);
#define TDX "%016lx"
#endif
#if defined (DEBUG_OP)
# define RETURN() __asm__ __volatile__("nop" : : : "memory");
#else
# define RETURN() __asm__ __volatile__("" : : : "memory");
#endif
#if !defined(CONFIG_USER_ONLY)
#include "softmmu_exec.h"
......
......@@ -1800,17 +1800,7 @@ static always_inline void dump_store_bat (CPUPPCState *env, char ID,
#endif
}
target_ulong do_load_ibatu (CPUPPCState *env, int nr)
{
return env->IBAT[0][nr];
}
target_ulong do_load_ibatl (CPUPPCState *env, int nr)
{
return env->IBAT[1][nr];
}
void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
void ppc_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
{
target_ulong mask;
......@@ -1836,23 +1826,13 @@ void do_store_ibatu (CPUPPCState *env, int nr, target_ulong value)
}
}
void do_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
void ppc_store_ibatl (CPUPPCState *env, int nr, target_ulong value)
{
dump_store_bat(env, 'I', 1, nr, value);
env->IBAT[1][nr] = value;
}
target_ulong do_load_dbatu (CPUPPCState *env, int nr)
{
return env->DBAT[0][nr];
}
target_ulong do_load_dbatl (CPUPPCState *env, int nr)
{
return env->DBAT[1][nr];
}
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
void ppc_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
{
target_ulong mask;
......@@ -1878,13 +1858,13 @@ void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value)
}
}
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
void ppc_store_dbatl (CPUPPCState *env, int nr, target_ulong value)
{
dump_store_bat(env, 'D', 1, nr, value);
env->DBAT[1][nr] = value;
}
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
void ppc_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
{
target_ulong mask;
int do_inval;
......@@ -1921,7 +1901,7 @@ void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value)
}
}
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
void ppc_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value)
{
target_ulong mask;
int do_inval;
......@@ -2075,11 +2055,6 @@ void ppc_tlb_invalidate_one (CPUPPCState *env, target_ulong addr)
/*****************************************************************************/
/* Special registers manipulation */
#if defined(TARGET_PPC64)
target_ulong ppc_load_asr (CPUPPCState *env)
{
return env->asr;
}
void ppc_store_asr (CPUPPCState *env, target_ulong value)
{
if (env->asr != value) {
......@@ -2089,12 +2064,7 @@ void ppc_store_asr (CPUPPCState *env, target_ulong value)
}
#endif
target_ulong do_load_sdr1 (CPUPPCState *env)
{
return env->sdr1;
}
void do_store_sdr1 (CPUPPCState *env, target_ulong value)
void ppc_store_sdr1 (CPUPPCState *env, target_ulong value)
{
#if defined (DEBUG_MMU)
if (loglevel != 0) {
......@@ -2110,7 +2080,7 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value)
}
}
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value)
void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value)
{
#if defined (DEBUG_MMU)
if (loglevel != 0) {
......
......@@ -184,7 +184,7 @@ DEF_HELPER_0(slbia, void)
DEF_HELPER_1(slbie, void, tl)
#endif
DEF_HELPER_1(load_sr, tl, tl);
DEF_HELPER_2(store_sr, void, tl, tl);
DEF_HELPER_2(store_sr, void, tl, tl)
DEF_HELPER_1(602_mfrom, tl, tl)
#endif
......@@ -200,6 +200,43 @@ DEF_HELPER_2(divs, tl, tl, tl)
DEF_HELPER_2(divso, tl, tl, tl)
DEF_HELPER_1(load_dcr, tl, tl);
DEF_HELPER_2(store_dcr, void, tl, tl);
DEF_HELPER_2(store_dcr, void, tl, tl)
DEF_HELPER_1(load_dump_spr, void, i32)
DEF_HELPER_1(store_dump_spr, void, i32)
DEF_HELPER_0(load_tbl, tl)
DEF_HELPER_0(load_tbu, tl)
DEF_HELPER_0(load_atbl, tl)
DEF_HELPER_0(load_atbu, tl)
DEF_HELPER_0(load_601_rtcl, tl)
DEF_HELPER_0(load_601_rtcu, tl)
#if !defined(CONFIG_USER_ONLY)
#if defined(TARGET_PPC64)
DEF_HELPER_1(store_asr, void, tl)
#endif
DEF_HELPER_1(store_sdr1, void, tl)
DEF_HELPER_1(store_tbl, void, tl)
DEF_HELPER_1(store_tbu, void, tl)
DEF_HELPER_1(store_atbl, void, tl)
DEF_HELPER_1(store_atbu, void, tl)
DEF_HELPER_1(store_601_rtcl, void, tl)
DEF_HELPER_1(store_601_rtcu, void, tl)
DEF_HELPER_0(load_decr, tl)
DEF_HELPER_1(store_decr, void, tl)
DEF_HELPER_1(store_hid0_601, void, tl)
DEF_HELPER_2(store_403_pbr, void, i32, tl)
DEF_HELPER_0(load_40x_pit, tl)
DEF_HELPER_1(store_40x_pit, void, tl)
DEF_HELPER_1(store_40x_dbcr0, void, tl)
DEF_HELPER_1(store_40x_sler, void, tl)
DEF_HELPER_1(store_booke_tcr, void, tl)
DEF_HELPER_1(store_booke_tsr, void, tl)
DEF_HELPER_2(store_ibatl, void, i32, tl)
DEF_HELPER_2(store_ibatu, void, i32, tl)
DEF_HELPER_2(store_dbatl, void, i32, tl)
DEF_HELPER_2(store_dbatu, void, i32, tl)
DEF_HELPER_2(store_601_batl, void, i32, tl)
DEF_HELPER_2(store_601_batu, void, i32, tl)
#endif
#include "def-helper.h"
/*
* 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
*/
//#define DEBUG_OP
#include "config.h"
#include "exec.h"
#include "host-utils.h"
#include "helper_regs.h"
#include "op_helper.h"
#if !defined(CONFIG_USER_ONLY)
void OPPROTO op_load_sdr1 (void)
{
T0 = env->sdr1;
RETURN();
}
void OPPROTO op_store_sdr1 (void)
{
do_store_sdr1(env, T0);
RETURN();
}
#if defined (TARGET_PPC64)
void OPPROTO op_load_asr (void)
{
T0 = env->asr;
RETURN();
}
void OPPROTO op_store_asr (void)
{
ppc_store_asr(env, T0);
RETURN();
}
#endif
#endif
/* SPR */
void OPPROTO op_load_spr (void)
{
T0 = env->spr[PARAM1];
RETURN();
}
void OPPROTO op_store_spr (void)
{
env->spr[PARAM1] = T0;
RETURN();
}
void OPPROTO op_load_dump_spr (void)
{
T0 = ppc_load_dump_spr(PARAM1);
RETURN();
}
void OPPROTO op_store_dump_spr (void)
{
ppc_store_dump_spr(PARAM1, T0);
RETURN();
}
void OPPROTO op_mask_spr (void)
{
env->spr[PARAM1] &= ~T0;
RETURN();
}
void OPPROTO op_load_tbl (void)
{
T0 = cpu_ppc_load_tbl(env);
RETURN();
}
void OPPROTO op_load_tbu (void)
{
T0 = cpu_ppc_load_tbu(env);
RETURN();
}
void OPPROTO op_load_atbl (void)
{
T0 = cpu_ppc_load_atbl(env);
RETURN();
}
void OPPROTO op_load_atbu (void)
{
T0 = cpu_ppc_load_atbu(env);
RETURN();
}
#if !defined(CONFIG_USER_ONLY)
void OPPROTO op_store_tbl (void)
{
cpu_ppc_store_tbl(env, T0);
RETURN();
}
void OPPROTO op_store_tbu (void)
{
cpu_ppc_store_tbu(env, T0);
RETURN();
}
void OPPROTO op_store_atbl (void)
{
cpu_ppc_store_atbl(env, T0);
RETURN();
}
void OPPROTO op_store_atbu (void)
{
cpu_ppc_store_atbu(env, T0);
RETURN();
}
void OPPROTO op_load_decr (void)
{
T0 = cpu_ppc_load_decr(env);
RETURN();
}
void OPPROTO op_store_decr (void)
{
cpu_ppc_store_decr(env, T0);
RETURN();
}
void OPPROTO op_load_ibat (void)
{
T0 = env->IBAT[PARAM1][PARAM2];
RETURN();
}
void OPPROTO op_store_ibatu (void)
{
do_store_ibatu(env, PARAM1, T0);
RETURN();
}
void OPPROTO op_store_ibatl (void)
{
#if 1
env->IBAT[1][PARAM1] = T0;
#else
do_store_ibatl(env, PARAM1, T0);
#endif
RETURN();
}
void OPPROTO op_load_dbat (void)
{
T0 = env->DBAT[PARAM1][PARAM2];
RETURN();
}
void OPPROTO op_store_dbatu (void)
{
do_store_dbatu(env, PARAM1, T0);
RETURN();
}
void OPPROTO op_store_dbatl (void)
{
#if 1
env->DBAT[1][PARAM1] = T0;
#else
do_store_dbatl(env, PARAM1, T0);
#endif
RETURN();
}
#endif /* !defined(CONFIG_USER_ONLY) */
/* Return from interrupt */
#if !defined(CONFIG_USER_ONLY)
/* Exception vectors */
void OPPROTO op_store_excp_prefix (void)
{
T0 &= env->ivpr_mask;
env->excp_prefix = T0;
RETURN();
}
void OPPROTO op_store_excp_vector (void)
{
T0 &= env->ivor_mask;
env->excp_vectors[PARAM1] = T0;
RETURN();
}
#endif
/* 601 specific */
void OPPROTO op_load_601_rtcl (void)
{
T0 = cpu_ppc601_load_rtcl(env);
RETURN();
}
void OPPROTO op_load_601_rtcu (void)
{
T0 = cpu_ppc601_load_rtcu(env);
RETURN();
}
#if !defined(CONFIG_USER_ONLY)
void OPPROTO op_store_601_rtcl (void)
{
cpu_ppc601_store_rtcl(env, T0);
RETURN();
}
void OPPROTO op_store_601_rtcu (void)
{
cpu_ppc601_store_rtcu(env, T0);
RETURN();
}
void OPPROTO op_store_hid0_601 (void)
{
do_store_hid0_601();
RETURN();
}
void OPPROTO op_load_601_bat (void)
{
T0 = env->IBAT[PARAM1][PARAM2];
RETURN();
}
void OPPROTO op_store_601_batl (void)
{
do_store_ibatl_601(env, PARAM1, T0);
RETURN();
}
void OPPROTO op_store_601_batu (void)
{
do_store_ibatu_601(env, PARAM1, T0);
RETURN();
}
#endif /* !defined(CONFIG_USER_ONLY) */
/* SPR micro-ops */
/* 440 specific */
#if !defined(CONFIG_USER_ONLY)
void OPPROTO op_store_pir (void)
{
env->spr[SPR_PIR] = T0 & 0x0000000FUL;
RETURN();
}
void OPPROTO op_load_403_pb (void)
{
do_load_403_pb(PARAM1);
RETURN();
}
void OPPROTO op_store_403_pb (void)
{
do_store_403_pb(PARAM1);
RETURN();
}
void OPPROTO op_load_40x_pit (void)
{
T0 = load_40x_pit(env);
RETURN();
}
void OPPROTO op_store_40x_pit (void)
{
store_40x_pit(env, T0);
RETURN();
}
void OPPROTO op_store_40x_dbcr0 (void)
{
store_40x_dbcr0(env, T0);
RETURN();
}
void OPPROTO op_store_40x_sler (void)
{
store_40x_sler(env, T0);
RETURN();
}
void OPPROTO op_store_booke_tcr (void)
{
store_booke_tcr(env, T0);
RETURN();
}
void OPPROTO op_store_booke_tsr (void)
{
store_booke_tsr(env, T0);
RETURN();
}
#endif /* !defined(CONFIG_USER_ONLY) */
......@@ -22,7 +22,6 @@
#include "helper.h"
#include "helper_regs.h"
#include "op_helper.h"
//#define DEBUG_OP
//#define DEBUG_EXCEPTIONS
......@@ -65,25 +64,196 @@ void helper_store_cr (target_ulong val, uint32_t mask)
}
}
target_ulong ppc_load_dump_spr (int sprn)
/*****************************************************************************/
/* SPR accesses */
void helper_load_dump_spr (uint32_t sprn)
{
if (loglevel != 0) {
fprintf(logfile, "Read SPR %d %03x => " ADDRX "\n",
sprn, sprn, env->spr[sprn]);
}
return env->spr[sprn];
}
void ppc_store_dump_spr (int sprn, target_ulong val)
void helper_store_dump_spr (uint32_t sprn)
{
if (loglevel != 0) {
fprintf(logfile, "Write SPR %d %03x => " ADDRX " <= " ADDRX "\n",
sprn, sprn, env->spr[sprn], val);
fprintf(logfile, "Write SPR %d %03x <= " ADDRX "\n",
sprn, sprn, env->spr[sprn]);
}
}
target_ulong helper_load_tbl (void)
{
return cpu_ppc_load_tbl(env);
}
target_ulong helper_load_tbu (void)
{
return cpu_ppc_load_tbu(env);
}
target_ulong helper_load_atbl (void)
{
return cpu_ppc_load_atbl(env);
}
target_ulong helper_load_atbu (void)
{
return cpu_ppc_load_atbu(env);
}
target_ulong helper_load_601_rtcl (void)
{
return cpu_ppc601_load_rtcl(env);
}
target_ulong helper_load_601_rtcu (void)
{
return cpu_ppc601_load_rtcu(env);
}
#if !defined(CONFIG_USER_ONLY)
#if defined (TARGET_PPC64)
void helper_store_asr (target_ulong val)
{
ppc_store_asr(env, val);
}
#endif
void helper_store_sdr1 (target_ulong val)
{
ppc_store_sdr1(env, val);
}
void helper_store_tbl (target_ulong val)
{
cpu_ppc_store_tbl(env, val);
}
void helper_store_tbu (target_ulong val)
{
cpu_ppc_store_tbu(env, val);
}
void helper_store_atbl (target_ulong val)
{
cpu_ppc_store_atbl(env, val);
}
void helper_store_atbu (target_ulong val)
{
cpu_ppc_store_atbu(env, val);
}
void helper_store_601_rtcl (target_ulong val)
{
cpu_ppc601_store_rtcl(env, val);
}
void helper_store_601_rtcu (target_ulong val)
{
cpu_ppc601_store_rtcu(env, val);
}
target_ulong helper_load_decr (void)
{
return cpu_ppc_load_decr(env);
}
void helper_store_decr (target_ulong val)
{
cpu_ppc_store_decr(env, val);
}
void helper_store_hid0_601 (target_ulong val)
{
target_ulong hid0;
hid0 = env->spr[SPR_HID0];
if ((val ^ hid0) & 0x00000008) {
/* Change current endianness */
env->hflags &= ~(1 << MSR_LE);
env->hflags_nmsr &= ~(1 << MSR_LE);
env->hflags_nmsr |= (1 << MSR_LE) & (((val >> 3) & 1) << MSR_LE);
env->hflags |= env->hflags_nmsr;
if (loglevel != 0) {
fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
__func__, val & 0x8 ? 'l' : 'b', env->hflags);
}
}
env->spr[sprn] = val;
env->spr[SPR_HID0] = (uint32_t)val;
}
void helper_store_403_pbr (uint32_t num, target_ulong value)
{
if (likely(env->pb[num] != value)) {
env->pb[num] = value;
/* Should be optimized */
tlb_flush(env, 1);
}
}
target_ulong helper_load_40x_pit (void)
{
return load_40x_pit(env);
}
void helper_store_40x_pit (target_ulong val)
{
store_40x_pit(env, val);
}
void helper_store_40x_dbcr0 (target_ulong val)
{
store_40x_dbcr0(env, val);
}
void helper_store_40x_sler (target_ulong val)
{
store_40x_sler(env, val);
}
void helper_store_booke_tcr (target_ulong val)
{
store_booke_tcr(env, val);
}
void helper_store_booke_tsr (target_ulong val)
{
store_booke_tsr(env, val);
}
void helper_store_ibatu (uint32_t nr, target_ulong val)
{
ppc_store_ibatu(env, nr, val);
}
void helper_store_ibatl (uint32_t nr, target_ulong val)
{
ppc_store_ibatl(env, nr, val);
}
void helper_store_dbatu (uint32_t nr, target_ulong val)
{
ppc_store_dbatu(env, nr, val);
}
void helper_store_dbatl (uint32_t nr, target_ulong val)
{
ppc_store_dbatl(env, nr, val);
}
void helper_store_601_batl (uint32_t nr, target_ulong val)
{
ppc_store_ibatl_601(env, nr, val);
}
void helper_store_601_batu (uint32_t nr, target_ulong val)
{
ppc_store_ibatu_601(env, nr, val);
}
#endif
/*****************************************************************************/
/* Memory load and stores */
......@@ -1678,25 +1848,6 @@ void helper_rfsvc (void)
{
do_rfi(env->lr, env->ctr, 0x0000FFFF, 0);
}
void do_store_hid0_601 (void)
{
uint32_t hid0;
hid0 = env->spr[SPR_HID0];
if ((T0 ^ hid0) & 0x00000008) {
/* Change current endianness */
env->hflags &= ~(1 << MSR_LE);
env->hflags_nmsr &= ~(1 << MSR_LE);
env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE);
env->hflags |= env->hflags_nmsr;
if (loglevel != 0) {
fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n",
__func__, T0 & 0x8 ? 'l' : 'b', env->hflags);
}
}
env->spr[SPR_HID0] = T0;
}
#endif
/*****************************************************************************/
......@@ -1709,7 +1860,7 @@ target_ulong helper_602_mfrom (target_ulong arg)
if (likely(arg < 602)) {
#if defined(USE_MFROM_ROM_TABLE)
#include "mfrom_table.c"
return mfrom_ROM_table[T0];
return mfrom_ROM_table[arg];
#else
double d;
/* Extremly decomposed:
......@@ -1747,7 +1898,7 @@ target_ulong helper_load_dcr (target_ulong dcrn)
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_read(env->dcr_env, dcrn, &val) != 0)) {
if (loglevel != 0) {
fprintf(logfile, "DCR read error %d %03x\n", (int)T0, (int)T0);
fprintf(logfile, "DCR read error %d %03x\n", (int)dcrn, (int)dcrn);
}
raise_exception_err(env, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
......@@ -1765,7 +1916,7 @@ void helper_store_dcr (target_ulong dcrn, target_ulong val)
POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
} else if (unlikely(ppc_dcr_write(env->dcr_env, dcrn, val) != 0)) {
if (loglevel != 0) {
fprintf(logfile, "DCR write error %d %03x\n", (int)T0, (int)T0);
fprintf(logfile, "DCR write error %d %03x\n", (int)dcrn, (int)dcrn);
}
raise_exception_err(env, POWERPC_EXCP_PROGRAM,
POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG);
......@@ -1796,20 +1947,6 @@ void helper_rfmci (void)
do_rfi(env->spr[SPR_BOOKE_MCSRR0], SPR_BOOKE_MCSRR1,
~((target_ulong)0x3FFF0000), 0);
}
void do_load_403_pb (int num)
{
T0 = env->pb[num];
}
void do_store_403_pb (int num)
{
if (likely(env->pb[num] != T0)) {
env->pb[num] = T0;
/* Should be optimized */
tlb_flush(env, 1);
}
}
#endif
/* 440 specific */
......@@ -2539,7 +2676,7 @@ target_ulong helper_load_sr (target_ulong sr_num)
void helper_store_sr (target_ulong sr_num, target_ulong val)
{
do_store_sr(env, sr_num, val);
ppc_store_sr(env, sr_num, val);
}
/* SLB management */
......
/*
* PowerPC emulation helpers header 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
*/
/* Registers load and stores */
#if defined(TARGET_PPC64)
void do_store_pri (int prio);
#endif
target_ulong ppc_load_dump_spr (int sprn);
void ppc_store_dump_spr (int sprn, target_ulong val);
/* Misc */
/* POWER / PowerPC 601 specific helpers */
#if !defined(CONFIG_USER_ONLY)
void do_store_hid0_601 (void);
#endif
/* PowerPC 403 specific helpers */
#if !defined(CONFIG_USER_ONLY)
void do_load_403_pb (int num);
void do_store_403_pb (int num);
#endif
......@@ -38,7 +38,7 @@
#define GDBSTUB_SINGLE_STEP 0x4
/* Include definitions for instructions classes and implementations flags */
//#define DO_SINGLE_STEP
#define DO_SINGLE_STEP
//#define PPC_DEBUG_DISAS
//#define DO_PPC_STATISTICS
//#define OPTIMIZE_FPRF_UPDATE
......@@ -71,9 +71,6 @@ static TCGv cpu_reserve;
static TCGv_i32 cpu_fpscr;
static TCGv_i32 cpu_access_type;
/* dyngen register indexes */
static TCGv cpu_T[1];
#include "gen-icount.h"
void ppc_translate_init(void)
......@@ -86,11 +83,6 @@ void ppc_translate_init(void)
return;
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
#if TARGET_LONG_BITS > HOST_LONG_BITS
cpu_T[0] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t0), "T0");
#else
cpu_T[0] = tcg_global_reg_new(TCG_AREG1, "T0");
#endif
p = cpu_reg_names;
......@@ -3886,7 +3878,7 @@ static void spr_noaccess (void *opaque, int sprn)
/* mfspr */
static always_inline void gen_op_mfspr (DisasContext *ctx)
{
void (*read_cb)(void *opaque, int sprn);
void (*read_cb)(void *opaque, int gprn, int sprn);
uint32_t sprn = SPR(ctx->opcode);
#if !defined(CONFIG_USER_ONLY)
......@@ -3899,8 +3891,7 @@ static always_inline void gen_op_mfspr (DisasContext *ctx)
read_cb = ctx->spr_cb[sprn].uea_read;
if (likely(read_cb != NULL)) {
if (likely(read_cb != SPR_NOACCESS)) {
(*read_cb)(ctx, sprn);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
(*read_cb)(ctx, rD(ctx->opcode), sprn);
} else {
/* Privilege exception */
/* This is a hack to avoid warnings when running Linux:
......@@ -3972,7 +3963,6 @@ GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
GEN_EXCP_PRIVREG(ctx);
return;
}
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
if (ctx->opcode & 0x00010000) {
/* Special form that does not need any synchronisation */
TCGv t0 = tcg_temp_new();
......@@ -4004,7 +3994,6 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
GEN_EXCP_PRIVREG(ctx);
return;
}
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
if (ctx->opcode & 0x00010000) {
/* Special form that does not need any synchronisation */
TCGv t0 = tcg_temp_new();
......@@ -4041,7 +4030,7 @@ GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
/* mtspr */
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
{
void (*write_cb)(void *opaque, int sprn);
void (*write_cb)(void *opaque, int sprn, int gprn);
uint32_t sprn = SPR(ctx->opcode);
#if !defined(CONFIG_USER_ONLY)
......@@ -4054,8 +4043,7 @@ GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
write_cb = ctx->spr_cb[sprn].uea_write;
if (likely(write_cb != NULL)) {
if (likely(write_cb != SPR_NOACCESS)) {
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
(*write_cb)(ctx, sprn);
(*write_cb)(ctx, sprn, rS(ctx->opcode));
} else {
/* Privilege exception */
if (loglevel != 0) {
......
......@@ -66,67 +66,76 @@ PPC_IRQ_INIT_FN(970);
/* Generic callbacks:
* do nothing but store/retrieve spr value
*/
#ifdef PPC_DUMP_SPR_ACCESSES
static void spr_read_generic (void *opaque, int sprn)
{
gen_op_load_dump_spr(sprn);
}
static void spr_write_generic (void *opaque, int sprn)
static void spr_read_generic (void *opaque, int gprn, int sprn)
{
gen_op_store_dump_spr(sprn);
}
#else
static void spr_read_generic (void *opaque, int sprn)
{
gen_op_load_spr(sprn);
gen_load_spr(cpu_gpr[gprn], sprn);
#ifdef PPC_DUMP_SPR_ACCESSES
{
TCGv t0 = tcg_const_i32(sprn);
gen_helper_load_dump_spr(t0);
tcg_temp_free_i32(t0);
}
#endif
}
static void spr_write_generic (void *opaque, int sprn)
static void spr_write_generic (void *opaque, int sprn, int gprn)
{
gen_op_store_spr(sprn);
}
gen_store_spr(sprn, cpu_gpr[gprn]);
#ifdef PPC_DUMP_SPR_ACCESSES
{
TCGv t0 = tcg_const_i32(sprn);
gen_helper_store_dump_spr(t0);
tcg_temp_free_i32(t0);
}
#endif
}
#if !defined(CONFIG_USER_ONLY)
static void spr_write_clear (void *opaque, int sprn)
static void spr_write_clear (void *opaque, int sprn, int gprn)
{
gen_op_mask_spr(sprn);
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
gen_load_spr(t0, sprn);
tcg_gen_neg_tl(t1, cpu_gpr[gprn]);
tcg_gen_and_tl(t0, t0, t1);
gen_store_spr(sprn, t0);
tcg_temp_free(t0);
tcg_temp_free(t1);
}
#endif
/* SPR common to all PowerPC */
/* XER */
static void spr_read_xer (void *opaque, int sprn)
static void spr_read_xer (void *opaque, int gprn, int sprn)
{
tcg_gen_mov_tl(cpu_T[0], cpu_xer);
tcg_gen_mov_tl(cpu_gpr[gprn], cpu_xer);
}
static void spr_write_xer (void *opaque, int sprn)
static void spr_write_xer (void *opaque, int sprn, int gprn)
{
tcg_gen_mov_tl(cpu_xer, cpu_T[0]);
tcg_gen_mov_tl(cpu_xer, cpu_gpr[gprn]);
}
/* LR */
static void spr_read_lr (void *opaque, int sprn)
static void spr_read_lr (void *opaque, int gprn, int sprn)
{
tcg_gen_mov_tl(cpu_T[0], cpu_lr);
tcg_gen_mov_tl(cpu_gpr[gprn], cpu_lr);
}
static void spr_write_lr (void *opaque, int sprn)
static void spr_write_lr (void *opaque, int sprn, int gprn)
{
tcg_gen_mov_tl(cpu_lr, cpu_T[0]);
tcg_gen_mov_tl(cpu_lr, cpu_gpr[gprn]);
}
/* CTR */
static void spr_read_ctr (void *opaque, int sprn)
static void spr_read_ctr (void *opaque, int gprn, int sprn)
{
tcg_gen_mov_tl(cpu_T[0], cpu_ctr);
tcg_gen_mov_tl(cpu_gpr[gprn], cpu_ctr);
}
static void spr_write_ctr (void *opaque, int sprn)
static void spr_write_ctr (void *opaque, int sprn, int gprn)
{
tcg_gen_mov_tl(cpu_ctr, cpu_T[0]);
tcg_gen_mov_tl(cpu_ctr, cpu_gpr[gprn]);
}
/* User read access to SPR */
......@@ -135,192 +144,208 @@ static void spr_write_ctr (void *opaque, int sprn)
/* UPMCx */
/* USIA */
/* UDECR */
static void spr_read_ureg (void *opaque, int sprn)
static void spr_read_ureg (void *opaque, int gprn, int sprn)
{
gen_op_load_spr(sprn + 0x10);
gen_load_spr(cpu_gpr[gprn], sprn + 0x10);
}
/* SPR common to all non-embedded PowerPC */
/* DECR */
#if !defined(CONFIG_USER_ONLY)
static void spr_read_decr (void *opaque, int sprn)
static void spr_read_decr (void *opaque, int gprn, int sprn)
{
gen_op_load_decr();
gen_helper_load_decr(cpu_gpr[gprn]);
}
static void spr_write_decr (void *opaque, int sprn)
static void spr_write_decr (void *opaque, int sprn, int gprn)
{
gen_op_store_decr();
gen_helper_store_decr(cpu_gpr[gprn]);
}
#endif
/* SPR common to all non-embedded PowerPC, except 601 */
/* Time base */
static void spr_read_tbl (void *opaque, int sprn)
static void spr_read_tbl (void *opaque, int gprn, int sprn)
{
gen_op_load_tbl();
gen_helper_load_tbl(cpu_gpr[gprn]);
}
static void spr_read_tbu (void *opaque, int sprn)
static void spr_read_tbu (void *opaque, int gprn, int sprn)
{
gen_op_load_tbu();
gen_helper_load_tbu(cpu_gpr[gprn]);
}
__attribute__ (( unused ))
static void spr_read_atbl (void *opaque, int sprn)
static void spr_read_atbl (void *opaque, int gprn, int sprn)
{
gen_op_load_atbl();
gen_helper_load_atbl(cpu_gpr[gprn]);
}
__attribute__ (( unused ))
static void spr_read_atbu (void *opaque, int sprn)
static void spr_read_atbu (void *opaque, int gprn, int sprn)
{
gen_op_load_atbu();
gen_helper_load_atbu(cpu_gpr[gprn]);
}
#if !defined(CONFIG_USER_ONLY)
static void spr_write_tbl (void *opaque, int sprn)
static void spr_write_tbl (void *opaque, int sprn, int gprn)
{
gen_op_store_tbl();
gen_helper_store_tbl(cpu_gpr[gprn]);
}
static void spr_write_tbu (void *opaque, int sprn)
static void spr_write_tbu (void *opaque, int sprn, int gprn)
{
gen_op_store_tbu();
gen_helper_store_tbu(cpu_gpr[gprn]);
}
__attribute__ (( unused ))
static void spr_write_atbl (void *opaque, int sprn)
static void spr_write_atbl (void *opaque, int sprn, int gprn)
{
gen_op_store_atbl();
gen_helper_store_atbl(cpu_gpr[gprn]);
}
__attribute__ (( unused ))
static void spr_write_atbu (void *opaque, int sprn)
static void spr_write_atbu (void *opaque, int sprn, int gprn)
{
gen_op_store_atbu();
gen_helper_store_atbu(cpu_gpr[gprn]);
}
#endif
#if !defined(CONFIG_USER_ONLY)
/* IBAT0U...IBAT0U */
/* IBAT0L...IBAT7L */
static void spr_read_ibat (void *opaque, int sprn)
static void spr_read_ibat (void *opaque, int gprn, int sprn)
{
gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT0U) / 2);
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
}
static void spr_read_ibat_h (void *opaque, int sprn)
static void spr_read_ibat_h (void *opaque, int gprn, int sprn)
{
gen_op_load_ibat(sprn & 1, (sprn - SPR_IBAT4U) / 2);
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT4U) / 2]));
}
static void spr_write_ibatu (void *opaque, int sprn)
static void spr_write_ibatu (void *opaque, int sprn, int gprn)
{
gen_op_store_ibatu((sprn - SPR_IBAT0U) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
gen_helper_store_ibatu(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_ibatu_h (void *opaque, int sprn)
static void spr_write_ibatu_h (void *opaque, int sprn, int gprn)
{
gen_op_store_ibatu((sprn - SPR_IBAT4U) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT4U) / 2);
gen_helper_store_ibatu(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_ibatl (void *opaque, int sprn)
static void spr_write_ibatl (void *opaque, int sprn, int gprn)
{
gen_op_store_ibatl((sprn - SPR_IBAT0L) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0L) / 2);
gen_helper_store_ibatl(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_ibatl_h (void *opaque, int sprn)
static void spr_write_ibatl_h (void *opaque, int sprn, int gprn)
{
gen_op_store_ibatl((sprn - SPR_IBAT4L) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT4L) / 2);
gen_helper_store_ibatl(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
/* DBAT0U...DBAT7U */
/* DBAT0L...DBAT7L */
static void spr_read_dbat (void *opaque, int sprn)
static void spr_read_dbat (void *opaque, int gprn, int sprn)
{
gen_op_load_dbat(sprn & 1, (sprn - SPR_DBAT0U) / 2);
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, DBAT[sprn & 1][(sprn - SPR_DBAT0U) / 2]));
}
static void spr_read_dbat_h (void *opaque, int sprn)
static void spr_read_dbat_h (void *opaque, int gprn, int sprn)
{
gen_op_load_dbat(sprn & 1, ((sprn - SPR_DBAT4U) / 2) + 4);
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, DBAT[sprn & 1][((sprn - SPR_DBAT4U) / 2) + 4]));
}
static void spr_write_dbatu (void *opaque, int sprn)
static void spr_write_dbatu (void *opaque, int sprn, int gprn)
{
gen_op_store_dbatu((sprn - SPR_DBAT0U) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0U) / 2);
gen_helper_store_dbatu(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_dbatu_h (void *opaque, int sprn)
static void spr_write_dbatu_h (void *opaque, int sprn, int gprn)
{
gen_op_store_dbatu(((sprn - SPR_DBAT4U) / 2) + 4);
TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4U) / 2) + 4);
gen_helper_store_dbatu(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_dbatl (void *opaque, int sprn)
static void spr_write_dbatl (void *opaque, int sprn, int gprn)
{
gen_op_store_dbatl((sprn - SPR_DBAT0L) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_DBAT0L) / 2);
gen_helper_store_dbatl(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_dbatl_h (void *opaque, int sprn)
static void spr_write_dbatl_h (void *opaque, int sprn, int gprn)
{
gen_op_store_dbatl(((sprn - SPR_DBAT4L) / 2) + 4);
TCGv_i32 t0 = tcg_const_i32(((sprn - SPR_DBAT4L) / 2) + 4);
gen_helper_store_dbatl(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
/* SDR1 */
static void spr_read_sdr1 (void *opaque, int sprn)
static void spr_read_sdr1 (void *opaque, int gprn, int sprn)
{
gen_op_load_sdr1();
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, sdr1));
}
static void spr_write_sdr1 (void *opaque, int sprn)
static void spr_write_sdr1 (void *opaque, int sprn, int gprn)
{
gen_op_store_sdr1();
gen_helper_store_sdr1(cpu_gpr[gprn]);
}
/* 64 bits PowerPC specific SPRs */
/* ASR */
#if defined(TARGET_PPC64)
static void spr_read_asr (void *opaque, int sprn)
static void spr_read_asr (void *opaque, int gprn, int sprn)
{
gen_op_load_asr();
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, asr));
}
static void spr_write_asr (void *opaque, int sprn)
static void spr_write_asr (void *opaque, int sprn, int gprn)
{
gen_op_store_asr();
gen_helper_store_asr(cpu_gpr[gprn]);
}
#endif
#endif
/* PowerPC 601 specific registers */
/* RTC */
static void spr_read_601_rtcl (void *opaque, int sprn)
static void spr_read_601_rtcl (void *opaque, int gprn, int sprn)
{
gen_op_load_601_rtcl();
gen_helper_load_601_rtcl(cpu_gpr[gprn]);
}
static void spr_read_601_rtcu (void *opaque, int sprn)
static void spr_read_601_rtcu (void *opaque, int gprn, int sprn)
{
gen_op_load_601_rtcu();
gen_helper_load_601_rtcu(cpu_gpr[gprn]);
}
#if !defined(CONFIG_USER_ONLY)
static void spr_write_601_rtcu (void *opaque, int sprn)
static void spr_write_601_rtcu (void *opaque, int sprn, int gprn)
{
gen_op_store_601_rtcu();
gen_helper_store_601_rtcu(cpu_gpr[gprn]);
}
static void spr_write_601_rtcl (void *opaque, int sprn)
static void spr_write_601_rtcl (void *opaque, int sprn, int gprn)
{
gen_op_store_601_rtcl();
gen_helper_store_601_rtcl(cpu_gpr[gprn]);
}
static void spr_write_hid0_601 (void *opaque, int sprn)
static void spr_write_hid0_601 (void *opaque, int sprn, int gprn)
{
DisasContext *ctx = opaque;
gen_op_store_hid0_601();
gen_helper_store_hid0_601(cpu_gpr[gprn]);
/* Must stop the translation as endianness may have changed */
GEN_STOP(ctx);
}
......@@ -328,96 +353,116 @@ static void spr_write_hid0_601 (void *opaque, int sprn)
/* Unified bats */
#if !defined(CONFIG_USER_ONLY)
static void spr_read_601_ubat (void *opaque, int sprn)
static void spr_read_601_ubat (void *opaque, int gprn, int sprn)
{
gen_op_load_601_bat(sprn & 1, (sprn - SPR_IBAT0U) / 2);
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, IBAT[sprn & 1][(sprn - SPR_IBAT0U) / 2]));
}
static void spr_write_601_ubatu (void *opaque, int sprn)
static void spr_write_601_ubatu (void *opaque, int sprn, int gprn)
{
gen_op_store_601_batu((sprn - SPR_IBAT0U) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
gen_helper_store_601_batl(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_601_ubatl (void *opaque, int sprn)
static void spr_write_601_ubatl (void *opaque, int sprn, int gprn)
{
gen_op_store_601_batl((sprn - SPR_IBAT0L) / 2);
TCGv_i32 t0 = tcg_const_i32((sprn - SPR_IBAT0U) / 2);
gen_helper_store_601_batu(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
#endif
/* PowerPC 40x specific registers */
#if !defined(CONFIG_USER_ONLY)
static void spr_read_40x_pit (void *opaque, int sprn)
static void spr_read_40x_pit (void *opaque, int gprn, int sprn)
{
gen_op_load_40x_pit();
gen_helper_load_40x_pit(cpu_gpr[gprn]);
}
static void spr_write_40x_pit (void *opaque, int sprn)
static void spr_write_40x_pit (void *opaque, int sprn, int gprn)
{
gen_op_store_40x_pit();
gen_helper_store_40x_pit(cpu_gpr[gprn]);
}
static void spr_write_40x_dbcr0 (void *opaque, int sprn)
static void spr_write_40x_dbcr0 (void *opaque, int sprn, int gprn)
{
DisasContext *ctx = opaque;
gen_op_store_40x_dbcr0();
gen_helper_store_40x_dbcr0(cpu_gpr[gprn]);
/* We must stop translation as we may have rebooted */
GEN_STOP(ctx);
}
static void spr_write_40x_sler (void *opaque, int sprn)
static void spr_write_40x_sler (void *opaque, int sprn, int gprn)
{
gen_op_store_40x_sler();
gen_helper_store_40x_sler(cpu_gpr[gprn]);
}
static void spr_write_booke_tcr (void *opaque, int sprn)
static void spr_write_booke_tcr (void *opaque, int sprn, int gprn)
{
gen_op_store_booke_tcr();
gen_helper_store_booke_tcr(cpu_gpr[gprn]);
}
static void spr_write_booke_tsr (void *opaque, int sprn)
static void spr_write_booke_tsr (void *opaque, int sprn, int gprn)
{
gen_op_store_booke_tsr();
gen_helper_store_booke_tsr(cpu_gpr[gprn]);
}
#endif
/* PowerPC 403 specific registers */
/* PBL1 / PBU1 / PBL2 / PBU2 */
#if !defined(CONFIG_USER_ONLY)
static void spr_read_403_pbr (void *opaque, int sprn)
static void spr_read_403_pbr (void *opaque, int gprn, int sprn)
{
gen_op_load_403_pb(sprn - SPR_403_PBL1);
tcg_gen_ld_tl(cpu_gpr[gprn], cpu_env, offsetof(CPUState, pb[sprn - SPR_403_PBL1]));
}
static void spr_write_403_pbr (void *opaque, int sprn)
static void spr_write_403_pbr (void *opaque, int sprn, int gprn)
{
gen_op_store_403_pb(sprn - SPR_403_PBL1);
TCGv_i32 t0 = tcg_const_i32(sprn - SPR_403_PBL1);
gen_helper_store_403_pbr(t0, cpu_gpr[gprn]);
tcg_temp_free_i32(t0);
}
static void spr_write_pir (void *opaque, int sprn)
static void spr_write_pir (void *opaque, int sprn, int gprn)
{
gen_op_store_pir();
TCGv t0 = tcg_temp_new();
tcg_gen_andi_tl(t0, cpu_gpr[gprn], 0xF);
gen_store_spr(SPR_PIR, t0);
tcg_temp_free(t0);
}
#endif
#if !defined(CONFIG_USER_ONLY)
/* Callback used to write the exception vector base */
static void spr_write_excp_prefix (void *opaque, int sprn)
static void spr_write_excp_prefix (void *opaque, int sprn, int gprn)
{
gen_op_store_excp_prefix();
gen_op_store_spr(sprn);
TCGv t0 = tcg_temp_new();
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivpr_mask));
tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_prefix));
gen_store_spr(sprn, t0);
}
static void spr_write_excp_vector (void *opaque, int sprn)
static void spr_write_excp_vector (void *opaque, int sprn, int gprn)
{
DisasContext *ctx = opaque;
if (sprn >= SPR_BOOKE_IVOR0 && sprn <= SPR_BOOKE_IVOR15) {
gen_op_store_excp_vector(sprn - SPR_BOOKE_IVOR0);
gen_op_store_spr(sprn);
TCGv t0 = tcg_temp_new();
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR0]));
gen_store_spr(sprn, t0);
tcg_temp_free(t0);
} else if (sprn >= SPR_BOOKE_IVOR32 && sprn <= SPR_BOOKE_IVOR37) {
gen_op_store_excp_vector(sprn - SPR_BOOKE_IVOR32 + 32);
gen_op_store_spr(sprn);
TCGv t0 = tcg_temp_new();
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, ivor_mask));
tcg_gen_and_tl(t0, t0, cpu_gpr[gprn]);
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, excp_vectors[sprn - SPR_BOOKE_IVOR32 + 32]));
gen_store_spr(sprn, t0);
tcg_temp_free(t0);
} else {
printf("Trying to write an unknown exception vector %d %03x\n",
sprn, sprn);
......@@ -434,16 +479,16 @@ do { \
} while (0)
static inline void _spr_register (CPUPPCState *env, int num,
const char *name,
void (*uea_read)(void *opaque, int sprn),
void (*uea_write)(void *opaque, int sprn),
void (*uea_read)(void *opaque, int gprn, int sprn),
void (*uea_write)(void *opaque, int sprn, int gprn),
target_ulong initial_value)
#else
static inline void spr_register (CPUPPCState *env, int num,
const char *name,
void (*uea_read)(void *opaque, int sprn),
void (*uea_write)(void *opaque, int sprn),
void (*oea_read)(void *opaque, int sprn),
void (*oea_write)(void *opaque, int sprn),
void (*uea_read)(void *opaque, int gprn, int sprn),
void (*uea_write)(void *opaque, int sprn, int gprn),
void (*oea_read)(void *opaque, int gprn, int sprn),
void (*oea_write)(void *opaque, int sprn, int gprn),
target_ulong initial_value)
#endif
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册