aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-30 16:24:21 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-11-30 16:24:21 +0000
commitdfbc799d8e94d26ab2e6ad4a65dc97fd8fb6ece6 (patch)
tree05cca5d527831931b1c89bf320ba610d8080cc16 /target-ppc
parent37d269dfc6ccbfc3871d458c426e089e0c4403b6 (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
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/helper.h3
-rw-r--r--target-ppc/op_helper.c93
-rw-r--r--target-ppc/op_helper.h7
-rw-r--r--target-ppc/op_helper_mem.h72
-rw-r--r--target-ppc/op_mem.h68
-rw-r--r--target-ppc/translate.c95
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 ***/