From 74d37793f4ea5f30ed6c0af6c449a204dacd8b44 Mon Sep 17 00:00:00 2001 From: aurel32 Date: Sat, 6 Dec 2008 21:46:17 +0000 Subject: [PATCH] target-ppc: convert SLB/TLB instructions to TCG Signed-off-by: Aurelien Jarno git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5895 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-ppc/cpu.h | 2 +- target-ppc/helper.c | 7 -- target-ppc/helper.h | 26 ++++- target-ppc/op.c | 150 ----------------------------- target-ppc/op_helper.c | 211 ++++++++++++++++++++++++++--------------- target-ppc/op_helper.h | 14 --- target-ppc/translate.c | 194 +++++++++++++++++++++---------------- 7 files changed, 272 insertions(+), 332 deletions(-) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 8f7309b372..3911f28f2d 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -582,7 +582,7 @@ struct CPUPPCState { #endif /* segment registers */ target_ulong sdr1; - target_ulong sr[16]; + target_ulong sr[32]; /* BATs */ int nb_BATs; target_ulong DBAT[2][8]; diff --git a/target-ppc/helper.c b/target-ppc/helper.c index 15ff5ccd44..2678dd61e2 100644 --- a/target-ppc/helper.c +++ b/target-ppc/helper.c @@ -2110,13 +2110,6 @@ void do_store_sdr1 (CPUPPCState *env, target_ulong value) } } -#if 0 // Unused -target_ulong do_load_sr (CPUPPCState *env, int srnum) -{ - return env->sr[srnum]; -} -#endif - void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) { #if defined (DEBUG_MMU) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 1e2bd57e5a..5b2607853a 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -163,10 +163,28 @@ DEF_HELPER_2(efdcmpgt, i32, i64, i64) DEF_HELPER_2(efdcmpeq, i32, i64, i64) #if !defined(CONFIG_USER_ONLY) -DEF_HELPER_1(load_6xx_tlbd, void, tl) -DEF_HELPER_1(load_6xx_tlbi, void, tl) -DEF_HELPER_1(load_74xx_tlbd, void, tl) -DEF_HELPER_1(load_74xx_tlbi, void, tl) +DEF_HELPER_1(4xx_tlbre_hi, tl, tl) +DEF_HELPER_1(4xx_tlbre_lo, tl, tl) +DEF_HELPER_2(4xx_tlbwe_hi, void, tl, tl) +DEF_HELPER_2(4xx_tlbwe_lo, void, tl, tl) +DEF_HELPER_1(4xx_tlbsx, tl, tl) +DEF_HELPER_2(440_tlbre, tl, i32, tl) +DEF_HELPER_3(440_tlbwe, void, i32, tl, tl) +DEF_HELPER_1(440_tlbsx, tl, tl) +DEF_HELPER_1(6xx_tlbd, void, tl) +DEF_HELPER_1(6xx_tlbi, void, tl) +DEF_HELPER_1(74xx_tlbd, void, tl) +DEF_HELPER_1(74xx_tlbi, void, tl) +DEF_HELPER_0(tlbia, void) +DEF_HELPER_1(tlbie, void, tl) +#if defined(TARGET_PPC64) +DEF_HELPER_1(load_slb, tl, tl) +DEF_HELPER_2(store_slb, void, tl, tl) +DEF_HELPER_0(slbia, void) +DEF_HELPER_1(slbie, void, tl) +#endif +DEF_HELPER_1(load_sr, tl, tl); +DEF_HELPER_2(store_sr, void, tl, tl); DEF_HELPER_1(602_mfrom, tl, tl) #endif diff --git a/target-ppc/op.c b/target-ppc/op.c index 4a546781f3..868db83779 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -27,33 +27,6 @@ #include "op_helper.h" #if !defined(CONFIG_USER_ONLY) -/* Segment registers load and store */ -void OPPROTO op_load_sr (void) -{ - T0 = env->sr[T1]; - RETURN(); -} - -void OPPROTO op_store_sr (void) -{ - do_store_sr(env, T1, T0); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_load_slb (void) -{ - T0 = ppc_load_slb(env, T1); - RETURN(); -} - -void OPPROTO op_store_slb (void) -{ - ppc_store_slb(env, T1, T0); - RETURN(); -} -#endif /* defined(TARGET_PPC64) */ - void OPPROTO op_load_sdr1 (void) { T0 = env->sdr1; @@ -218,13 +191,6 @@ void OPPROTO op_store_dbatl (void) } #endif /* !defined(CONFIG_USER_ONLY) */ -/*** Integer shift ***/ -void OPPROTO op_srli_T1 (void) -{ - T1 = (uint32_t)T1 >> PARAM1; - RETURN(); -} - /* Return from interrupt */ #if !defined(CONFIG_USER_ONLY) /* Exception vectors */ @@ -243,50 +209,6 @@ void OPPROTO op_store_excp_vector (void) } #endif -#if !defined(CONFIG_USER_ONLY) -/* tlbia */ -void OPPROTO op_tlbia (void) -{ - ppc_tlb_invalidate_all(env); - RETURN(); -} - -/* tlbie */ -void OPPROTO op_tlbie (void) -{ - ppc_tlb_invalidate_one(env, (uint32_t)T0); - RETURN(); -} - -#if defined(TARGET_PPC64) -void OPPROTO op_tlbie_64 (void) -{ - ppc_tlb_invalidate_one(env, T0); - RETURN(); -} -#endif - -#if defined(TARGET_PPC64) -void OPPROTO op_slbia (void) -{ - ppc_slb_invalidate_all(env); - RETURN(); -} - -void OPPROTO op_slbie (void) -{ - ppc_slb_invalidate_one(env, (uint32_t)T0); - RETURN(); -} - -void OPPROTO op_slbie_64 (void) -{ - ppc_slb_invalidate_one(env, T0); - RETURN(); -} -#endif -#endif - /* 601 specific */ void OPPROTO op_load_601_rtcl (void) { @@ -338,78 +260,6 @@ void OPPROTO op_store_601_batu (void) } #endif /* !defined(CONFIG_USER_ONLY) */ -/* POWER instructions not implemented in PowerPC 601 */ -#if !defined(CONFIG_USER_ONLY) -void OPPROTO op_POWER_mfsri (void) -{ - T1 = T0 >> 28; - T0 = env->sr[T1]; - RETURN(); -} -#endif - -/* PowerPC 4xx specific micro-ops */ -#if !defined(CONFIG_USER_ONLY) -void OPPROTO op_440_tlbre (void) -{ - do_440_tlbre(PARAM1); - RETURN(); -} - -void OPPROTO op_440_tlbsx (void) -{ - T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF); - RETURN(); -} - -void OPPROTO op_4xx_tlbsx_check (void) -{ - int tmp; - - tmp = xer_so; - if ((int)T0 != -1) - tmp |= 0x02; - env->crf[0] = tmp; - RETURN(); -} - -void OPPROTO op_440_tlbwe (void) -{ - do_440_tlbwe(PARAM1); - RETURN(); -} - -void OPPROTO op_4xx_tlbre_lo (void) -{ - do_4xx_tlbre_lo(); - RETURN(); -} - -void OPPROTO op_4xx_tlbre_hi (void) -{ - do_4xx_tlbre_hi(); - RETURN(); -} - -void OPPROTO op_4xx_tlbsx (void) -{ - T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]); - RETURN(); -} - -void OPPROTO op_4xx_tlbwe_lo (void) -{ - do_4xx_tlbwe_lo(); - RETURN(); -} - -void OPPROTO op_4xx_tlbwe_hi (void) -{ - do_4xx_tlbwe_hi(); - RETURN(); -} -#endif - /* SPR micro-ops */ /* 440 specific */ #if !defined(CONFIG_USER_ONLY) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index 8c9b804716..a4dc41d0c4 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -2552,9 +2552,55 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) env = saved_env; } +/* Segment registers load and store */ +target_ulong helper_load_sr (target_ulong sr_num) +{ + return env->sr[sr_num]; +} + +void helper_store_sr (target_ulong sr_num, target_ulong val) +{ + do_store_sr(env, sr_num, val); +} + +/* SLB management */ +#if defined(TARGET_PPC64) +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) +{ + ppc_store_slb(env, slb_nr, rs); +} + +void helper_slbia (void) +{ + ppc_slb_invalidate_all(env); +} + +void helper_slbie (target_ulong addr) +{ + ppc_slb_invalidate_one(env, addr); +} + +#endif /* defined(TARGET_PPC64) */ + +/* TLB management */ +void helper_tlbia (void) +{ + ppc_tlb_invalidate_all(env); +} + +void helper_tlbie (target_ulong addr) +{ + ppc_tlb_invalidate_one(env, addr); +} + /* Software driven TLBs management */ /* PowerPC 602/603 software TLB load instructions helpers */ -static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code) +static void do_6xx_tlb (target_ulong new_EPN, int is_code) { target_ulong RPN, CMP, EPN; int way; @@ -2580,18 +2626,18 @@ static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code) way, is_code, CMP, RPN); } -void helper_load_6xx_tlbd (target_ulong EPN) +void helper_6xx_tlbd (target_ulong EPN) { - helper_load_6xx_tlb(EPN, 0); + do_6xx_tlb(EPN, 0); } -void helper_load_6xx_tlbi (target_ulong EPN) +void helper_6xx_tlbi (target_ulong EPN) { - helper_load_6xx_tlb(EPN, 1); + do_6xx_tlb(EPN, 1); } /* PowerPC 74xx software TLB load instructions helpers */ -static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code) +static void do_74xx_tlb (target_ulong new_EPN, int is_code) { target_ulong RPN, CMP, EPN; int way; @@ -2612,14 +2658,14 @@ static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code) way, is_code, CMP, RPN); } -void helper_load_74xx_tlbd (target_ulong EPN) +void helper_74xx_tlbd (target_ulong EPN) { - helper_load_74xx_tlb(EPN, 0); + do_74xx_tlb(EPN, 0); } -void helper_load_74xx_tlbi (target_ulong EPN) +void helper_74xx_tlbi (target_ulong EPN) { - helper_load_74xx_tlb(EPN, 1); + do_74xx_tlb(EPN, 1); } static always_inline target_ulong booke_tlb_to_page_size (int size) @@ -2691,81 +2737,85 @@ static always_inline int booke_page_size_to_tlb (target_ulong page_size) } /* Helpers for 4xx TLB management */ -void do_4xx_tlbre_lo (void) +target_ulong helper_4xx_tlbre_lo (target_ulong entry) { ppcemb_tlb_t *tlb; + target_ulong ret; int size; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; - T0 = tlb->EPN; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; + ret = tlb->EPN; if (tlb->prot & PAGE_VALID) - T0 |= 0x400; + ret |= 0x400; size = booke_page_size_to_tlb(tlb->size); if (size < 0 || size > 0x7) size = 1; - T0 |= size << 7; + ret |= size << 7; env->spr[SPR_40x_PID] = tlb->PID; + return ret; } -void do_4xx_tlbre_hi (void) +target_ulong helper_4xx_tlbre_hi (target_ulong entry) { ppcemb_tlb_t *tlb; + target_ulong ret; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; - T0 = tlb->RPN; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; + ret = tlb->RPN; if (tlb->prot & PAGE_EXEC) - T0 |= 0x200; + ret |= 0x200; if (tlb->prot & PAGE_WRITE) - T0 |= 0x100; + ret |= 0x100; + return ret; } -void do_4xx_tlbwe_hi (void) +void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val) { ppcemb_tlb_t *tlb; target_ulong page, end; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1); + fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val); } #endif - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; /* Invalidate previous TLB (if it's valid) */ if (tlb->prot & PAGE_VALID) { end = tlb->EPN + tlb->size; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX - " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end); + " end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end); } #endif for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) tlb_flush_page(env, page); } - tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7); + tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7); /* We cannot handle TLB size < TARGET_PAGE_SIZE. * If this ever occurs, one should use the ppcemb target instead * of the ppc or ppc64 one */ - if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) { + if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) { cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u " "are not supported (%d)\n", - tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7)); + tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); } - tlb->EPN = T1 & ~(tlb->size - 1); - if (T1 & 0x40) + tlb->EPN = val & ~(tlb->size - 1); + if (val & 0x40) tlb->prot |= PAGE_VALID; else tlb->prot &= ~PAGE_VALID; - if (T1 & 0x20) { + if (val & 0x20) { /* XXX: TO BE FIXED */ cpu_abort(env, "Little-endian TLB entries are not supported by now\n"); } tlb->PID = env->spr[SPR_40x_PID]; /* PID */ - tlb->attr = T1 & 0xFF; + tlb->attr = val & 0xFF; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX @@ -2791,28 +2841,28 @@ void do_4xx_tlbwe_hi (void) } } -void do_4xx_tlbwe_lo (void) +void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val) { ppcemb_tlb_t *tlb; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1); + fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val); } #endif - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; - tlb->RPN = T1 & 0xFFFFFC00; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; + tlb->RPN = val & 0xFFFFFC00; tlb->prot = PAGE_READ; - if (T1 & 0x200) + if (val & 0x200) tlb->prot |= PAGE_EXEC; - if (T1 & 0x100) + if (val & 0x100) tlb->prot |= PAGE_WRITE; #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX " size " ADDRX " prot %c%c%c%c PID %d\n", __func__, - (int)T0, tlb->RPN, tlb->EPN, tlb->size, + (int)entry, tlb->RPN, tlb->EPN, tlb->size, tlb->prot & PAGE_READ ? 'r' : '-', tlb->prot & PAGE_WRITE ? 'w' : '-', tlb->prot & PAGE_EXEC ? 'x' : '-', @@ -2821,8 +2871,13 @@ void do_4xx_tlbwe_lo (void) #endif } +target_ulong helper_4xx_tlbsx (target_ulong address) +{ + return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]); +} + /* PowerPC 440 TLB management */ -void do_440_tlbwe (int word) +void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value) { ppcemb_tlb_t *tlb; target_ulong EPN, RPN, size; @@ -2830,28 +2885,28 @@ void do_440_tlbwe (int word) #if defined (DEBUG_SOFTWARE_TLB) if (loglevel != 0) { - fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n", - __func__, word, T0, T1); + fprintf(logfile, "%s word %d entry " TDX " value " TDX "\n", + __func__, word, entry, value); } #endif do_flush_tlbs = 0; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; switch (word) { default: /* Just here to please gcc */ case 0: - EPN = T1 & 0xFFFFFC00; + EPN = value & 0xFFFFFC00; if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) do_flush_tlbs = 1; tlb->EPN = EPN; - size = booke_tlb_to_page_size((T1 >> 4) & 0xF); + size = booke_tlb_to_page_size((value >> 4) & 0xF); if ((tlb->prot & PAGE_VALID) && tlb->size < size) do_flush_tlbs = 1; tlb->size = size; tlb->attr &= ~0x1; - tlb->attr |= (T1 >> 8) & 1; - if (T1 & 0x200) { + tlb->attr |= (value >> 8) & 1; + if (value & 0x200) { tlb->prot |= PAGE_VALID; } else { if (tlb->prot & PAGE_VALID) { @@ -2864,71 +2919,79 @@ void do_440_tlbwe (int word) tlb_flush(env, 1); break; case 1: - RPN = T1 & 0xFFFFFC0F; + RPN = value & 0xFFFFFC0F; if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) tlb_flush(env, 1); tlb->RPN = RPN; break; case 2: - tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00); + tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00); tlb->prot = tlb->prot & PAGE_VALID; - if (T1 & 0x1) + if (value & 0x1) tlb->prot |= PAGE_READ << 4; - if (T1 & 0x2) + if (value & 0x2) tlb->prot |= PAGE_WRITE << 4; - if (T1 & 0x4) + if (value & 0x4) tlb->prot |= PAGE_EXEC << 4; - if (T1 & 0x8) + if (value & 0x8) tlb->prot |= PAGE_READ; - if (T1 & 0x10) + if (value & 0x10) tlb->prot |= PAGE_WRITE; - if (T1 & 0x20) + if (value & 0x20) tlb->prot |= PAGE_EXEC; break; } } -void do_440_tlbre (int word) +target_ulong helper_440_tlbre (uint32_t word, target_ulong entry) { ppcemb_tlb_t *tlb; + target_ulong ret; int size; - T0 &= 0x3F; - tlb = &env->tlb[T0].tlbe; + entry &= 0x3F; + tlb = &env->tlb[entry].tlbe; switch (word) { default: /* Just here to please gcc */ case 0: - T0 = tlb->EPN; + ret = tlb->EPN; size = booke_page_size_to_tlb(tlb->size); if (size < 0 || size > 0xF) size = 1; - T0 |= size << 4; + ret |= size << 4; if (tlb->attr & 0x1) - T0 |= 0x100; + ret |= 0x100; if (tlb->prot & PAGE_VALID) - T0 |= 0x200; + ret |= 0x200; env->spr[SPR_440_MMUCR] &= ~0x000000FF; env->spr[SPR_440_MMUCR] |= tlb->PID; break; case 1: - T0 = tlb->RPN; + ret = tlb->RPN; break; case 2: - T0 = tlb->attr & ~0x1; + ret = tlb->attr & ~0x1; if (tlb->prot & (PAGE_READ << 4)) - T0 |= 0x1; + ret |= 0x1; if (tlb->prot & (PAGE_WRITE << 4)) - T0 |= 0x2; + ret |= 0x2; if (tlb->prot & (PAGE_EXEC << 4)) - T0 |= 0x4; + ret |= 0x4; if (tlb->prot & PAGE_READ) - T0 |= 0x8; + ret |= 0x8; if (tlb->prot & PAGE_WRITE) - T0 |= 0x10; + ret |= 0x10; if (tlb->prot & PAGE_EXEC) - T0 |= 0x20; + ret |= 0x20; break; } + return ret; } + +target_ulong helper_440_tlbsx (target_ulong address) +{ + return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF); +} + #endif /* !CONFIG_USER_ONLY */ diff --git a/target-ppc/op_helper.h b/target-ppc/op_helper.h index 098695e291..1de35a1b0b 100644 --- a/target-ppc/op_helper.h +++ b/target-ppc/op_helper.h @@ -34,20 +34,6 @@ void do_POWER_rac (void); void do_store_hid0_601 (void); #endif -/* PowerPC 440 specific helpers */ -#if !defined(CONFIG_USER_ONLY) -void do_440_tlbre (int word); -void do_440_tlbwe (int word); -#endif - -/* PowerPC 4xx specific helpers */ -#if !defined(CONFIG_USER_ONLY) -void do_4xx_tlbre_lo (void); -void do_4xx_tlbre_hi (void); -void do_4xx_tlbwe_lo (void); -void do_4xx_tlbwe_hi (void); -#endif - /* PowerPC 403 specific helpers */ #if !defined(CONFIG_USER_ONLY) void do_load_403_pb (int num); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 8a96afe5d8..e486c2316e 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -4208,13 +4208,14 @@ GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode)); - gen_op_load_sr(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + t0 = tcg_const_tl(SR(ctx->opcode)); + gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0); + tcg_temp_free(t0); #endif } @@ -4224,14 +4225,16 @@ GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_srli_T1(28); - gen_op_load_sr(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + 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_sr(cpu_gpr[rD(ctx->opcode)], t0); + tcg_temp_free(t0); #endif } @@ -4241,13 +4244,14 @@ GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode)); - gen_op_store_sr(); + t0 = tcg_const_tl(SR(ctx->opcode)); + gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]); + tcg_temp_free(t0); #endif } @@ -4257,14 +4261,16 @@ GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_srli_T1(28); - gen_op_store_sr(); + 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_sr(t0, cpu_gpr[rD(ctx->opcode)]); + tcg_temp_free(t0); #endif } @@ -4276,13 +4282,14 @@ GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode)); - gen_op_load_slb(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + t0 = tcg_const_tl(SR(ctx->opcode)); + gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0); + tcg_temp_free(t0); #endif } @@ -4293,14 +4300,16 @@ GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001, #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_srli_T1(28); - gen_op_load_slb(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + 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); + tcg_temp_free(t0); #endif } @@ -4310,13 +4319,14 @@ GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode)); - gen_op_store_slb(); + t0 = tcg_const_tl(SR(ctx->opcode)); + gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]); + tcg_temp_free(t0); #endif } @@ -4327,14 +4337,16 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001, #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVREG(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVREG(ctx); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); - gen_op_srli_T1(28); - gen_op_store_slb(); + 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)]); + tcg_temp_free(t0); #endif } #endif /* defined(TARGET_PPC64) */ @@ -4351,7 +4363,7 @@ GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA) GEN_EXCP_PRIVOPC(ctx); return; } - gen_op_tlbia(); + gen_helper_tlbia(); #endif } @@ -4365,13 +4377,15 @@ GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE) GEN_EXCP_PRIVOPC(ctx); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]); #if defined(TARGET_PPC64) - if (ctx->sf_mode) - gen_op_tlbie_64(); - else + if (!ctx->sf_mode) { + TCGv t0 = tcg_temp_new(); + tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]); + gen_helper_tlbie(t0); + tcg_temp_free(t0); + } else #endif - gen_op_tlbie(); + gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]); #endif } @@ -4403,7 +4417,7 @@ GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI) GEN_EXCP_PRIVOPC(ctx); return; } - gen_op_slbia(); + gen_helper_slbia(); #endif } @@ -4417,8 +4431,7 @@ GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI) GEN_EXCP_PRIVOPC(ctx); return; } - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]); - gen_op_slbie(); + gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]); #endif } #endif @@ -5129,7 +5142,7 @@ GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB) GEN_EXCP_PRIVOPC(ctx); return; } - gen_helper_load_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]); + gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]); #endif } @@ -5143,7 +5156,7 @@ GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB) GEN_EXCP_PRIVOPC(ctx); return; } - gen_helper_load_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]); + gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]); #endif } @@ -5158,7 +5171,7 @@ GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB) GEN_EXCP_PRIVOPC(ctx); return; } - gen_helper_load_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]); + gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]); #endif } @@ -5172,7 +5185,7 @@ GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB) GEN_EXCP_PRIVOPC(ctx); return; } - gen_helper_load_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]); + gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]); #endif } @@ -5208,18 +5221,21 @@ GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVOPC(ctx); #else + int ra = rA(ctx->opcode); + int rd = rD(ctx->opcode); + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVOPC(ctx); return; } - int ra = rA(ctx->opcode); - int rd = rD(ctx->opcode); - - gen_addr_reg_index(cpu_T[0], ctx); - gen_op_POWER_mfsri(); - tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]); + t0 = tcg_temp_new(); + gen_addr_reg_index(t0, ctx); + tcg_gen_shri_tl(t0, t0, 28); + tcg_gen_andi_tl(t0, t0, 0xF); + gen_helper_load_sr(cpu_gpr[rd], t0); + tcg_temp_free(t0); if (ra != 0 && ra != rd) - tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]); + tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]); #endif } @@ -5389,18 +5405,18 @@ GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVOPC(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVOPC(ctx); return; } - gen_addr_reg_index(cpu_T[0], ctx); - /* Use the same micro-ops as for tlbie */ + gen_addr_reg_index(t0, ctx); #if defined(TARGET_PPC64) - if (ctx->sf_mode) - gen_op_tlbie_64(); - else + if (!ctx->sf_mode) + tcg_gen_ext32u_tl(t0, t0); #endif - gen_op_tlbie(); + gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]); + tcg_temp_free(t0); #endif } @@ -5861,14 +5877,10 @@ GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB) } switch (rB(ctx->opcode)) { case 0: - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); - gen_op_4xx_tlbre_hi(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); break; case 1: - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); - gen_op_4xx_tlbre_lo(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); break; default: GEN_EXCP_INVAL(ctx); @@ -5883,15 +5895,24 @@ GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVOPC(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVOPC(ctx); return; } - gen_addr_reg_index(cpu_T[0], ctx); - gen_op_4xx_tlbsx(); - if (Rc(ctx->opcode)) - gen_op_4xx_tlbsx_check(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + t0 = tcg_temp_new(); + gen_addr_reg_index(t0, ctx); + gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0); + tcg_temp_free(t0); + if (Rc(ctx->opcode)) { + int l1 = gen_new_label(); + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); + tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); + tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1); + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); + gen_set_label(l1); + } #endif } @@ -5907,14 +5928,10 @@ GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB) } switch (rB(ctx->opcode)) { case 0: - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); - gen_op_4xx_tlbwe_hi(); + gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); break; case 1: - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); - gen_op_4xx_tlbwe_lo(); + gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); break; default: GEN_EXCP_INVAL(ctx); @@ -5938,9 +5955,11 @@ GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE) case 0: case 1: case 2: - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); - gen_op_440_tlbre(rB(ctx->opcode)); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + { + TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode)); + gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); + tcg_temp_free_i32(t0); + } break; default: GEN_EXCP_INVAL(ctx); @@ -5955,15 +5974,24 @@ GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE) #if defined(CONFIG_USER_ONLY) GEN_EXCP_PRIVOPC(ctx); #else + TCGv t0; if (unlikely(!ctx->supervisor)) { GEN_EXCP_PRIVOPC(ctx); return; } - gen_addr_reg_index(cpu_T[0], ctx); - gen_op_440_tlbsx(); - if (Rc(ctx->opcode)) - gen_op_4xx_tlbsx_check(); - tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); + t0 = tcg_temp_new(); + gen_addr_reg_index(t0, ctx); + gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0); + tcg_temp_free(t0); + if (Rc(ctx->opcode)) { + int l1 = gen_new_label(); + tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); + tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); + tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); + tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1); + tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); + gen_set_label(l1); + } #endif } @@ -5981,9 +6009,11 @@ GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE) case 0: case 1: case 2: - tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); - tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); - gen_op_440_tlbwe(rB(ctx->opcode)); + { + TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode)); + gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); + tcg_temp_free_i32(t0); + } break; default: GEN_EXCP_INVAL(ctx);