diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-11-30 16:24:21 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-11-30 16:24:21 +0000 |
commit | dfbc799d8e94d26ab2e6ad4a65dc97fd8fb6ece6 (patch) | |
tree | 05cca5d527831931b1c89bf320ba610d8080cc16 | |
parent | 37d269dfc6ccbfc3871d458c426e089e0c4403b6 (diff) |
target-ppc: convert load/store string instructions to TCG
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5828 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | target-ppc/helper.h | 3 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 93 | ||||
-rw-r--r-- | target-ppc/op_helper.h | 7 | ||||
-rw-r--r-- | target-ppc/op_helper_mem.h | 72 | ||||
-rw-r--r-- | target-ppc/op_mem.h | 68 | ||||
-rw-r--r-- | target-ppc/translate.c | 95 |
6 files changed, 135 insertions, 203 deletions
diff --git a/target-ppc/helper.h b/target-ppc/helper.h index b22f6f205f..24be7700d5 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -9,6 +9,9 @@ DEF_HELPER_3(td, void, tl, tl, i32) 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) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 98c428990a..75fbefbb96 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -170,6 +170,99 @@ void helper_stmw (target_ulong addr, uint32_t reg) } } +void helper_lsw(target_ulong addr, uint32_t nb, uint32_t reg) +{ + int sh; +#ifdef CONFIG_USER_ONLY +#define ldfunl ldl_raw +#define ldfunb ldub_raw +#else + int (*ldfunl)(target_ulong); + int (*ldfunb)(target_ulong); + + switch (env->mmu_idx) { + default: + case 0: + ldfunl = ldl_user; + ldfunb = ldub_user; + break; + case 1: + ldfunl = ldl_kernel; + ldfunb = ldub_kernel; + break; + case 2: + ldfunl = ldl_hypv; + ldfunb = ldub_hypv; + break; + } +#endif + for (; nb > 3; nb -= 4, addr += 4) { + env->gpr[reg] = ldfunl(get_addr(addr)); + reg = (reg + 1) % 32; + } + if (unlikely(nb > 0)) { + env->gpr[reg] = 0; + for (sh = 24; nb > 0; nb--, addr++, sh -= 8) { + env->gpr[reg] |= ldfunb(get_addr(addr)) << sh; + } + } +} +/* PPC32 specification says we must generate an exception if + * rA is in the range of registers to be loaded. + * 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) +{ + if (likely(xer_bc != 0)) { + if (unlikely((ra != 0 && reg < ra && (reg + xer_bc) > ra) || + (reg < rb && (reg + xer_bc) > rb))) { + raise_exception_err(env, POWERPC_EXCP_PROGRAM, + POWERPC_EXCP_INVAL | + POWERPC_EXCP_INVAL_LSWX); + } else { + helper_lsw(addr, xer_bc, reg); + } + } +} + +void helper_stsw(target_ulong addr, uint32_t nb, uint32_t reg) +{ + int sh; +#ifdef CONFIG_USER_ONLY +#define stfunl stl_raw +#define stfunb stb_raw +#else + void (*stfunl)(target_ulong, int); + void (*stfunb)(target_ulong, int); + + switch (env->mmu_idx) { + default: + case 0: + stfunl = stl_user; + stfunb = stb_user; + break; + case 1: + stfunl = stl_kernel; + stfunb = stb_kernel; + break; + case 2: + stfunl = stl_hypv; + stfunb = stb_hypv; + break; + } +#endif + + for (; nb > 3; nb -= 4, addr += 4) { + stfunl(get_addr(addr), env->gpr[reg]); + reg = (reg + 1) % 32; + } + if (unlikely(nb > 0)) { + for (sh = 24; nb > 0; nb--, addr++, sh -= 8) + stfunb(get_addr(addr), (env->gpr[reg] >> sh) & 0xFF); + } +} + static void do_dcbz(target_ulong addr, int dcache_line_size) { target_long mask = get_addr(~(dcache_line_size - 1)); diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h index 48ac651767..5b86fe9c14 100644 --- a/target-ppc/op_helper.h +++ b/target-ppc/op_helper.h @@ -21,19 +21,12 @@ #if defined(MEMSUFFIX) /* Memory load/store helpers */ -void glue(do_lsw, MEMSUFFIX) (int dst); -void glue(do_stsw, MEMSUFFIX) (int src); void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb); void glue(do_POWER2_lfq, MEMSUFFIX) (void); void glue(do_POWER2_lfq_le, MEMSUFFIX) (void); void glue(do_POWER2_stfq, MEMSUFFIX) (void); void glue(do_POWER2_stfq_le, MEMSUFFIX) (void); -#if defined(TARGET_PPC64) -void glue(do_lsw_64, MEMSUFFIX) (int dst); -void glue(do_stsw_64, MEMSUFFIX) (int src); -#endif - #else void do_print_mem_EA (target_ulong EA); diff --git a/target-ppc/op_helper_mem.h b/target-ppc/op_helper_mem.h index 9663110693..8940bdbb00 100644 --- a/target-ppc/op_helper_mem.h +++ b/target-ppc/op_helper_mem.h @@ -20,78 +20,6 @@ #include "op_mem_access.h" -void glue(do_lsw, MEMSUFFIX) (int dst) -{ - uint32_t tmp; - int sh; - - for (; T1 > 3; T1 -= 4, T0 += 4) { - env->gpr[dst++] = glue(ldu32, MEMSUFFIX)((uint32_t)T0); - if (unlikely(dst == 32)) - dst = 0; - } - if (unlikely(T1 != 0)) { - tmp = 0; - for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) { - tmp |= glue(ldu8, MEMSUFFIX)((uint32_t)T0) << sh; - } - env->gpr[dst] = tmp; - } -} - -#if defined(TARGET_PPC64) -void glue(do_lsw_64, MEMSUFFIX) (int dst) -{ - uint32_t tmp; - int sh; - - for (; T1 > 3; T1 -= 4, T0 += 4) { - env->gpr[dst++] = glue(ldu32, MEMSUFFIX)((uint64_t)T0); - if (unlikely(dst == 32)) - dst = 0; - } - if (unlikely(T1 != 0)) { - tmp = 0; - for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) { - tmp |= glue(ldu8, MEMSUFFIX)((uint64_t)T0) << sh; - } - env->gpr[dst] = tmp; - } -} -#endif - -void glue(do_stsw, MEMSUFFIX) (int src) -{ - int sh; - - for (; T1 > 3; T1 -= 4, T0 += 4) { - glue(st32, MEMSUFFIX)((uint32_t)T0, env->gpr[src++]); - if (unlikely(src == 32)) - src = 0; - } - if (unlikely(T1 != 0)) { - for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) - glue(st8, MEMSUFFIX)((uint32_t)T0, (env->gpr[src] >> sh) & 0xFF); - } -} - -#if defined(TARGET_PPC64) -void glue(do_stsw_64, MEMSUFFIX) (int src) -{ - int sh; - - for (; T1 > 3; T1 -= 4, T0 += 4) { - glue(st32, MEMSUFFIX)((uint64_t)T0, env->gpr[src++]); - if (unlikely(src == 32)) - src = 0; - } - if (unlikely(T1 != 0)) { - for (sh = 24; T1 > 0; T1--, T0++, sh -= 8) - glue(st8, MEMSUFFIX)((uint64_t)T0, (env->gpr[src] >> sh) & 0xFF); - } -} -#endif - /* PowerPC 601 specific instructions (POWER bridge) */ // XXX: to be tested void glue(do_POWER_lscbx, MEMSUFFIX) (int dest, int ra, int rb) diff --git a/target-ppc/op_mem.h b/target-ppc/op_mem.h index 37fc488d16..1de7f1ec35 100644 --- a/target-ppc/op_mem.h +++ b/target-ppc/op_mem.h @@ -20,74 +20,6 @@ #include "op_mem_access.h" -/*** Integer load and store strings ***/ -void OPPROTO glue(op_lswi, MEMSUFFIX) (void) -{ - glue(do_lsw, MEMSUFFIX)(PARAM1); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_lswi_64, MEMSUFFIX) (void) -{ - glue(do_lsw_64, MEMSUFFIX)(PARAM1); - RETURN(); -} -#endif - -/* PPC32 specification says we must generate an exception if - * rA is in the range of registers to be loaded. - * In an other hand, IBM says this is valid, but rA won't be loaded. - * For now, I'll follow the spec... - */ -void OPPROTO glue(op_lswx, MEMSUFFIX) (void) -{ - /* Note: T1 comes from xer_bc then no cast is needed */ - if (likely(T1 != 0)) { - if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) || - (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) { - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | - POWERPC_EXCP_INVAL_LSWX); - } else { - glue(do_lsw, MEMSUFFIX)(PARAM1); - } - } - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_lswx_64, MEMSUFFIX) (void) -{ - /* Note: T1 comes from xer_bc then no cast is needed */ - if (likely(T1 != 0)) { - if (unlikely((PARAM1 < PARAM2 && (PARAM1 + T1) > PARAM2) || - (PARAM1 < PARAM3 && (PARAM1 + T1) > PARAM3))) { - raise_exception_err(env, POWERPC_EXCP_PROGRAM, - POWERPC_EXCP_INVAL | - POWERPC_EXCP_INVAL_LSWX); - } else { - glue(do_lsw_64, MEMSUFFIX)(PARAM1); - } - } - RETURN(); -} -#endif - -void OPPROTO glue(op_stsw, MEMSUFFIX) (void) -{ - glue(do_stsw, MEMSUFFIX)(PARAM1); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO glue(op_stsw_64, MEMSUFFIX) (void) -{ - glue(do_stsw_64, MEMSUFFIX)(PARAM1); - RETURN(); -} -#endif - /* Load and set reservation */ void OPPROTO glue(op_lwarx, MEMSUFFIX) (void) { diff --git a/target-ppc/translate.c b/target-ppc/translate.c index aff9a30753..91c0f3d07e 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -3118,43 +3118,6 @@ GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER) } /*** Integer load and store strings ***/ -#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start) -#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb) -/* string load & stores are by definition endian-safe */ -#define gen_op_lswi_le_raw gen_op_lswi_raw -#define gen_op_lswi_le_user gen_op_lswi_user -#define gen_op_lswi_le_kernel gen_op_lswi_kernel -#define gen_op_lswi_le_hypv gen_op_lswi_hypv -#define gen_op_lswi_le_64_raw gen_op_lswi_raw -#define gen_op_lswi_le_64_user gen_op_lswi_user -#define gen_op_lswi_le_64_kernel gen_op_lswi_kernel -#define gen_op_lswi_le_64_hypv gen_op_lswi_hypv -static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(lswi), -}; -#define gen_op_lswx_le_raw gen_op_lswx_raw -#define gen_op_lswx_le_user gen_op_lswx_user -#define gen_op_lswx_le_kernel gen_op_lswx_kernel -#define gen_op_lswx_le_hypv gen_op_lswx_hypv -#define gen_op_lswx_le_64_raw gen_op_lswx_raw -#define gen_op_lswx_le_64_user gen_op_lswx_user -#define gen_op_lswx_le_64_kernel gen_op_lswx_kernel -#define gen_op_lswx_le_64_hypv gen_op_lswx_hypv -static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(lswx), -}; -#define gen_op_stsw_le_raw gen_op_stsw_raw -#define gen_op_stsw_le_user gen_op_stsw_user -#define gen_op_stsw_le_kernel gen_op_stsw_kernel -#define gen_op_stsw_le_hypv gen_op_stsw_hypv -#define gen_op_stsw_le_64_raw gen_op_stsw_raw -#define gen_op_stsw_le_64_user gen_op_stsw_user -#define gen_op_stsw_le_64_kernel gen_op_stsw_kernel -#define gen_op_stsw_le_64_hypv gen_op_stsw_hypv -static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = { - GEN_MEM_FUNCS(stsw), -}; - /* lswi */ /* PowerPC32 specification says we must generate an exception if * rA is in the range of registers to be loaded. @@ -3163,6 +3126,8 @@ static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = { */ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING) { + TCGv t0; + TCGv_i32 t1, t2; int nb = NB(ctx->opcode); int start = rD(ctx->opcode); int ra = rA(ctx->opcode); @@ -3180,49 +3145,67 @@ GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING) } /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_register(cpu_T[0], ctx); - tcg_gen_movi_tl(cpu_T[1], nb); - op_ldsts(lswi, start); + t0 = tcg_temp_new(); + gen_addr_register(t0, ctx); + t1 = tcg_const_i32(nb); + t2 = tcg_const_i32(start); + gen_helper_lsw(t0, t1, t2); + tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); } /* lswx */ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING) { - int ra = rA(ctx->opcode); - int rb = rB(ctx->opcode); - + TCGv t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode)); + TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode)); + TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode)); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_reg_index(cpu_T[0], ctx); - if (ra == 0) { - ra = rb; - } - tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F); - op_ldstsx(lswx, rD(ctx->opcode), ra, rb); + gen_addr_reg_index(t0, ctx); + gen_helper_lswx(t0, t1, t2, t3); + tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t3); } /* stswi */ GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING) { int nb = NB(ctx->opcode); - + TCGv t0 = tcg_temp_new(); + TCGv_i32 t1; + TCGv_i32 t2 = tcg_const_i32(rS(ctx->opcode)); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_register(cpu_T[0], ctx); + gen_addr_register(t0, ctx); if (nb == 0) nb = 32; - tcg_gen_movi_tl(cpu_T[1], nb); - op_ldsts(stsw, rS(ctx->opcode)); + t1 = tcg_const_i32(nb); + gen_helper_stsw(t0, t1, t2); + tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); } /* stswx */ GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING) { + TCGv t0 = tcg_temp_new(); + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_const_i32(rS(ctx->opcode)); /* NIP cannot be restored if the memory exception comes from an helper */ gen_update_nip(ctx, ctx->nip - 4); - gen_addr_reg_index(cpu_T[0], ctx); - tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F); - op_ldsts(stsw, rS(ctx->opcode)); + gen_addr_reg_index(t0, ctx); + tcg_gen_trunc_tl_i32(t1, cpu_xer); + tcg_gen_andi_i32(t1, t1, 0x7F); + gen_helper_stsw(t0, t1, t2); + tcg_temp_free(t0); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); } /*** Memory synchronisation ***/ |