aboutsummaryrefslogtreecommitdiff
path: root/target-ppc/op_helper.c
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-06 21:46:17 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-12-06 21:46:17 +0000
commit74d37793f4ea5f30ed6c0af6c449a204dacd8b44 (patch)
tree2af7cbe375158ea786fa3aa8f2d47974cd989f66 /target-ppc/op_helper.c
parent331dadde1900247ee90547ce51c620432c5a8f79 (diff)
target-ppc: convert SLB/TLB instructions to TCG
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5895 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-ppc/op_helper.c')
-rw-r--r--target-ppc/op_helper.c211
1 files changed, 137 insertions, 74 deletions
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 */