static TCGv cpu_lr;
static TCGv cpu_xer;
static TCGv_i32 cpu_fpscr;
+static TCGv_i32 cpu_access_type;
/* dyngen register indexes */
static TCGv cpu_T[3];
cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUState, fpscr), "fpscr");
+ cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUState, access_type), "access_type");
+
/* register helpers */
#define GEN_HELPER 2
#include "helper.h"
#endif
}
+static always_inline void gen_set_access_type(int access_type)
+{
+ tcg_gen_movi_i32(cpu_access_type, access_type);
+}
+
static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
{
#if defined(TARGET_PPC64)
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
{ \
TCGv EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
gen_addr_imm_index(EA, ctx, 0); \
gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
tcg_temp_free(EA); \
return; \
} \
EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
if (type == PPC_64B) \
gen_addr_imm_index(EA, ctx, 0x03); \
else \
return; \
} \
EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
gen_addr_reg_index(EA, ctx); \
gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
{ \
TCGv EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
gen_addr_reg_index(EA, ctx); \
gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
tcg_temp_free(EA); \
}
}
EA = tcg_temp_new();
+ gen_set_access_type(ACCESS_INT);
gen_addr_imm_index(EA, ctx, 0x03);
if (ctx->opcode & 0x02) {
/* lwa (lwau is undefined) */
return;
}
EA = tcg_temp_new();
+ gen_set_access_type(ACCESS_INT);
gen_addr_imm_index(EA, ctx, 0x0F);
gen_qemu_ld64(cpu_gpr[rd], EA, ctx->mem_idx);
tcg_gen_addi_tl(EA, EA, 8);
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
{ \
TCGv EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
gen_addr_imm_index(EA, ctx, 0); \
gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
tcg_temp_free(EA); \
return; \
} \
EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
if (type == PPC_64B) \
gen_addr_imm_index(EA, ctx, 0x03); \
else \
return; \
} \
EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
gen_addr_reg_index(EA, ctx); \
gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
{ \
TCGv EA = tcg_temp_new(); \
+ gen_set_access_type(ACCESS_INT); \
gen_addr_reg_index(EA, ctx); \
gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
tcg_temp_free(EA); \
return;
}
EA = tcg_temp_new();
+ gen_set_access_type(ACCESS_INT);
gen_addr_imm_index(EA, ctx, 0x03);
gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
tcg_gen_addi_tl(EA, EA, 8);
}
}
EA = tcg_temp_new();
+ gen_set_access_type(ACCESS_INT);
gen_addr_imm_index(EA, ctx, 0x03);
gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
if (Rc(ctx->opcode))
{
/* NIP cannot be restored if the memory exception comes from an helper */
gen_update_nip(ctx, ctx->nip - 4);
+ gen_set_access_type(ACCESS_RES);
gen_addr_reg_index(cpu_T[0], ctx);
op_lwarx();
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
{
/* NIP cannot be restored if the memory exception comes from an helper */
gen_update_nip(ctx, ctx->nip - 4);
+ gen_set_access_type(ACCESS_RES);
gen_addr_reg_index(cpu_T[0], ctx);
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
op_stwcx();
{
/* NIP cannot be restored if the memory exception comes from an helper */
gen_update_nip(ctx, ctx->nip - 4);
+ gen_set_access_type(ACCESS_RES);
gen_addr_reg_index(cpu_T[0], ctx);
op_ldarx();
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
{
/* NIP cannot be restored if the memory exception comes from an helper */
gen_update_nip(ctx, ctx->nip - 4);
+ gen_set_access_type(ACCESS_RES);
gen_addr_reg_index(cpu_T[0], ctx);
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
op_stdcx();
GEN_EXCP_NO_FP(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_imm_index(cpu_T[0], ctx, 0); \
op_ldst(l##width); \
tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
GEN_EXCP_INVAL(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_imm_index(cpu_T[0], ctx, 0); \
op_ldst(l##width); \
tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
GEN_EXCP_INVAL(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_reg_index(cpu_T[0], ctx); \
op_ldst(l##width); \
tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
GEN_EXCP_NO_FP(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_reg_index(cpu_T[0], ctx); \
op_ldst(l##width); \
tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
GEN_EXCP_NO_FP(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_imm_index(cpu_T[0], ctx, 0); \
tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
op_ldst(st##width); \
GEN_EXCP_INVAL(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_imm_index(cpu_T[0], ctx, 0); \
tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
op_ldst(st##width); \
GEN_EXCP_INVAL(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_reg_index(cpu_T[0], ctx); \
tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
op_ldst(st##width); \
GEN_EXCP_NO_FP(ctx); \
return; \
} \
+ gen_set_access_type(ACCESS_FLOAT); \
gen_addr_reg_index(cpu_T[0], ctx); \
tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
op_ldst(st##width); \
{
/* XXX: specification says this is treated as a load by the MMU */
TCGv t0 = tcg_temp_new();
+ gen_set_access_type(ACCESS_CACHE);
gen_addr_reg_index(t0, ctx);
gen_qemu_ld8u(t0, t0, ctx->mem_idx);
tcg_temp_free(t0);
return;
}
EA = tcg_temp_new();
+ gen_set_access_type(ACCESS_CACHE);
gen_addr_reg_index(EA, ctx);
val = tcg_temp_new();
/* XXX: specification says this should be treated as a store by the MMU */
{
/* XXX: specification say this is treated as a load by the MMU */
TCGv t0 = tcg_temp_new();
+ gen_set_access_type(ACCESS_CACHE);
gen_addr_reg_index(t0, ctx);
gen_qemu_ld8u(t0, t0, ctx->mem_idx);
tcg_temp_free(t0);
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
{
/* Should check EAR[E] & alignment ! */
+ gen_set_access_type(ACCESS_RES);
gen_addr_reg_index(cpu_T[0], ctx);
op_eciwx();
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
return;
}
EA = tcg_temp_new();
+ gen_set_access_type(ACCESS_CACHE);
gen_addr_reg_index(EA, ctx);
val = tcg_temp_new();
gen_qemu_ld32u(val, EA, ctx->mem_idx);
void gen_pc_load(CPUState *env, TranslationBlock *tb,
unsigned long searched_pc, int pc_pos, void *puc)
{
- int type, c;
- /* for PPC, we need to look at the micro operation to get the
- * access type */
env->nip = gen_opc_pc[pc_pos];
- c = gen_opc_buf[pc_pos];
- switch(c) {
-#if defined(CONFIG_USER_ONLY)
-#define CASE3(op)\
- case INDEX_op_ ## op ## _raw
-#else
-#define CASE3(op)\
- case INDEX_op_ ## op ## _user:\
- case INDEX_op_ ## op ## _kernel:\
- case INDEX_op_ ## op ## _hypv
-#endif
-
- CASE3(stfd):
- CASE3(stfs):
- CASE3(lfd):
- CASE3(lfs):
- type = ACCESS_FLOAT;
- break;
- CASE3(lwarx):
- type = ACCESS_RES;
- break;
- CASE3(stwcx):
- type = ACCESS_RES;
- break;
- CASE3(eciwx):
- CASE3(ecowx):
- type = ACCESS_EXT;
- break;
- default:
- type = ACCESS_INT;
- break;
- }
- env->access_type = type;
}