Revision 74d37793
b/target-ppc/cpu.h | ||
---|---|---|
582 | 582 |
#endif |
583 | 583 |
/* segment registers */ |
584 | 584 |
target_ulong sdr1; |
585 |
target_ulong sr[16];
|
|
585 |
target_ulong sr[32];
|
|
586 | 586 |
/* BATs */ |
587 | 587 |
int nb_BATs; |
588 | 588 |
target_ulong DBAT[2][8]; |
b/target-ppc/helper.c | ||
---|---|---|
2110 | 2110 |
} |
2111 | 2111 |
} |
2112 | 2112 |
|
2113 |
#if 0 // Unused |
|
2114 |
target_ulong do_load_sr (CPUPPCState *env, int srnum) |
|
2115 |
{ |
|
2116 |
return env->sr[srnum]; |
|
2117 |
} |
|
2118 |
#endif |
|
2119 |
|
|
2120 | 2113 |
void do_store_sr (CPUPPCState *env, int srnum, target_ulong value) |
2121 | 2114 |
{ |
2122 | 2115 |
#if defined (DEBUG_MMU) |
b/target-ppc/helper.h | ||
---|---|---|
163 | 163 |
DEF_HELPER_2(efdcmpeq, i32, i64, i64) |
164 | 164 |
|
165 | 165 |
#if !defined(CONFIG_USER_ONLY) |
166 |
DEF_HELPER_1(load_6xx_tlbd, void, tl) |
|
167 |
DEF_HELPER_1(load_6xx_tlbi, void, tl) |
|
168 |
DEF_HELPER_1(load_74xx_tlbd, void, tl) |
|
169 |
DEF_HELPER_1(load_74xx_tlbi, void, tl) |
|
166 |
DEF_HELPER_1(4xx_tlbre_hi, tl, tl) |
|
167 |
DEF_HELPER_1(4xx_tlbre_lo, tl, tl) |
|
168 |
DEF_HELPER_2(4xx_tlbwe_hi, void, tl, tl) |
|
169 |
DEF_HELPER_2(4xx_tlbwe_lo, void, tl, tl) |
|
170 |
DEF_HELPER_1(4xx_tlbsx, tl, tl) |
|
171 |
DEF_HELPER_2(440_tlbre, tl, i32, tl) |
|
172 |
DEF_HELPER_3(440_tlbwe, void, i32, tl, tl) |
|
173 |
DEF_HELPER_1(440_tlbsx, tl, tl) |
|
174 |
DEF_HELPER_1(6xx_tlbd, void, tl) |
|
175 |
DEF_HELPER_1(6xx_tlbi, void, tl) |
|
176 |
DEF_HELPER_1(74xx_tlbd, void, tl) |
|
177 |
DEF_HELPER_1(74xx_tlbi, void, tl) |
|
178 |
DEF_HELPER_0(tlbia, void) |
|
179 |
DEF_HELPER_1(tlbie, void, tl) |
|
180 |
#if defined(TARGET_PPC64) |
|
181 |
DEF_HELPER_1(load_slb, tl, tl) |
|
182 |
DEF_HELPER_2(store_slb, void, tl, tl) |
|
183 |
DEF_HELPER_0(slbia, void) |
|
184 |
DEF_HELPER_1(slbie, void, tl) |
|
185 |
#endif |
|
186 |
DEF_HELPER_1(load_sr, tl, tl); |
|
187 |
DEF_HELPER_2(store_sr, void, tl, tl); |
|
170 | 188 |
|
171 | 189 |
DEF_HELPER_1(602_mfrom, tl, tl) |
172 | 190 |
#endif |
b/target-ppc/op.c | ||
---|---|---|
27 | 27 |
#include "op_helper.h" |
28 | 28 |
|
29 | 29 |
#if !defined(CONFIG_USER_ONLY) |
30 |
/* Segment registers load and store */ |
|
31 |
void OPPROTO op_load_sr (void) |
|
32 |
{ |
|
33 |
T0 = env->sr[T1]; |
|
34 |
RETURN(); |
|
35 |
} |
|
36 |
|
|
37 |
void OPPROTO op_store_sr (void) |
|
38 |
{ |
|
39 |
do_store_sr(env, T1, T0); |
|
40 |
RETURN(); |
|
41 |
} |
|
42 |
|
|
43 |
#if defined(TARGET_PPC64) |
|
44 |
void OPPROTO op_load_slb (void) |
|
45 |
{ |
|
46 |
T0 = ppc_load_slb(env, T1); |
|
47 |
RETURN(); |
|
48 |
} |
|
49 |
|
|
50 |
void OPPROTO op_store_slb (void) |
|
51 |
{ |
|
52 |
ppc_store_slb(env, T1, T0); |
|
53 |
RETURN(); |
|
54 |
} |
|
55 |
#endif /* defined(TARGET_PPC64) */ |
|
56 |
|
|
57 | 30 |
void OPPROTO op_load_sdr1 (void) |
58 | 31 |
{ |
59 | 32 |
T0 = env->sdr1; |
... | ... | |
218 | 191 |
} |
219 | 192 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
220 | 193 |
|
221 |
/*** Integer shift ***/ |
|
222 |
void OPPROTO op_srli_T1 (void) |
|
223 |
{ |
|
224 |
T1 = (uint32_t)T1 >> PARAM1; |
|
225 |
RETURN(); |
|
226 |
} |
|
227 |
|
|
228 | 194 |
/* Return from interrupt */ |
229 | 195 |
#if !defined(CONFIG_USER_ONLY) |
230 | 196 |
/* Exception vectors */ |
... | ... | |
243 | 209 |
} |
244 | 210 |
#endif |
245 | 211 |
|
246 |
#if !defined(CONFIG_USER_ONLY) |
|
247 |
/* tlbia */ |
|
248 |
void OPPROTO op_tlbia (void) |
|
249 |
{ |
|
250 |
ppc_tlb_invalidate_all(env); |
|
251 |
RETURN(); |
|
252 |
} |
|
253 |
|
|
254 |
/* tlbie */ |
|
255 |
void OPPROTO op_tlbie (void) |
|
256 |
{ |
|
257 |
ppc_tlb_invalidate_one(env, (uint32_t)T0); |
|
258 |
RETURN(); |
|
259 |
} |
|
260 |
|
|
261 |
#if defined(TARGET_PPC64) |
|
262 |
void OPPROTO op_tlbie_64 (void) |
|
263 |
{ |
|
264 |
ppc_tlb_invalidate_one(env, T0); |
|
265 |
RETURN(); |
|
266 |
} |
|
267 |
#endif |
|
268 |
|
|
269 |
#if defined(TARGET_PPC64) |
|
270 |
void OPPROTO op_slbia (void) |
|
271 |
{ |
|
272 |
ppc_slb_invalidate_all(env); |
|
273 |
RETURN(); |
|
274 |
} |
|
275 |
|
|
276 |
void OPPROTO op_slbie (void) |
|
277 |
{ |
|
278 |
ppc_slb_invalidate_one(env, (uint32_t)T0); |
|
279 |
RETURN(); |
|
280 |
} |
|
281 |
|
|
282 |
void OPPROTO op_slbie_64 (void) |
|
283 |
{ |
|
284 |
ppc_slb_invalidate_one(env, T0); |
|
285 |
RETURN(); |
|
286 |
} |
|
287 |
#endif |
|
288 |
#endif |
|
289 |
|
|
290 | 212 |
/* 601 specific */ |
291 | 213 |
void OPPROTO op_load_601_rtcl (void) |
292 | 214 |
{ |
... | ... | |
338 | 260 |
} |
339 | 261 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
340 | 262 |
|
341 |
/* POWER instructions not implemented in PowerPC 601 */ |
|
342 |
#if !defined(CONFIG_USER_ONLY) |
|
343 |
void OPPROTO op_POWER_mfsri (void) |
|
344 |
{ |
|
345 |
T1 = T0 >> 28; |
|
346 |
T0 = env->sr[T1]; |
|
347 |
RETURN(); |
|
348 |
} |
|
349 |
#endif |
|
350 |
|
|
351 |
/* PowerPC 4xx specific micro-ops */ |
|
352 |
#if !defined(CONFIG_USER_ONLY) |
|
353 |
void OPPROTO op_440_tlbre (void) |
|
354 |
{ |
|
355 |
do_440_tlbre(PARAM1); |
|
356 |
RETURN(); |
|
357 |
} |
|
358 |
|
|
359 |
void OPPROTO op_440_tlbsx (void) |
|
360 |
{ |
|
361 |
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_440_MMUCR] & 0xFF); |
|
362 |
RETURN(); |
|
363 |
} |
|
364 |
|
|
365 |
void OPPROTO op_4xx_tlbsx_check (void) |
|
366 |
{ |
|
367 |
int tmp; |
|
368 |
|
|
369 |
tmp = xer_so; |
|
370 |
if ((int)T0 != -1) |
|
371 |
tmp |= 0x02; |
|
372 |
env->crf[0] = tmp; |
|
373 |
RETURN(); |
|
374 |
} |
|
375 |
|
|
376 |
void OPPROTO op_440_tlbwe (void) |
|
377 |
{ |
|
378 |
do_440_tlbwe(PARAM1); |
|
379 |
RETURN(); |
|
380 |
} |
|
381 |
|
|
382 |
void OPPROTO op_4xx_tlbre_lo (void) |
|
383 |
{ |
|
384 |
do_4xx_tlbre_lo(); |
|
385 |
RETURN(); |
|
386 |
} |
|
387 |
|
|
388 |
void OPPROTO op_4xx_tlbre_hi (void) |
|
389 |
{ |
|
390 |
do_4xx_tlbre_hi(); |
|
391 |
RETURN(); |
|
392 |
} |
|
393 |
|
|
394 |
void OPPROTO op_4xx_tlbsx (void) |
|
395 |
{ |
|
396 |
T0 = ppcemb_tlb_search(env, T0, env->spr[SPR_40x_PID]); |
|
397 |
RETURN(); |
|
398 |
} |
|
399 |
|
|
400 |
void OPPROTO op_4xx_tlbwe_lo (void) |
|
401 |
{ |
|
402 |
do_4xx_tlbwe_lo(); |
|
403 |
RETURN(); |
|
404 |
} |
|
405 |
|
|
406 |
void OPPROTO op_4xx_tlbwe_hi (void) |
|
407 |
{ |
|
408 |
do_4xx_tlbwe_hi(); |
|
409 |
RETURN(); |
|
410 |
} |
|
411 |
#endif |
|
412 |
|
|
413 | 263 |
/* SPR micro-ops */ |
414 | 264 |
/* 440 specific */ |
415 | 265 |
#if !defined(CONFIG_USER_ONLY) |
b/target-ppc/op_helper.c | ||
---|---|---|
2552 | 2552 |
env = saved_env; |
2553 | 2553 |
} |
2554 | 2554 |
|
2555 |
/* Segment registers load and store */ |
|
2556 |
target_ulong helper_load_sr (target_ulong sr_num) |
|
2557 |
{ |
|
2558 |
return env->sr[sr_num]; |
|
2559 |
} |
|
2560 |
|
|
2561 |
void helper_store_sr (target_ulong sr_num, target_ulong val) |
|
2562 |
{ |
|
2563 |
do_store_sr(env, sr_num, val); |
|
2564 |
} |
|
2565 |
|
|
2566 |
/* SLB management */ |
|
2567 |
#if defined(TARGET_PPC64) |
|
2568 |
target_ulong helper_load_slb (target_ulong slb_nr) |
|
2569 |
{ |
|
2570 |
return ppc_load_slb(env, slb_nr); |
|
2571 |
} |
|
2572 |
|
|
2573 |
void helper_store_slb (target_ulong slb_nr, target_ulong rs) |
|
2574 |
{ |
|
2575 |
ppc_store_slb(env, slb_nr, rs); |
|
2576 |
} |
|
2577 |
|
|
2578 |
void helper_slbia (void) |
|
2579 |
{ |
|
2580 |
ppc_slb_invalidate_all(env); |
|
2581 |
} |
|
2582 |
|
|
2583 |
void helper_slbie (target_ulong addr) |
|
2584 |
{ |
|
2585 |
ppc_slb_invalidate_one(env, addr); |
|
2586 |
} |
|
2587 |
|
|
2588 |
#endif /* defined(TARGET_PPC64) */ |
|
2589 |
|
|
2590 |
/* TLB management */ |
|
2591 |
void helper_tlbia (void) |
|
2592 |
{ |
|
2593 |
ppc_tlb_invalidate_all(env); |
|
2594 |
} |
|
2595 |
|
|
2596 |
void helper_tlbie (target_ulong addr) |
|
2597 |
{ |
|
2598 |
ppc_tlb_invalidate_one(env, addr); |
|
2599 |
} |
|
2600 |
|
|
2555 | 2601 |
/* Software driven TLBs management */ |
2556 | 2602 |
/* PowerPC 602/603 software TLB load instructions helpers */ |
2557 |
static void helper_load_6xx_tlb (target_ulong new_EPN, int is_code)
|
|
2603 |
static void do_6xx_tlb (target_ulong new_EPN, int is_code)
|
|
2558 | 2604 |
{ |
2559 | 2605 |
target_ulong RPN, CMP, EPN; |
2560 | 2606 |
int way; |
... | ... | |
2580 | 2626 |
way, is_code, CMP, RPN); |
2581 | 2627 |
} |
2582 | 2628 |
|
2583 |
void helper_load_6xx_tlbd (target_ulong EPN)
|
|
2629 |
void helper_6xx_tlbd (target_ulong EPN) |
|
2584 | 2630 |
{ |
2585 |
helper_load_6xx_tlb(EPN, 0);
|
|
2631 |
do_6xx_tlb(EPN, 0);
|
|
2586 | 2632 |
} |
2587 | 2633 |
|
2588 |
void helper_load_6xx_tlbi (target_ulong EPN)
|
|
2634 |
void helper_6xx_tlbi (target_ulong EPN) |
|
2589 | 2635 |
{ |
2590 |
helper_load_6xx_tlb(EPN, 1);
|
|
2636 |
do_6xx_tlb(EPN, 1);
|
|
2591 | 2637 |
} |
2592 | 2638 |
|
2593 | 2639 |
/* PowerPC 74xx software TLB load instructions helpers */ |
2594 |
static void helper_load_74xx_tlb (target_ulong new_EPN, int is_code)
|
|
2640 |
static void do_74xx_tlb (target_ulong new_EPN, int is_code)
|
|
2595 | 2641 |
{ |
2596 | 2642 |
target_ulong RPN, CMP, EPN; |
2597 | 2643 |
int way; |
... | ... | |
2612 | 2658 |
way, is_code, CMP, RPN); |
2613 | 2659 |
} |
2614 | 2660 |
|
2615 |
void helper_load_74xx_tlbd (target_ulong EPN)
|
|
2661 |
void helper_74xx_tlbd (target_ulong EPN) |
|
2616 | 2662 |
{ |
2617 |
helper_load_74xx_tlb(EPN, 0);
|
|
2663 |
do_74xx_tlb(EPN, 0);
|
|
2618 | 2664 |
} |
2619 | 2665 |
|
2620 |
void helper_load_74xx_tlbi (target_ulong EPN)
|
|
2666 |
void helper_74xx_tlbi (target_ulong EPN) |
|
2621 | 2667 |
{ |
2622 |
helper_load_74xx_tlb(EPN, 1);
|
|
2668 |
do_74xx_tlb(EPN, 1);
|
|
2623 | 2669 |
} |
2624 | 2670 |
|
2625 | 2671 |
static always_inline target_ulong booke_tlb_to_page_size (int size) |
... | ... | |
2691 | 2737 |
} |
2692 | 2738 |
|
2693 | 2739 |
/* Helpers for 4xx TLB management */ |
2694 |
void do_4xx_tlbre_lo (void)
|
|
2740 |
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
|
|
2695 | 2741 |
{ |
2696 | 2742 |
ppcemb_tlb_t *tlb; |
2743 |
target_ulong ret; |
|
2697 | 2744 |
int size; |
2698 | 2745 |
|
2699 |
T0 &= 0x3F;
|
|
2700 |
tlb = &env->tlb[T0].tlbe;
|
|
2701 |
T0 = tlb->EPN;
|
|
2746 |
entry &= 0x3F;
|
|
2747 |
tlb = &env->tlb[entry].tlbe;
|
|
2748 |
ret = tlb->EPN;
|
|
2702 | 2749 |
if (tlb->prot & PAGE_VALID) |
2703 |
T0 |= 0x400;
|
|
2750 |
ret |= 0x400;
|
|
2704 | 2751 |
size = booke_page_size_to_tlb(tlb->size); |
2705 | 2752 |
if (size < 0 || size > 0x7) |
2706 | 2753 |
size = 1; |
2707 |
T0 |= size << 7;
|
|
2754 |
ret |= size << 7;
|
|
2708 | 2755 |
env->spr[SPR_40x_PID] = tlb->PID; |
2756 |
return ret; |
|
2709 | 2757 |
} |
2710 | 2758 |
|
2711 |
void do_4xx_tlbre_hi (void)
|
|
2759 |
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
|
|
2712 | 2760 |
{ |
2713 | 2761 |
ppcemb_tlb_t *tlb; |
2762 |
target_ulong ret; |
|
2714 | 2763 |
|
2715 |
T0 &= 0x3F;
|
|
2716 |
tlb = &env->tlb[T0].tlbe;
|
|
2717 |
T0 = tlb->RPN;
|
|
2764 |
entry &= 0x3F;
|
|
2765 |
tlb = &env->tlb[entry].tlbe;
|
|
2766 |
ret = tlb->RPN;
|
|
2718 | 2767 |
if (tlb->prot & PAGE_EXEC) |
2719 |
T0 |= 0x200;
|
|
2768 |
ret |= 0x200;
|
|
2720 | 2769 |
if (tlb->prot & PAGE_WRITE) |
2721 |
T0 |= 0x100; |
|
2770 |
ret |= 0x100; |
|
2771 |
return ret; |
|
2722 | 2772 |
} |
2723 | 2773 |
|
2724 |
void do_4xx_tlbwe_hi (void)
|
|
2774 |
void helper_4xx_tlbwe_hi (target_ulong entry, target_ulong val)
|
|
2725 | 2775 |
{ |
2726 | 2776 |
ppcemb_tlb_t *tlb; |
2727 | 2777 |
target_ulong page, end; |
2728 | 2778 |
|
2729 | 2779 |
#if defined (DEBUG_SOFTWARE_TLB) |
2730 | 2780 |
if (loglevel != 0) { |
2731 |
fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
|
|
2781 |
fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val);
|
|
2732 | 2782 |
} |
2733 | 2783 |
#endif |
2734 |
T0 &= 0x3F;
|
|
2735 |
tlb = &env->tlb[T0].tlbe;
|
|
2784 |
entry &= 0x3F;
|
|
2785 |
tlb = &env->tlb[entry].tlbe;
|
|
2736 | 2786 |
/* Invalidate previous TLB (if it's valid) */ |
2737 | 2787 |
if (tlb->prot & PAGE_VALID) { |
2738 | 2788 |
end = tlb->EPN + tlb->size; |
2739 | 2789 |
#if defined (DEBUG_SOFTWARE_TLB) |
2740 | 2790 |
if (loglevel != 0) { |
2741 | 2791 |
fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX |
2742 |
" end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
|
|
2792 |
" end " ADDRX "\n", __func__, (int)entry, tlb->EPN, end);
|
|
2743 | 2793 |
} |
2744 | 2794 |
#endif |
2745 | 2795 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) |
2746 | 2796 |
tlb_flush_page(env, page); |
2747 | 2797 |
} |
2748 |
tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
|
|
2798 |
tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7);
|
|
2749 | 2799 |
/* We cannot handle TLB size < TARGET_PAGE_SIZE. |
2750 | 2800 |
* If this ever occurs, one should use the ppcemb target instead |
2751 | 2801 |
* of the ppc or ppc64 one |
2752 | 2802 |
*/ |
2753 |
if ((T1 & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
|
|
2803 |
if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
|
|
2754 | 2804 |
cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u " |
2755 | 2805 |
"are not supported (%d)\n", |
2756 |
tlb->size, TARGET_PAGE_SIZE, (int)((T1 >> 7) & 0x7));
|
|
2806 |
tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7));
|
|
2757 | 2807 |
} |
2758 |
tlb->EPN = T1 & ~(tlb->size - 1);
|
|
2759 |
if (T1 & 0x40)
|
|
2808 |
tlb->EPN = val & ~(tlb->size - 1);
|
|
2809 |
if (val & 0x40)
|
|
2760 | 2810 |
tlb->prot |= PAGE_VALID; |
2761 | 2811 |
else |
2762 | 2812 |
tlb->prot &= ~PAGE_VALID; |
2763 |
if (T1 & 0x20) {
|
|
2813 |
if (val & 0x20) {
|
|
2764 | 2814 |
/* XXX: TO BE FIXED */ |
2765 | 2815 |
cpu_abort(env, "Little-endian TLB entries are not supported by now\n"); |
2766 | 2816 |
} |
2767 | 2817 |
tlb->PID = env->spr[SPR_40x_PID]; /* PID */ |
2768 |
tlb->attr = T1 & 0xFF;
|
|
2818 |
tlb->attr = val & 0xFF;
|
|
2769 | 2819 |
#if defined (DEBUG_SOFTWARE_TLB) |
2770 | 2820 |
if (loglevel != 0) { |
2771 | 2821 |
fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX |
... | ... | |
2791 | 2841 |
} |
2792 | 2842 |
} |
2793 | 2843 |
|
2794 |
void do_4xx_tlbwe_lo (void)
|
|
2844 |
void helper_4xx_tlbwe_lo (target_ulong entry, target_ulong val)
|
|
2795 | 2845 |
{ |
2796 | 2846 |
ppcemb_tlb_t *tlb; |
2797 | 2847 |
|
2798 | 2848 |
#if defined (DEBUG_SOFTWARE_TLB) |
2799 | 2849 |
if (loglevel != 0) { |
2800 |
fprintf(logfile, "%s T0 " TDX " T1 " TDX "\n", __func__, T0, T1);
|
|
2850 |
fprintf(logfile, "%s entry " TDX " val " TDX "\n", __func__, entry, val);
|
|
2801 | 2851 |
} |
2802 | 2852 |
#endif |
2803 |
T0 &= 0x3F;
|
|
2804 |
tlb = &env->tlb[T0].tlbe;
|
|
2805 |
tlb->RPN = T1 & 0xFFFFFC00;
|
|
2853 |
entry &= 0x3F;
|
|
2854 |
tlb = &env->tlb[entry].tlbe;
|
|
2855 |
tlb->RPN = val & 0xFFFFFC00;
|
|
2806 | 2856 |
tlb->prot = PAGE_READ; |
2807 |
if (T1 & 0x200)
|
|
2857 |
if (val & 0x200)
|
|
2808 | 2858 |
tlb->prot |= PAGE_EXEC; |
2809 |
if (T1 & 0x100)
|
|
2859 |
if (val & 0x100)
|
|
2810 | 2860 |
tlb->prot |= PAGE_WRITE; |
2811 | 2861 |
#if defined (DEBUG_SOFTWARE_TLB) |
2812 | 2862 |
if (loglevel != 0) { |
2813 | 2863 |
fprintf(logfile, "%s: set up TLB %d RPN " PADDRX " EPN " ADDRX |
2814 | 2864 |
" size " ADDRX " prot %c%c%c%c PID %d\n", __func__, |
2815 |
(int)T0, tlb->RPN, tlb->EPN, tlb->size,
|
|
2865 |
(int)entry, tlb->RPN, tlb->EPN, tlb->size,
|
|
2816 | 2866 |
tlb->prot & PAGE_READ ? 'r' : '-', |
2817 | 2867 |
tlb->prot & PAGE_WRITE ? 'w' : '-', |
2818 | 2868 |
tlb->prot & PAGE_EXEC ? 'x' : '-', |
... | ... | |
2821 | 2871 |
#endif |
2822 | 2872 |
} |
2823 | 2873 |
|
2874 |
target_ulong helper_4xx_tlbsx (target_ulong address) |
|
2875 |
{ |
|
2876 |
return ppcemb_tlb_search(env, address, env->spr[SPR_40x_PID]); |
|
2877 |
} |
|
2878 |
|
|
2824 | 2879 |
/* PowerPC 440 TLB management */ |
2825 |
void do_440_tlbwe (int word)
|
|
2880 |
void helper_440_tlbwe (uint32_t word, target_ulong entry, target_ulong value)
|
|
2826 | 2881 |
{ |
2827 | 2882 |
ppcemb_tlb_t *tlb; |
2828 | 2883 |
target_ulong EPN, RPN, size; |
... | ... | |
2830 | 2885 |
|
2831 | 2886 |
#if defined (DEBUG_SOFTWARE_TLB) |
2832 | 2887 |
if (loglevel != 0) { |
2833 |
fprintf(logfile, "%s word %d T0 " TDX " T1 " TDX "\n",
|
|
2834 |
__func__, word, T0, T1);
|
|
2888 |
fprintf(logfile, "%s word %d entry " TDX " value " TDX "\n",
|
|
2889 |
__func__, word, entry, value);
|
|
2835 | 2890 |
} |
2836 | 2891 |
#endif |
2837 | 2892 |
do_flush_tlbs = 0; |
2838 |
T0 &= 0x3F;
|
|
2839 |
tlb = &env->tlb[T0].tlbe;
|
|
2893 |
entry &= 0x3F;
|
|
2894 |
tlb = &env->tlb[entry].tlbe;
|
|
2840 | 2895 |
switch (word) { |
2841 | 2896 |
default: |
2842 | 2897 |
/* Just here to please gcc */ |
2843 | 2898 |
case 0: |
2844 |
EPN = T1 & 0xFFFFFC00;
|
|
2899 |
EPN = value & 0xFFFFFC00;
|
|
2845 | 2900 |
if ((tlb->prot & PAGE_VALID) && EPN != tlb->EPN) |
2846 | 2901 |
do_flush_tlbs = 1; |
2847 | 2902 |
tlb->EPN = EPN; |
2848 |
size = booke_tlb_to_page_size((T1 >> 4) & 0xF);
|
|
2903 |
size = booke_tlb_to_page_size((value >> 4) & 0xF);
|
|
2849 | 2904 |
if ((tlb->prot & PAGE_VALID) && tlb->size < size) |
2850 | 2905 |
do_flush_tlbs = 1; |
2851 | 2906 |
tlb->size = size; |
2852 | 2907 |
tlb->attr &= ~0x1; |
2853 |
tlb->attr |= (T1 >> 8) & 1;
|
|
2854 |
if (T1 & 0x200) {
|
|
2908 |
tlb->attr |= (value >> 8) & 1;
|
|
2909 |
if (value & 0x200) {
|
|
2855 | 2910 |
tlb->prot |= PAGE_VALID; |
2856 | 2911 |
} else { |
2857 | 2912 |
if (tlb->prot & PAGE_VALID) { |
... | ... | |
2864 | 2919 |
tlb_flush(env, 1); |
2865 | 2920 |
break; |
2866 | 2921 |
case 1: |
2867 |
RPN = T1 & 0xFFFFFC0F;
|
|
2922 |
RPN = value & 0xFFFFFC0F;
|
|
2868 | 2923 |
if ((tlb->prot & PAGE_VALID) && tlb->RPN != RPN) |
2869 | 2924 |
tlb_flush(env, 1); |
2870 | 2925 |
tlb->RPN = RPN; |
2871 | 2926 |
break; |
2872 | 2927 |
case 2: |
2873 |
tlb->attr = (tlb->attr & 0x1) | (T1 & 0x0000FF00);
|
|
2928 |
tlb->attr = (tlb->attr & 0x1) | (value & 0x0000FF00);
|
|
2874 | 2929 |
tlb->prot = tlb->prot & PAGE_VALID; |
2875 |
if (T1 & 0x1)
|
|
2930 |
if (value & 0x1)
|
|
2876 | 2931 |
tlb->prot |= PAGE_READ << 4; |
2877 |
if (T1 & 0x2)
|
|
2932 |
if (value & 0x2)
|
|
2878 | 2933 |
tlb->prot |= PAGE_WRITE << 4; |
2879 |
if (T1 & 0x4)
|
|
2934 |
if (value & 0x4)
|
|
2880 | 2935 |
tlb->prot |= PAGE_EXEC << 4; |
2881 |
if (T1 & 0x8)
|
|
2936 |
if (value & 0x8)
|
|
2882 | 2937 |
tlb->prot |= PAGE_READ; |
2883 |
if (T1 & 0x10)
|
|
2938 |
if (value & 0x10)
|
|
2884 | 2939 |
tlb->prot |= PAGE_WRITE; |
2885 |
if (T1 & 0x20)
|
|
2940 |
if (value & 0x20)
|
|
2886 | 2941 |
tlb->prot |= PAGE_EXEC; |
2887 | 2942 |
break; |
2888 | 2943 |
} |
2889 | 2944 |
} |
2890 | 2945 |
|
2891 |
void do_440_tlbre (int word)
|
|
2946 |
target_ulong helper_440_tlbre (uint32_t word, target_ulong entry)
|
|
2892 | 2947 |
{ |
2893 | 2948 |
ppcemb_tlb_t *tlb; |
2949 |
target_ulong ret; |
|
2894 | 2950 |
int size; |
2895 | 2951 |
|
2896 |
T0 &= 0x3F;
|
|
2897 |
tlb = &env->tlb[T0].tlbe;
|
|
2952 |
entry &= 0x3F;
|
|
2953 |
tlb = &env->tlb[entry].tlbe;
|
|
2898 | 2954 |
switch (word) { |
2899 | 2955 |
default: |
2900 | 2956 |
/* Just here to please gcc */ |
2901 | 2957 |
case 0: |
2902 |
T0 = tlb->EPN;
|
|
2958 |
ret = tlb->EPN;
|
|
2903 | 2959 |
size = booke_page_size_to_tlb(tlb->size); |
2904 | 2960 |
if (size < 0 || size > 0xF) |
2905 | 2961 |
size = 1; |
2906 |
T0 |= size << 4;
|
|
2962 |
ret |= size << 4;
|
|
2907 | 2963 |
if (tlb->attr & 0x1) |
2908 |
T0 |= 0x100;
|
|
2964 |
ret |= 0x100;
|
|
2909 | 2965 |
if (tlb->prot & PAGE_VALID) |
2910 |
T0 |= 0x200;
|
|
2966 |
ret |= 0x200;
|
|
2911 | 2967 |
env->spr[SPR_440_MMUCR] &= ~0x000000FF; |
2912 | 2968 |
env->spr[SPR_440_MMUCR] |= tlb->PID; |
2913 | 2969 |
break; |
2914 | 2970 |
case 1: |
2915 |
T0 = tlb->RPN;
|
|
2971 |
ret = tlb->RPN;
|
|
2916 | 2972 |
break; |
2917 | 2973 |
case 2: |
2918 |
T0 = tlb->attr & ~0x1;
|
|
2974 |
ret = tlb->attr & ~0x1;
|
|
2919 | 2975 |
if (tlb->prot & (PAGE_READ << 4)) |
2920 |
T0 |= 0x1;
|
|
2976 |
ret |= 0x1;
|
|
2921 | 2977 |
if (tlb->prot & (PAGE_WRITE << 4)) |
2922 |
T0 |= 0x2;
|
|
2978 |
ret |= 0x2;
|
|
2923 | 2979 |
if (tlb->prot & (PAGE_EXEC << 4)) |
2924 |
T0 |= 0x4;
|
|
2980 |
ret |= 0x4;
|
|
2925 | 2981 |
if (tlb->prot & PAGE_READ) |
2926 |
T0 |= 0x8;
|
|
2982 |
ret |= 0x8;
|
|
2927 | 2983 |
if (tlb->prot & PAGE_WRITE) |
2928 |
T0 |= 0x10;
|
|
2984 |
ret |= 0x10;
|
|
2929 | 2985 |
if (tlb->prot & PAGE_EXEC) |
2930 |
T0 |= 0x20;
|
|
2986 |
ret |= 0x20;
|
|
2931 | 2987 |
break; |
2932 | 2988 |
} |
2989 |
return ret; |
|
2933 | 2990 |
} |
2991 |
|
|
2992 |
target_ulong helper_440_tlbsx (target_ulong address) |
|
2993 |
{ |
|
2994 |
return ppcemb_tlb_search(env, address, env->spr[SPR_440_MMUCR] & 0xFF); |
|
2995 |
} |
|
2996 |
|
|
2934 | 2997 |
#endif /* !CONFIG_USER_ONLY */ |
b/target-ppc/op_helper.h | ||
---|---|---|
34 | 34 |
void do_store_hid0_601 (void); |
35 | 35 |
#endif |
36 | 36 |
|
37 |
/* PowerPC 440 specific helpers */ |
|
38 |
#if !defined(CONFIG_USER_ONLY) |
|
39 |
void do_440_tlbre (int word); |
|
40 |
void do_440_tlbwe (int word); |
|
41 |
#endif |
|
42 |
|
|
43 |
/* PowerPC 4xx specific helpers */ |
|
44 |
#if !defined(CONFIG_USER_ONLY) |
|
45 |
void do_4xx_tlbre_lo (void); |
|
46 |
void do_4xx_tlbre_hi (void); |
|
47 |
void do_4xx_tlbwe_lo (void); |
|
48 |
void do_4xx_tlbwe_hi (void); |
|
49 |
#endif |
|
50 |
|
|
51 | 37 |
/* PowerPC 403 specific helpers */ |
52 | 38 |
#if !defined(CONFIG_USER_ONLY) |
53 | 39 |
void do_load_403_pb (int num); |
b/target-ppc/translate.c | ||
---|---|---|
4208 | 4208 |
#if defined(CONFIG_USER_ONLY) |
4209 | 4209 |
GEN_EXCP_PRIVREG(ctx); |
4210 | 4210 |
#else |
4211 |
TCGv t0; |
|
4211 | 4212 |
if (unlikely(!ctx->supervisor)) { |
4212 | 4213 |
GEN_EXCP_PRIVREG(ctx); |
4213 | 4214 |
return; |
4214 | 4215 |
} |
4215 |
tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
|
|
4216 |
gen_op_load_sr();
|
|
4217 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
|
|
4216 |
t0 = tcg_const_tl(SR(ctx->opcode));
|
|
4217 |
gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
|
|
4218 |
tcg_temp_free(t0);
|
|
4218 | 4219 |
#endif |
4219 | 4220 |
} |
4220 | 4221 |
|
... | ... | |
4224 | 4225 |
#if defined(CONFIG_USER_ONLY) |
4225 | 4226 |
GEN_EXCP_PRIVREG(ctx); |
4226 | 4227 |
#else |
4228 |
TCGv t0; |
|
4227 | 4229 |
if (unlikely(!ctx->supervisor)) { |
4228 | 4230 |
GEN_EXCP_PRIVREG(ctx); |
4229 | 4231 |
return; |
4230 | 4232 |
} |
4231 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); |
|
4232 |
gen_op_srli_T1(28); |
|
4233 |
gen_op_load_sr(); |
|
4234 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
4233 |
t0 = tcg_temp_new(); |
|
4234 |
tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); |
|
4235 |
tcg_gen_andi_tl(t0, t0, 0xF); |
|
4236 |
gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0); |
|
4237 |
tcg_temp_free(t0); |
|
4235 | 4238 |
#endif |
4236 | 4239 |
} |
4237 | 4240 |
|
... | ... | |
4241 | 4244 |
#if defined(CONFIG_USER_ONLY) |
4242 | 4245 |
GEN_EXCP_PRIVREG(ctx); |
4243 | 4246 |
#else |
4247 |
TCGv t0; |
|
4244 | 4248 |
if (unlikely(!ctx->supervisor)) { |
4245 | 4249 |
GEN_EXCP_PRIVREG(ctx); |
4246 | 4250 |
return; |
4247 | 4251 |
} |
4248 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
|
|
4249 |
tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
|
|
4250 |
gen_op_store_sr();
|
|
4252 |
t0 = tcg_const_tl(SR(ctx->opcode));
|
|
4253 |
gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
|
|
4254 |
tcg_temp_free(t0);
|
|
4251 | 4255 |
#endif |
4252 | 4256 |
} |
4253 | 4257 |
|
... | ... | |
4257 | 4261 |
#if defined(CONFIG_USER_ONLY) |
4258 | 4262 |
GEN_EXCP_PRIVREG(ctx); |
4259 | 4263 |
#else |
4264 |
TCGv t0; |
|
4260 | 4265 |
if (unlikely(!ctx->supervisor)) { |
4261 | 4266 |
GEN_EXCP_PRIVREG(ctx); |
4262 | 4267 |
return; |
4263 | 4268 |
} |
4264 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); |
|
4265 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); |
|
4266 |
gen_op_srli_T1(28); |
|
4267 |
gen_op_store_sr(); |
|
4269 |
t0 = tcg_temp_new(); |
|
4270 |
tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); |
|
4271 |
tcg_gen_andi_tl(t0, t0, 0xF); |
|
4272 |
gen_helper_store_sr(t0, cpu_gpr[rD(ctx->opcode)]); |
|
4273 |
tcg_temp_free(t0); |
|
4268 | 4274 |
#endif |
4269 | 4275 |
} |
4270 | 4276 |
|
... | ... | |
4276 | 4282 |
#if defined(CONFIG_USER_ONLY) |
4277 | 4283 |
GEN_EXCP_PRIVREG(ctx); |
4278 | 4284 |
#else |
4285 |
TCGv t0; |
|
4279 | 4286 |
if (unlikely(!ctx->supervisor)) { |
4280 | 4287 |
GEN_EXCP_PRIVREG(ctx); |
4281 | 4288 |
return; |
4282 | 4289 |
} |
4283 |
tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
|
|
4284 |
gen_op_load_slb();
|
|
4285 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
|
|
4290 |
t0 = tcg_const_tl(SR(ctx->opcode));
|
|
4291 |
gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
|
|
4292 |
tcg_temp_free(t0);
|
|
4286 | 4293 |
#endif |
4287 | 4294 |
} |
4288 | 4295 |
|
... | ... | |
4293 | 4300 |
#if defined(CONFIG_USER_ONLY) |
4294 | 4301 |
GEN_EXCP_PRIVREG(ctx); |
4295 | 4302 |
#else |
4303 |
TCGv t0; |
|
4296 | 4304 |
if (unlikely(!ctx->supervisor)) { |
4297 | 4305 |
GEN_EXCP_PRIVREG(ctx); |
4298 | 4306 |
return; |
4299 | 4307 |
} |
4300 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); |
|
4301 |
gen_op_srli_T1(28); |
|
4302 |
gen_op_load_slb(); |
|
4303 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
4308 |
t0 = tcg_temp_new(); |
|
4309 |
tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); |
|
4310 |
tcg_gen_andi_tl(t0, t0, 0xF); |
|
4311 |
gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0); |
|
4312 |
tcg_temp_free(t0); |
|
4304 | 4313 |
#endif |
4305 | 4314 |
} |
4306 | 4315 |
|
... | ... | |
4310 | 4319 |
#if defined(CONFIG_USER_ONLY) |
4311 | 4320 |
GEN_EXCP_PRIVREG(ctx); |
4312 | 4321 |
#else |
4322 |
TCGv t0; |
|
4313 | 4323 |
if (unlikely(!ctx->supervisor)) { |
4314 | 4324 |
GEN_EXCP_PRIVREG(ctx); |
4315 | 4325 |
return; |
4316 | 4326 |
} |
4317 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
|
|
4318 |
tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
|
|
4319 |
gen_op_store_slb();
|
|
4327 |
t0 = tcg_const_tl(SR(ctx->opcode));
|
|
4328 |
gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
|
|
4329 |
tcg_temp_free(t0);
|
|
4320 | 4330 |
#endif |
4321 | 4331 |
} |
4322 | 4332 |
|
... | ... | |
4327 | 4337 |
#if defined(CONFIG_USER_ONLY) |
4328 | 4338 |
GEN_EXCP_PRIVREG(ctx); |
4329 | 4339 |
#else |
4340 |
TCGv t0; |
|
4330 | 4341 |
if (unlikely(!ctx->supervisor)) { |
4331 | 4342 |
GEN_EXCP_PRIVREG(ctx); |
4332 | 4343 |
return; |
4333 | 4344 |
} |
4334 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); |
|
4335 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); |
|
4336 |
gen_op_srli_T1(28); |
|
4337 |
gen_op_store_slb(); |
|
4345 |
t0 = tcg_temp_new(); |
|
4346 |
tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28); |
|
4347 |
tcg_gen_andi_tl(t0, t0, 0xF); |
|
4348 |
gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]); |
|
4349 |
tcg_temp_free(t0); |
|
4338 | 4350 |
#endif |
4339 | 4351 |
} |
4340 | 4352 |
#endif /* defined(TARGET_PPC64) */ |
... | ... | |
4351 | 4363 |
GEN_EXCP_PRIVOPC(ctx); |
4352 | 4364 |
return; |
4353 | 4365 |
} |
4354 |
gen_op_tlbia();
|
|
4366 |
gen_helper_tlbia();
|
|
4355 | 4367 |
#endif |
4356 | 4368 |
} |
4357 | 4369 |
|
... | ... | |
4365 | 4377 |
GEN_EXCP_PRIVOPC(ctx); |
4366 | 4378 |
return; |
4367 | 4379 |
} |
4368 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]); |
|
4369 | 4380 |
#if defined(TARGET_PPC64) |
4370 |
if (ctx->sf_mode) |
|
4371 |
gen_op_tlbie_64(); |
|
4372 |
else |
|
4381 |
if (!ctx->sf_mode) { |
|
4382 |
TCGv t0 = tcg_temp_new(); |
|
4383 |
tcg_gen_ext32u_tl(t0, cpu_gpr[rB(ctx->opcode)]); |
|
4384 |
gen_helper_tlbie(t0); |
|
4385 |
tcg_temp_free(t0); |
|
4386 |
} else |
|
4373 | 4387 |
#endif |
4374 |
gen_op_tlbie();
|
|
4388 |
gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
|
|
4375 | 4389 |
#endif |
4376 | 4390 |
} |
4377 | 4391 |
|
... | ... | |
4403 | 4417 |
GEN_EXCP_PRIVOPC(ctx); |
4404 | 4418 |
return; |
4405 | 4419 |
} |
4406 |
gen_op_slbia();
|
|
4420 |
gen_helper_slbia();
|
|
4407 | 4421 |
#endif |
4408 | 4422 |
} |
4409 | 4423 |
|
... | ... | |
4417 | 4431 |
GEN_EXCP_PRIVOPC(ctx); |
4418 | 4432 |
return; |
4419 | 4433 |
} |
4420 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]); |
|
4421 |
gen_op_slbie(); |
|
4434 |
gen_helper_slbie(cpu_gpr[rB(ctx->opcode)]); |
|
4422 | 4435 |
#endif |
4423 | 4436 |
} |
4424 | 4437 |
#endif |
... | ... | |
5129 | 5142 |
GEN_EXCP_PRIVOPC(ctx); |
5130 | 5143 |
return; |
5131 | 5144 |
} |
5132 |
gen_helper_load_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
|
|
5145 |
gen_helper_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]); |
|
5133 | 5146 |
#endif |
5134 | 5147 |
} |
5135 | 5148 |
|
... | ... | |
5143 | 5156 |
GEN_EXCP_PRIVOPC(ctx); |
5144 | 5157 |
return; |
5145 | 5158 |
} |
5146 |
gen_helper_load_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
|
|
5159 |
gen_helper_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]); |
|
5147 | 5160 |
#endif |
5148 | 5161 |
} |
5149 | 5162 |
|
... | ... | |
5158 | 5171 |
GEN_EXCP_PRIVOPC(ctx); |
5159 | 5172 |
return; |
5160 | 5173 |
} |
5161 |
gen_helper_load_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
|
|
5174 |
gen_helper_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]); |
|
5162 | 5175 |
#endif |
5163 | 5176 |
} |
5164 | 5177 |
|
... | ... | |
5172 | 5185 |
GEN_EXCP_PRIVOPC(ctx); |
5173 | 5186 |
return; |
5174 | 5187 |
} |
5175 |
gen_helper_load_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
|
|
5188 |
gen_helper_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]); |
|
5176 | 5189 |
#endif |
5177 | 5190 |
} |
5178 | 5191 |
|
... | ... | |
5208 | 5221 |
#if defined(CONFIG_USER_ONLY) |
5209 | 5222 |
GEN_EXCP_PRIVOPC(ctx); |
5210 | 5223 |
#else |
5224 |
int ra = rA(ctx->opcode); |
|
5225 |
int rd = rD(ctx->opcode); |
|
5226 |
TCGv t0; |
|
5211 | 5227 |
if (unlikely(!ctx->supervisor)) { |
5212 | 5228 |
GEN_EXCP_PRIVOPC(ctx); |
5213 | 5229 |
return; |
5214 | 5230 |
} |
5215 |
int ra = rA(ctx->opcode);
|
|
5216 |
int rd = rD(ctx->opcode);
|
|
5217 |
|
|
5218 |
gen_addr_reg_index(cpu_T[0], ctx);
|
|
5219 |
gen_op_POWER_mfsri();
|
|
5220 |
tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
|
|
5231 |
t0 = tcg_temp_new();
|
|
5232 |
gen_addr_reg_index(t0, ctx);
|
|
5233 |
tcg_gen_shri_tl(t0, t0, 28); |
|
5234 |
tcg_gen_andi_tl(t0, t0, 0xF);
|
|
5235 |
gen_helper_load_sr(cpu_gpr[rd], t0);
|
|
5236 |
tcg_temp_free(t0);
|
|
5221 | 5237 |
if (ra != 0 && ra != rd) |
5222 |
tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
|
|
5238 |
tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rd]);
|
|
5223 | 5239 |
#endif |
5224 | 5240 |
} |
5225 | 5241 |
|
... | ... | |
5389 | 5405 |
#if defined(CONFIG_USER_ONLY) |
5390 | 5406 |
GEN_EXCP_PRIVOPC(ctx); |
5391 | 5407 |
#else |
5408 |
TCGv t0; |
|
5392 | 5409 |
if (unlikely(!ctx->supervisor)) { |
5393 | 5410 |
GEN_EXCP_PRIVOPC(ctx); |
5394 | 5411 |
return; |
5395 | 5412 |
} |
5396 |
gen_addr_reg_index(cpu_T[0], ctx); |
|
5397 |
/* Use the same micro-ops as for tlbie */ |
|
5413 |
gen_addr_reg_index(t0, ctx); |
|
5398 | 5414 |
#if defined(TARGET_PPC64) |
5399 |
if (ctx->sf_mode) |
|
5400 |
gen_op_tlbie_64(); |
|
5401 |
else |
|
5415 |
if (!ctx->sf_mode) |
|
5416 |
tcg_gen_ext32u_tl(t0, t0); |
|
5402 | 5417 |
#endif |
5403 |
gen_op_tlbie(); |
|
5418 |
gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]); |
|
5419 |
tcg_temp_free(t0); |
|
5404 | 5420 |
#endif |
5405 | 5421 |
} |
5406 | 5422 |
|
... | ... | |
5861 | 5877 |
} |
5862 | 5878 |
switch (rB(ctx->opcode)) { |
5863 | 5879 |
case 0: |
5864 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); |
|
5865 |
gen_op_4xx_tlbre_hi(); |
|
5866 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
5880 |
gen_helper_4xx_tlbre_hi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); |
|
5867 | 5881 |
break; |
5868 | 5882 |
case 1: |
5869 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); |
|
5870 |
gen_op_4xx_tlbre_lo(); |
|
5871 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
5883 |
gen_helper_4xx_tlbre_lo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); |
|
5872 | 5884 |
break; |
5873 | 5885 |
default: |
5874 | 5886 |
GEN_EXCP_INVAL(ctx); |
... | ... | |
5883 | 5895 |
#if defined(CONFIG_USER_ONLY) |
5884 | 5896 |
GEN_EXCP_PRIVOPC(ctx); |
5885 | 5897 |
#else |
5898 |
TCGv t0; |
|
5886 | 5899 |
if (unlikely(!ctx->supervisor)) { |
5887 | 5900 |
GEN_EXCP_PRIVOPC(ctx); |
5888 | 5901 |
return; |
5889 | 5902 |
} |
5890 |
gen_addr_reg_index(cpu_T[0], ctx); |
|
5891 |
gen_op_4xx_tlbsx(); |
|
5892 |
if (Rc(ctx->opcode)) |
|
5893 |
gen_op_4xx_tlbsx_check(); |
|
5894 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
5903 |
t0 = tcg_temp_new(); |
|
5904 |
gen_addr_reg_index(t0, ctx); |
|
5905 |
gen_helper_4xx_tlbsx(cpu_gpr[rD(ctx->opcode)], t0); |
|
5906 |
tcg_temp_free(t0); |
|
5907 |
if (Rc(ctx->opcode)) { |
|
5908 |
int l1 = gen_new_label(); |
|
5909 |
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); |
|
5910 |
tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); |
|
5911 |
tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); |
|
5912 |
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1); |
|
5913 |
tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); |
|
5914 |
gen_set_label(l1); |
|
5915 |
} |
|
5895 | 5916 |
#endif |
5896 | 5917 |
} |
5897 | 5918 |
|
... | ... | |
5907 | 5928 |
} |
5908 | 5929 |
switch (rB(ctx->opcode)) { |
5909 | 5930 |
case 0: |
5910 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); |
|
5911 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); |
|
5912 |
gen_op_4xx_tlbwe_hi(); |
|
5931 |
gen_helper_4xx_tlbwe_hi(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); |
|
5913 | 5932 |
break; |
5914 | 5933 |
case 1: |
5915 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); |
|
5916 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); |
|
5917 |
gen_op_4xx_tlbwe_lo(); |
|
5934 |
gen_helper_4xx_tlbwe_lo(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); |
|
5918 | 5935 |
break; |
5919 | 5936 |
default: |
5920 | 5937 |
GEN_EXCP_INVAL(ctx); |
... | ... | |
5938 | 5955 |
case 0: |
5939 | 5956 |
case 1: |
5940 | 5957 |
case 2: |
5941 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); |
|
5942 |
gen_op_440_tlbre(rB(ctx->opcode)); |
|
5943 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
5958 |
{ |
|
5959 |
TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode)); |
|
5960 |
gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); |
|
5961 |
tcg_temp_free_i32(t0); |
|
5962 |
} |
|
5944 | 5963 |
break; |
5945 | 5964 |
default: |
5946 | 5965 |
GEN_EXCP_INVAL(ctx); |
... | ... | |
5955 | 5974 |
#if defined(CONFIG_USER_ONLY) |
5956 | 5975 |
GEN_EXCP_PRIVOPC(ctx); |
5957 | 5976 |
#else |
5977 |
TCGv t0; |
|
5958 | 5978 |
if (unlikely(!ctx->supervisor)) { |
5959 | 5979 |
GEN_EXCP_PRIVOPC(ctx); |
5960 | 5980 |
return; |
5961 | 5981 |
} |
5962 |
gen_addr_reg_index(cpu_T[0], ctx); |
|
5963 |
gen_op_440_tlbsx(); |
|
5964 |
if (Rc(ctx->opcode)) |
|
5965 |
gen_op_4xx_tlbsx_check(); |
|
5966 |
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); |
|
5982 |
t0 = tcg_temp_new(); |
|
5983 |
gen_addr_reg_index(t0, ctx); |
|
5984 |
gen_helper_440_tlbsx(cpu_gpr[rD(ctx->opcode)], t0); |
|
5985 |
tcg_temp_free(t0); |
|
5986 |
if (Rc(ctx->opcode)) { |
|
5987 |
int l1 = gen_new_label(); |
|
5988 |
tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer); |
|
5989 |
tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO); |
|
5990 |
tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1); |
|
5991 |
tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rD(ctx->opcode)], -1, l1); |
|
5992 |
tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 0x02); |
|
5993 |
gen_set_label(l1); |
|
5994 |
} |
|
5967 | 5995 |
#endif |
5968 | 5996 |
} |
5969 | 5997 |
|
... | ... | |
5981 | 6009 |
case 0: |
5982 | 6010 |
case 1: |
5983 | 6011 |
case 2: |
5984 |
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); |
|
5985 |
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); |
|
5986 |
gen_op_440_tlbwe(rB(ctx->opcode)); |
|
6012 |
{ |
|
6013 |
TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode)); |
|
6014 |
gen_helper_440_tlbwe(t0, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); |
|
6015 |
tcg_temp_free_i32(t0); |
|
6016 |
} |
|
5987 | 6017 |
break; |
5988 | 6018 |
default: |
5989 | 6019 |
GEN_EXCP_INVAL(ctx); |
Also available in: Unified diff