diff options
-rw-r--r-- | target-ppc/cpu.h | 3 | ||||
-rw-r--r-- | target-ppc/helper.c | 60 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 8 | ||||
-rw-r--r-- | target-ppc/translate.c | 23 |
4 files changed, 74 insertions, 20 deletions
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index fba5a8fec2..d6feb88bb4 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -716,7 +716,8 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value); #if defined(TARGET_PPC64) void ppc_store_asr (CPUPPCState *env, target_ulong value); target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr); -void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs); +target_ulong ppc_load_sr (CPUPPCState *env, int sr_nr); +void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs); #endif /* defined(TARGET_PPC64) */ void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value); #endif /* !defined(CONFIG_USER_ONLY) */ diff --git a/target-ppc/helper.c b/target-ppc/helper.c index e02dcb03d9..cc471969a2 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -821,27 +821,34 @@ target_ulong ppc_load_slb (CPUPPCState *env, int slb_nr) return rt; } -void ppc_store_slb (CPUPPCState *env, int slb_nr, target_ulong rs) +void ppc_store_slb (CPUPPCState *env, target_ulong rb, target_ulong rs) { target_phys_addr_t sr_base; uint64_t tmp64; uint32_t tmp; + uint64_t vsid; + uint64_t esid; + int flags, valid, slb_nr; + + vsid = rs >> 12; + flags = ((rs >> 8) & 0xf); + + esid = rb >> 28; + valid = (rb & (1 << 27)); + slb_nr = rb & 0xfff; + + tmp64 = (esid << 28) | valid | (vsid >> 24); + tmp = (vsid << 8) | (flags << 3); + + /* Write SLB entry to memory */ sr_base = env->spr[SPR_ASR]; sr_base += 12 * slb_nr; - /* Copy Rs bits 37:63 to SLB 62:88 */ - tmp = rs << 8; - tmp64 = (rs >> 24) & 0x7; - /* Copy Rs bits 33:36 to SLB 89:92 */ - tmp |= ((rs >> 27) & 0xF) << 4; - /* Set the valid bit */ - tmp64 |= 1 << 27; - /* Set ESID */ - tmp64 |= (uint32_t)slb_nr << 28; - LOG_SLB("%s: %d " ADDRX " => " PADDRX " %016" PRIx64 + + LOG_SLB("%s: %d " ADDRX " - " ADDRX " => " PADDRX " %016" PRIx64 " %08" PRIx32 "\n", __func__, - slb_nr, rs, sr_base, tmp64, tmp); - /* Write SLB entry to memory */ + slb_nr, rb, rs, sr_base, tmp64, tmp); + stq_phys(sr_base, tmp64); stl_phys(sr_base + 8, tmp); } @@ -1945,10 +1952,37 @@ void ppc_store_sdr1 (CPUPPCState *env, target_ulong value) } } +#if defined(TARGET_PPC64) +target_ulong ppc_load_sr (CPUPPCState *env, int slb_nr) +{ + // XXX + return 0; +} +#endif + void ppc_store_sr (CPUPPCState *env, int srnum, target_ulong value) { LOG_MMU("%s: reg=%d " ADDRX " " ADDRX "\n", __func__, srnum, value, env->sr[srnum]); +#if defined(TARGET_PPC64) + if (env->mmu_model & POWERPC_MMU_64) { + uint64_t rb = 0, rs = 0; + + /* ESID = srnum */ + rb |= ((uint32_t)srnum & 0xf) << 28; + /* Set the valid bit */ + rb |= 1 << 27; + /* Index = ESID */ + rb |= (uint32_t)srnum; + + /* VSID = VSID */ + rs |= (value & 0xfffffff) << 12; + /* flags = flags */ + rs |= ((value >> 27) & 0xf) << 9; + + ppc_store_slb(env, rb, rs); + } else +#endif if (env->sr[srnum] != value) { env->sr[srnum] = value; #if !defined(FLUSH_ALL_TLBS) && 0 diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 3afd217bc2..76fe8f6f8c 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -3752,6 +3752,10 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) /* Segment registers load and store */ target_ulong helper_load_sr (target_ulong sr_num) { +#if defined(TARGET_PPC64) + if (env->mmu_model & POWERPC_MMU_64) + return ppc_load_sr(env, sr_num); +#endif return env->sr[sr_num]; } @@ -3767,9 +3771,9 @@ target_ulong helper_load_slb (target_ulong slb_nr) return ppc_load_slb(env, slb_nr); } -void helper_store_slb (target_ulong slb_nr, target_ulong rs) +void helper_store_slb (target_ulong rb, target_ulong rs) { - ppc_store_slb(env, slb_nr, rs); + ppc_store_slb(env, rb, rs); } void helper_slbia (void) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 6816e0867d..cbf1a35899 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -4300,7 +4300,7 @@ GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B) return; } t0 = tcg_const_tl(SR(ctx->opcode)); - gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0); + gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); #endif } @@ -4320,7 +4320,7 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001, t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); tcg_gen_andi_tl(t0, t0, 0xF); - gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0); + gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0); tcg_temp_free(t0); #endif } @@ -4337,7 +4337,7 @@ GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B) return; } t0 = tcg_const_tl(SR(ctx->opcode)); - gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]); + gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]); tcg_temp_free(t0); #endif } @@ -4357,10 +4357,25 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, t0 = tcg_temp_new(); tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); tcg_gen_andi_tl(t0, t0, 0xF); - gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]); + gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]); tcg_temp_free(t0); #endif } + +/* slbmte */ +GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B) +{ +#if defined(CONFIG_USER_ONLY) + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); +#else + if (unlikely(!ctx->mem_idx)) { + gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG); + return; + } + gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); +#endif +} + #endif /* defined(TARGET_PPC64) */ /*** Lookaside buffer management ***/ |