}
}
-void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
+static void do_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb,
+ uint32_t reg, uintptr_t raddr)
{
int sh;
for (; nb > 3; nb -= 4) {
- env->gpr[reg] = cpu_ldl_data(env, addr);
+ env->gpr[reg] = cpu_ldl_data_ra(env, addr, raddr);
reg = (reg + 1) % 32;
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] |= cpu_ldub_data(env, addr) << sh;
+ env->gpr[reg] |= cpu_ldub_data_ra(env, addr, raddr) << sh;
addr = addr_add(env, addr, 1);
}
}
}
+
+void helper_lsw(CPUPPCState *env, target_ulong addr, uint32_t nb, uint32_t reg)
+{
+ do_lsw(env, addr, nb, reg, GETPC());
+}
+
/* 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.
int num_used_regs = (xer_bc + 3) / 4;
if (unlikely((ra != 0 && lsw_reg_in_range(reg, num_used_regs, ra)) ||
lsw_reg_in_range(reg, num_used_regs, rb))) {
- env->nip += 4; /* Compensate the "nip - 4" from gen_lswx() */
- helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
- POWERPC_EXCP_INVAL |
- POWERPC_EXCP_INVAL_LSWX);
+ raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
+ POWERPC_EXCP_INVAL |
+ POWERPC_EXCP_INVAL_LSWX, GETPC());
} else {
- helper_lsw(env, addr, xer_bc, reg);
+ do_lsw(env, addr, xer_bc, reg, GETPC());
}
}
}
int sh;
for (; nb > 3; nb -= 4) {
- cpu_stl_data(env, addr, env->gpr[reg]);
+ cpu_stl_data_ra(env, addr, env->gpr[reg], GETPC());
reg = (reg + 1) % 32;
addr = addr_add(env, addr, 4);
}
if (unlikely(nb > 0)) {
for (sh = 24; nb > 0; nb--, sh -= 8) {
- cpu_stb_data(env, addr, (env->gpr[reg] >> sh) & 0xFF);
+ cpu_stb_data_ra(env, addr, (env->gpr[reg] >> sh) & 0xFF, GETPC());
addr = addr_add(env, addr, 1);
}
}
nb = 32;
nr = (nb + 3) / 4;
if (unlikely(lsw_reg_in_range(start, nr, ra))) {
+ /* The handler expects the PC to point to *this* instruction,
+ * so setting ctx->exception here prevents it from being
+ * improperly updated again by gen_inval_exception
+ */
+ gen_update_nip(ctx, ctx->nip - 4);
+ ctx->exception = POWERPC_EXCP_HV_EMU;
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
return;
}
gen_set_access_type(ctx, ACCESS_INT);
- /* NIP cannot be restored if the memory exception comes from an helper */
- gen_update_nip(ctx, ctx->nip - 4);
t0 = tcg_temp_new();
gen_addr_register(ctx, t0);
t1 = tcg_const_i32(nb);
TCGv t0;
TCGv_i32 t1, t2, t3;
gen_set_access_type(ctx, ACCESS_INT);
- /* NIP cannot be restored if the memory exception comes from an helper */
- gen_update_nip(ctx, ctx->nip - 4);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
t1 = tcg_const_i32(rD(ctx->opcode));
TCGv_i32 t1, t2;
int nb = NB(ctx->opcode);
gen_set_access_type(ctx, ACCESS_INT);
- /* NIP cannot be restored if the memory exception comes from an helper */
- gen_update_nip(ctx, ctx->nip - 4);
t0 = tcg_temp_new();
gen_addr_register(ctx, t0);
if (nb == 0)
TCGv t0;
TCGv_i32 t1, t2;
gen_set_access_type(ctx, ACCESS_INT);
- /* NIP cannot be restored if the memory exception comes from an helper */
- gen_update_nip(ctx, ctx->nip - 4);
t0 = tcg_temp_new();
gen_addr_reg_index(ctx, t0);
t1 = tcg_temp_new_i32();
static void gen_dst(DisasContext *ctx)
{
if (rA(ctx->opcode) == 0) {
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
} else {
/* interpreted as no-op */
}
static void gen_dstst(DisasContext *ctx)
{
if (rA(ctx->opcode) == 0) {
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
} else {
/* interpreted as no-op */
}