Commit dfbc799d authored by Aurelien Jarno's avatar Aurelien Jarno
Browse files

target-ppc: convert load/store string instructions to TCG



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

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5828 c046a42c-6fe2-441c-8c8c-71466251a162
parent 37d269df
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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)
+93 −0
Original line number Diff line number Diff line
@@ -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));
+0 −7
Original line number Diff line number Diff line
@@ -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);
+0 −72
Original line number Diff line number Diff line
@@ -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)
+0 −68
Original line number Diff line number Diff line
@@ -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)
{
Loading