ppc: Move load and store helpers, switch to AREG0 free mode

Add an explicit CPUPPCState parameter instead of relying on AREG0
and rename op_helper.c (which only contains load and store helpers)
to mem_helper.c. Remove AREG0 swapping in
tlb_fill().

Switch to AREG0 free mode. Use cpu_ld{l,uw}_code in translation
and interrupt handling, cpu_{ld,st}{l,uw}_data in loads and stores.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
Blue Swirl 2012-05-30 04:23:40 +00:00 committed by Alexander Graf
parent 8555f71dcb
commit 2f5a189cae
7 changed files with 100 additions and 90 deletions

2
configure vendored
View File

@ -3679,7 +3679,7 @@ symlink "$source_path/Makefile.target" "$target_dir/Makefile"
case "$target_arch2" in
alpha | sparc* | xtensa*)
alpha | sparc* | xtensa* | ppc*)
echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
;;
esac

View File

@ -291,6 +291,15 @@ extern unsigned long reserved_va;
#define stfl_kernel(p, v) stfl_raw(p, v)
#define stfq_kernel(p, vt) stfq_raw(p, v)
#ifdef CONFIG_TCG_PASS_AREG0
#define cpu_ldub_data(env, addr) ldub_raw(addr)
#define cpu_lduw_data(env, addr) lduw_raw(addr)
#define cpu_ldl_data(env, addr) ldl_raw(addr)
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
#endif
#endif /* defined(CONFIG_USER_ONLY) */
/* page related stuff */

View File

@ -1,12 +1,11 @@
obj-y += translate.o op_helper.o helper.o
obj-y += translate.o helper.o
obj-$(CONFIG_SOFTMMU) += machine.o
obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
obj-y += op_helper.o helper.o
obj-y += helper.o
obj-y += excp_helper.o
obj-y += fpu_helper.o
obj-y += int_helper.o
obj-y += mmu_helper.o
obj-y += timebase_helper.o
obj-y += misc_helper.o
$(obj)/op_helper.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
obj-y += mem_helper.o

View File

@ -179,7 +179,8 @@ static inline void powerpc_excp(CPUPPCState *env, int excp_model, int excp)
}
/* XXX: this is false */
/* Get rS/rD and rA from faulting opcode */
env->spr[SPR_DSISR] |= (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
& 0x03FF0000) >> 16;
goto store_current;
case POWERPC_EXCP_PROGRAM: /* Program exception */
switch (env->error_code & ~0xF) {

View File

@ -20,15 +20,15 @@ DEF_HELPER_1(hrfid, void, env)
#endif
#endif
DEF_HELPER_2(lmw, void, tl, i32)
DEF_HELPER_2(stmw, void, tl, i32)
DEF_HELPER_3(lsw, void, tl, i32, i32)
DEF_HELPER_4(lswx, void, tl, i32, i32, i32)
DEF_HELPER_3(stsw, void, tl, i32, i32)
DEF_HELPER_1(dcbz, void, tl)
DEF_HELPER_1(dcbz_970, void, tl)
DEF_HELPER_1(icbi, void, tl)
DEF_HELPER_4(lscbx, tl, tl, i32, i32, i32)
DEF_HELPER_3(lmw, void, env, tl, i32)
DEF_HELPER_3(stmw, void, env, tl, i32)
DEF_HELPER_4(lsw, void, env, tl, i32, i32)
DEF_HELPER_5(lswx, void, env, tl, i32, i32, i32)
DEF_HELPER_4(stsw, void, env, tl, i32, i32)
DEF_HELPER_2(dcbz, void, env, tl)
DEF_HELPER_2(dcbz_970, void, env, tl)
DEF_HELPER_2(icbi, void, env, tl)
DEF_HELPER_5(lscbx, tl, env, tl, i32, i32, i32)
#if defined(TARGET_PPC64)
DEF_HELPER_FLAGS_2(mulhd, TCG_CALL_CONST | TCG_CALL_PURE, i64, i64, i64)
@ -226,12 +226,12 @@ DEF_HELPER_5(vmsumshm, void, env, avr, avr, avr, avr)
DEF_HELPER_5(vmsumshs, void, env, avr, avr, avr, avr)
DEF_HELPER_4(vmladduhm, void, avr, avr, avr, avr)
DEF_HELPER_2(mtvscr, void, env, avr);
DEF_HELPER_2(lvebx, void, avr, tl)
DEF_HELPER_2(lvehx, void, avr, tl)
DEF_HELPER_2(lvewx, void, avr, tl)
DEF_HELPER_2(stvebx, void, avr, tl)
DEF_HELPER_2(stvehx, void, avr, tl)
DEF_HELPER_2(stvewx, void, avr, tl)
DEF_HELPER_3(lvebx, void, env, avr, tl)
DEF_HELPER_3(lvehx, void, env, avr, tl)
DEF_HELPER_3(lvewx, void, env, avr, tl)
DEF_HELPER_3(stvebx, void, env, avr, tl)
DEF_HELPER_3(stvehx, void, env, avr, tl)
DEF_HELPER_3(stvewx, void, env, avr, tl)
DEF_HELPER_4(vsumsws, void, env, avr, avr, avr)
DEF_HELPER_4(vsum2sws, void, env, avr, avr, avr)
DEF_HELPER_4(vsum4sbs, void, env, avr, avr, avr)

View File

@ -1,5 +1,5 @@
/*
* PowerPC emulation helpers for QEMU.
* PowerPC memory access emulation helpers for QEMU.
*
* Copyright (c) 2003-2007 Jocelyn Mayer
*
@ -16,9 +16,7 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "cpu.h"
#include "dyngen-exec.h"
#include "host-utils.h"
#include "helper.h"
@ -33,7 +31,8 @@
/*****************************************************************************/
/* Memory load and stores */
static inline target_ulong addr_add(target_ulong addr, target_long arg)
static inline target_ulong addr_add(CPUPPCState *env, target_ulong addr,
target_long arg)
{
#if defined(TARGET_PPC64)
if (!msr_sf) {
@ -45,44 +44,44 @@ static inline target_ulong addr_add(target_ulong addr, target_long arg)
}
}
void helper_lmw(target_ulong addr, uint32_t reg)
void helper_lmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
for (; reg < 32; reg++) {
if (msr_le) {
env->gpr[reg] = bswap32(ldl(addr));
env->gpr[reg] = bswap32(cpu_ldl_data(env, addr));
} else {
env->gpr[reg] = ldl(addr);
env->gpr[reg] = cpu_ldl_data(env, addr);
}
addr = addr_add(addr, 4);
addr = addr_add(env, addr, 4);
}
}
void helper_stmw(target_ulong addr, uint32_t reg)
void helper_stmw(CPUPPCState *env, target_ulong addr, uint32_t reg)
{
for (; reg < 32; reg++) {
if (msr_le) {
stl(addr, bswap32((uint32_t)env->gpr[reg]));
cpu_stl_data(env, addr, bswap32((uint32_t)env->gpr[reg]));
} else {
stl(addr, (uint32_t)env->gpr[reg]);
cpu_stl_data(env, addr, (uint32_t)env->gpr[reg]);
}
addr = addr_add(addr, 4);
addr = addr_add(env, addr, 4);
}
}
void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
{
int sh;
for (; nb > 3; nb -= 4) {
env->gpr[reg] = ldl(addr);
env->gpr[reg] = cpu_ldl_data(env, addr);
reg = (reg + 1) % 32;
addr = addr_add(addr, 4);
addr = addr_add(env, addr, 4);
}
if (unlikely(nb > 0)) {
env->gpr[reg] = 0;
for (sh = 24; nb > 0; nb--, sh -= 8) {
env->gpr[reg] |= ldub(addr) << sh;
addr = addr_add(addr, 1);
env->gpr[reg] |= cpu_ldub_data(env, addr) << sh;
addr = addr_add(env, addr, 1);
}
}
}
@ -91,7 +90,8 @@ void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg)
* In an other hand, IBM says this is valid, but rA won't be loaded.
* For now, I'll follow the spec...
*/
void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
void helper_lswx(CPUPPCState *env, target_ulong addr, uint32_t reg,
uint32_t ra, uint32_t rb)
{
if (likely(xer_bc != 0)) {
if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) ||
@ -100,56 +100,57 @@ void helper_lswx(target_ulong addr, uint32_t reg, uint32_t ra, uint32_t rb)
POWERPC_EXCP_INVAL |
POWERPC_EXCP_INVAL_LSWX);
} else {
helper_lsw(addr, xer_bc, reg);
helper_lsw(env, addr, xer_bc, reg);
}
}
}
void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg)
void helper_stsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
uint32_t reg)
{
int sh;
for (; nb > 3; nb -= 4) {
stl(addr, env->gpr[reg]);
cpu_stl_data(env, addr, env->gpr[reg]);
reg = (reg + 1) % 32;
addr = addr_add(addr, 4);
addr = addr_add(env, addr, 4);
}
if (unlikely(nb > 0)) {
for (sh = 24; nb > 0; nb--, sh -= 8) {
stb(addr, (env->gpr[reg] >> sh) & 0xFF);
addr = addr_add(addr, 1);
cpu_stb_data(env, addr, (env->gpr[reg] >> sh) & 0xFF);
addr = addr_add(env, addr, 1);
}
}
}
static void do_dcbz(target_ulong addr, int dcache_line_size)
static void do_dcbz(CPUPPCState *env, target_ulong addr, int dcache_line_size)
{
int i;
addr &= ~(dcache_line_size - 1);
for (i = 0; i < dcache_line_size; i += 4) {
stl(addr + i, 0);
cpu_stl_data(env, addr + i, 0);
}
if (env->reserve_addr == addr) {
env->reserve_addr = (target_ulong)-1ULL;
}
}
void helper_dcbz(target_ulong addr)
void helper_dcbz(CPUPPCState *env, target_ulong addr)
{
do_dcbz(addr, env->dcache_line_size);
do_dcbz(env, addr, env->dcache_line_size);
}
void helper_dcbz_970(target_ulong addr)
void helper_dcbz_970(CPUPPCState *env, target_ulong addr)
{
if (((env->spr[SPR_970_HID5] >> 7) & 0x3) == 1) {
do_dcbz(addr, 32);
do_dcbz(env, addr, 32);
} else {
do_dcbz(addr, env->dcache_line_size);
do_dcbz(env, addr, env->dcache_line_size);
}
}
void helper_icbi(target_ulong addr)
void helper_icbi(CPUPPCState *env, target_ulong addr)
{
addr &= ~(env->dcache_line_size - 1);
/* Invalidate one cache line :
@ -157,19 +158,19 @@ void helper_icbi(target_ulong addr)
* (not a fetch) by the MMU. To be sure it will be so,
* do the load "by hand".
*/
ldl(addr);
cpu_ldl_data(env, addr);
}
/* XXX: to be tested */
target_ulong helper_lscbx(target_ulong addr, uint32_t reg, uint32_t ra,
uint32_t rb)
target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
uint32_t ra, uint32_t rb)
{
int i, c, d;
d = 24;
for (i = 0; i < xer_bc; i++) {
c = ldub(addr);
addr = addr_add(addr, 1);
c = cpu_ldub_data(env, addr);
addr = addr_add(env, addr, 1);
/* ra (if not 0) and rb are never modified */
if (likely(reg != rb && (ra == 0 || reg != ra))) {
env->gpr[reg] = (env->gpr[reg] & ~(0xFF << d)) | (c << d);
@ -199,7 +200,8 @@ target_ulong helper_lscbx(target_ulong addr, uint32_t reg, uint32_t ra,
#endif
#define LVE(name, access, swap, element) \
void helper_##name(ppc_avr_t *r, target_ulong addr) \
void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
target_ulong addr) \
{ \
size_t n_elems = ARRAY_SIZE(r->element); \
int adjust = HI_IDX*(n_elems - 1); \
@ -208,21 +210,22 @@ target_ulong helper_lscbx(target_ulong addr, uint32_t reg, uint32_t ra,
\
if (msr_le) { \
r->element[LO_IDX ? index : (adjust - index)] = \
swap(access(addr)); \
swap(access(env, addr)); \
} else { \
r->element[LO_IDX ? index : (adjust - index)] = \
access(addr); \
access(env, addr); \
} \
}
#define I(x) (x)
LVE(lvebx, ldub, I, u8)
LVE(lvehx, lduw, bswap16, u16)
LVE(lvewx, ldl, bswap32, u32)
LVE(lvebx, cpu_ldub_data, I, u8)
LVE(lvehx, cpu_lduw_data, bswap16, u16)
LVE(lvewx, cpu_ldl_data, bswap32, u32)
#undef I
#undef LVE
#define STVE(name, access, swap, element) \
void helper_##name(ppc_avr_t *r, target_ulong addr) \
void helper_##name(CPUPPCState *env, ppc_avr_t *r, \
target_ulong addr) \
{ \
size_t n_elems = ARRAY_SIZE(r->element); \
int adjust = HI_IDX * (n_elems - 1); \
@ -230,15 +233,17 @@ LVE(lvewx, ldl, bswap32, u32)
int index = (addr & 0xf) >> sh; \
\
if (msr_le) { \
access(addr, swap(r->element[LO_IDX ? index : (adjust - index)])); \
access(env, addr, swap(r->element[LO_IDX ? index : \
(adjust - index)])); \
} else { \
access(addr, r->element[LO_IDX ? index : (adjust - index)]); \
access(env, addr, r->element[LO_IDX ? index : \
(adjust - index)]); \
} \
}
#define I(x) (x)
STVE(stvebx, stb, I, u8)
STVE(stvehx, stw, bswap16, u16)
STVE(stvewx, stl, bswap32, u32)
STVE(stvebx, cpu_stb_data, I, u8)
STVE(stvehx, cpu_stw_data, bswap16, u16)
STVE(stvewx, cpu_stl_data, bswap32, u32)
#undef I
#undef LVE
@ -267,15 +272,12 @@ STVE(stvewx, stl, bswap32, u32)
NULL, it means that the function was called in C code (i.e. not
from generated code or from helper.c) */
/* XXX: fix it to restore all registers */
void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
TranslationBlock *tb;
CPUPPCState *saved_env;
int ret;
saved_env = env;
env = env1;
ret = cpu_ppc_handle_mmu_fault(env, addr, is_write, mmu_idx);
if (unlikely(ret != 0)) {
if (likely(retaddr)) {
@ -289,6 +291,5 @@ void tlb_fill(CPUPPCState *env1, target_ulong addr, int is_write, int mmu_idx,
}
helper_raise_exception_err(env, env->exception_index, env->error_code);
}
env = saved_env;
}
#endif /* !CONFIG_USER_ONLY */

View File

@ -2989,7 +2989,7 @@ static void gen_lmw(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_const_i32(rD(ctx->opcode));
gen_addr_imm_index(ctx, t0, 0);
gen_helper_lmw(t0, t1);
gen_helper_lmw(cpu_env, t0, t1);
tcg_temp_free(t0);
tcg_temp_free_i32(t1);
}
@ -3005,7 +3005,7 @@ static void gen_stmw(DisasContext *ctx)
t0 = tcg_temp_new();
t1 = tcg_const_i32(rS(ctx->opcode));
gen_addr_imm_index(ctx, t0, 0);
gen_helper_stmw(t0, t1);
gen_helper_stmw(cpu_env, t0, t1);
tcg_temp_free(t0);
tcg_temp_free_i32(t1);
}
@ -3043,7 +3043,7 @@ static void gen_lswi(DisasContext *ctx)
gen_addr_register(ctx, t0);
t1 = tcg_const_i32(nb);
t2 = tcg_const_i32(start);
gen_helper_lsw(t0, t1, t2);
gen_helper_lsw(cpu_env, t0, t1, t2);
tcg_temp_free(t0);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t2);
@ -3062,7 +3062,7 @@ static void gen_lswx(DisasContext *ctx)
t1 = tcg_const_i32(rD(ctx->opcode));
t2 = tcg_const_i32(rA(ctx->opcode));
t3 = tcg_const_i32(rB(ctx->opcode));
gen_helper_lswx(t0, t1, t2, t3);
gen_helper_lswx(cpu_env, t0, t1, t2, t3);
tcg_temp_free(t0);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t2);
@ -3084,7 +3084,7 @@ static void gen_stswi(DisasContext *ctx)
nb = 32;
t1 = tcg_const_i32(nb);
t2 = tcg_const_i32(rS(ctx->opcode));
gen_helper_stsw(t0, t1, t2);
gen_helper_stsw(cpu_env, t0, t1, t2);
tcg_temp_free(t0);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t2);
@ -3104,7 +3104,7 @@ static void gen_stswx(DisasContext *ctx)
tcg_gen_trunc_tl_i32(t1, cpu_xer);
tcg_gen_andi_i32(t1, t1, 0x7F);
t2 = tcg_const_i32(rS(ctx->opcode));
gen_helper_stsw(t0, t1, t2);
gen_helper_stsw(cpu_env, t0, t1, t2);
tcg_temp_free(t0);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t2);
@ -4116,7 +4116,7 @@ static void gen_dcbz(DisasContext *ctx)
gen_update_nip(ctx, ctx->nip - 4);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
gen_helper_dcbz(t0);
gen_helper_dcbz(cpu_env, t0);
tcg_temp_free(t0);
}
@ -4129,9 +4129,9 @@ static void gen_dcbz_970(DisasContext *ctx)
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
if (ctx->opcode & 0x00200000)
gen_helper_dcbz(t0);
gen_helper_dcbz(cpu_env, t0);
else
gen_helper_dcbz_970(t0);
gen_helper_dcbz_970(cpu_env, t0);
tcg_temp_free(t0);
}
@ -4171,7 +4171,7 @@ static void gen_icbi(DisasContext *ctx)
gen_update_nip(ctx, ctx->nip - 4);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
gen_helper_icbi(t0);
gen_helper_icbi(cpu_env, t0);
tcg_temp_free(t0);
}
@ -4663,7 +4663,7 @@ static void gen_lscbx(DisasContext *ctx)
gen_addr_reg_index(ctx, t0);
/* NIP cannot be restored if the memory exception comes from an helper */
gen_update_nip(ctx, ctx->nip - 4);
gen_helper_lscbx(t0, t0, t1, t2, t3);
gen_helper_lscbx(t0, cpu_env, t0, t1, t2, t3);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t3);
@ -6387,7 +6387,7 @@ static void gen_lve##name(DisasContext *ctx) \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
rs = gen_avr_ptr(rS(ctx->opcode)); \
gen_helper_lve##name (rs, EA); \
gen_helper_lve##name(cpu_env, rs, EA); \
tcg_temp_free(EA); \
tcg_temp_free_ptr(rs); \
}
@ -6405,7 +6405,7 @@ static void gen_stve##name(DisasContext *ctx) \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
rs = gen_avr_ptr(rS(ctx->opcode)); \
gen_helper_stve##name (rs, EA); \
gen_helper_stve##name(cpu_env, rs, EA); \
tcg_temp_free(EA); \
tcg_temp_free_ptr(rs); \
}
@ -9683,9 +9683,9 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env,
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
if (unlikely(ctx.le_mode)) {
ctx.opcode = bswap32(ldl_code(ctx.nip));
ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
} else {
ctx.opcode = ldl_code(ctx.nip);
ctx.opcode = cpu_ldl_code(env, ctx.nip);
}
LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),