Revision 056401ea
b/target-ppc/cpu.h | ||
---|---|---|
651 | 651 |
/* Those resources are used only in Qemu core */ |
652 | 652 |
jmp_buf jmp_env; |
653 | 653 |
int user_mode_only; /* user mode only simulation */ |
654 |
target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */ |
|
654 |
target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */ |
|
655 |
target_ulong hflags_nmsr; /* specific hflags, not comming from MSR */ |
|
655 | 656 |
int mmu_idx; /* precomputed MMU index to speed up mem accesses */ |
656 | 657 |
|
657 | 658 |
/* Power management */ |
... | ... | |
698 | 699 |
target_ulong do_load_dbatl (CPUPPCState *env, int nr); |
699 | 700 |
void do_store_dbatu (CPUPPCState *env, int nr, target_ulong value); |
700 | 701 |
void do_store_dbatl (CPUPPCState *env, int nr, target_ulong value); |
702 |
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value); |
|
703 |
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value); |
|
701 | 704 |
target_ulong do_load_sdr1 (CPUPPCState *env); |
702 | 705 |
void do_store_sdr1 (CPUPPCState *env, target_ulong value); |
703 | 706 |
#if defined(TARGET_PPC64) |
b/target-ppc/helper.c | ||
---|---|---|
482 | 482 |
int key, pp, valid, prot; |
483 | 483 |
|
484 | 484 |
bl = (*BATl & 0x0000003F) << 17; |
485 |
#if defined (DEBUG_BATS) |
|
485 | 486 |
if (loglevel != 0) { |
486 | 487 |
fprintf(logfile, "b %02x ==> bl %08x msk %08x\n", |
487 | 488 |
*BATl & 0x0000003F, bl, ~bl); |
488 | 489 |
} |
490 |
#endif |
|
489 | 491 |
prot = 0; |
490 | 492 |
valid = (*BATl >> 6) & 1; |
491 | 493 |
if (valid) { |
... | ... | |
1836 | 1838 |
env->DBAT[1][nr] = value; |
1837 | 1839 |
} |
1838 | 1840 |
|
1841 |
void do_store_ibatu_601 (CPUPPCState *env, int nr, target_ulong value) |
|
1842 |
{ |
|
1843 |
target_ulong mask; |
|
1844 |
int do_inval; |
|
1845 |
|
|
1846 |
dump_store_bat(env, 'I', 0, nr, value); |
|
1847 |
if (env->IBAT[0][nr] != value) { |
|
1848 |
do_inval = 0; |
|
1849 |
mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL; |
|
1850 |
if (env->IBAT[1][nr] & 0x40) { |
|
1851 |
/* Invalidate BAT only if it is valid */ |
|
1852 |
#if !defined(FLUSH_ALL_TLBS) |
|
1853 |
do_invalidate_BAT(env, env->IBAT[0][nr], mask); |
|
1854 |
#else |
|
1855 |
do_inval = 1; |
|
1856 |
#endif |
|
1857 |
} |
|
1858 |
/* When storing valid upper BAT, mask BEPI and BRPN |
|
1859 |
* and invalidate all TLBs covered by this BAT |
|
1860 |
*/ |
|
1861 |
env->IBAT[0][nr] = (value & 0x00001FFFUL) | |
|
1862 |
(value & ~0x0001FFFFUL & ~mask); |
|
1863 |
env->DBAT[0][nr] = env->IBAT[0][nr]; |
|
1864 |
if (env->IBAT[1][nr] & 0x40) { |
|
1865 |
#if !defined(FLUSH_ALL_TLBS) |
|
1866 |
do_invalidate_BAT(env, env->IBAT[0][nr], mask); |
|
1867 |
#else |
|
1868 |
do_inval = 1; |
|
1869 |
#endif |
|
1870 |
} |
|
1871 |
#if defined(FLUSH_ALL_TLBS) |
|
1872 |
if (do_inval) |
|
1873 |
tlb_flush(env, 1); |
|
1874 |
#endif |
|
1875 |
} |
|
1876 |
} |
|
1877 |
|
|
1878 |
void do_store_ibatl_601 (CPUPPCState *env, int nr, target_ulong value) |
|
1879 |
{ |
|
1880 |
target_ulong mask; |
|
1881 |
int do_inval; |
|
1882 |
|
|
1883 |
dump_store_bat(env, 'I', 1, nr, value); |
|
1884 |
if (env->IBAT[1][nr] != value) { |
|
1885 |
do_inval = 0; |
|
1886 |
if (env->IBAT[1][nr] & 0x40) { |
|
1887 |
#if !defined(FLUSH_ALL_TLBS) |
|
1888 |
mask = (env->IBAT[1][nr] << 17) & 0x0FFE0000UL; |
|
1889 |
do_invalidate_BAT(env, env->IBAT[0][nr], mask); |
|
1890 |
#else |
|
1891 |
do_inval = 1; |
|
1892 |
#endif |
|
1893 |
} |
|
1894 |
if (value & 0x40) { |
|
1895 |
#if !defined(FLUSH_ALL_TLBS) |
|
1896 |
mask = (value << 17) & 0x0FFE0000UL; |
|
1897 |
do_invalidate_BAT(env, env->IBAT[0][nr], mask); |
|
1898 |
#else |
|
1899 |
do_inval = 1; |
|
1900 |
#endif |
|
1901 |
} |
|
1902 |
env->IBAT[1][nr] = value; |
|
1903 |
env->DBAT[1][nr] = value; |
|
1904 |
#if defined(FLUSH_ALL_TLBS) |
|
1905 |
if (do_inval) |
|
1906 |
tlb_flush(env, 1); |
|
1907 |
#endif |
|
1908 |
} |
|
1909 |
} |
|
1910 |
|
|
1839 | 1911 |
/*****************************************************************************/ |
1840 | 1912 |
/* TLB management */ |
1841 | 1913 |
void ppc_tlb_invalidate_all (CPUPPCState *env) |
... | ... | |
2684 | 2756 |
* any special case that could occur. Just store MSR and update hflags |
2685 | 2757 |
*/ |
2686 | 2758 |
env->msr = new_msr; |
2759 |
env->hflags_nmsr = 0x00000000; |
|
2687 | 2760 |
hreg_compute_hflags(env); |
2688 | 2761 |
env->nip = vector; |
2689 | 2762 |
/* Reset exception state */ |
b/target-ppc/helper_regs.h | ||
---|---|---|
58 | 58 |
env->tgpr[3] = tmp; |
59 | 59 |
} |
60 | 60 |
|
61 |
static always_inline void hreg_compute_mem_idx (CPUPPCState *env) |
|
62 |
{ |
|
63 |
#if defined (TARGET_PPC64H) |
|
64 |
/* Precompute MMU index */ |
|
65 |
if (msr_pr == 0 && msr_hv != 0) |
|
66 |
env->mmu_idx = 2; |
|
67 |
else |
|
68 |
#endif |
|
69 |
env->mmu_idx = 1 - msr_pr; |
|
70 |
} |
|
71 |
|
|
61 | 72 |
static always_inline void hreg_compute_hflags (CPUPPCState *env) |
62 | 73 |
{ |
63 | 74 |
target_ulong hflags_mask; |
... | ... | |
70 | 81 |
hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF); |
71 | 82 |
#if defined (TARGET_PPC64H) |
72 | 83 |
hflags_mask |= 1ULL << MSR_HV; |
73 |
/* Precompute MMU index */ |
|
74 |
if (msr_pr == 0 && msr_hv != 0) |
|
75 |
env->mmu_idx = 2; |
|
76 |
else |
|
77 | 84 |
#endif |
78 | 85 |
#endif |
79 |
env->mmu_idx = 1 - msr_pr;
|
|
86 |
hreg_compute_mem_idx(env);
|
|
80 | 87 |
env->hflags = env->msr & hflags_mask; |
88 |
/* Merge with hflags coming from other registers */ |
|
89 |
env->hflags |= env->hflags_nmsr; |
|
81 | 90 |
} |
82 | 91 |
|
83 | 92 |
static always_inline int hreg_store_msr (CPUPPCState *env, target_ulong value) |
b/target-ppc/op.c | ||
---|---|---|
2190 | 2190 |
RETURN(); |
2191 | 2191 |
} |
2192 | 2192 |
|
2193 |
void OPPROTO op_store_hid0_601 (void) |
|
2194 |
{ |
|
2195 |
do_store_hid0_601(); |
|
2196 |
RETURN(); |
|
2197 |
} |
|
2198 |
|
|
2193 | 2199 |
void OPPROTO op_load_601_bat (void) |
2194 | 2200 |
{ |
2195 | 2201 |
T0 = env->IBAT[PARAM1][PARAM2]; |
2196 | 2202 |
RETURN(); |
2197 | 2203 |
} |
2198 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
|
2199 | 2204 |
|
2200 |
/* 601 unified BATs store. |
|
2201 |
* To avoid using specific MMU code for 601, we store BATs in |
|
2202 |
* IBAT and DBAT simultaneously, then emulate unified BATs. |
|
2203 |
*/ |
|
2204 |
#if !defined(CONFIG_USER_ONLY) |
|
2205 | 2205 |
void OPPROTO op_store_601_batl (void) |
2206 | 2206 |
{ |
2207 |
int nr = PARAM1; |
|
2208 |
|
|
2209 |
env->IBAT[1][nr] = T0; |
|
2210 |
env->DBAT[1][nr] = T0; |
|
2207 |
do_store_ibatl_601(env, PARAM1, T0); |
|
2211 | 2208 |
RETURN(); |
2212 | 2209 |
} |
2213 | 2210 |
|
2214 | 2211 |
void OPPROTO op_store_601_batu (void) |
2215 | 2212 |
{ |
2216 |
do_store_601_batu(PARAM1);
|
|
2213 |
do_store_ibatu_601(env, PARAM1, T0);
|
|
2217 | 2214 |
RETURN(); |
2218 | 2215 |
} |
2219 | 2216 |
#endif /* !defined(CONFIG_USER_ONLY) */ |
b/target-ppc/op_helper.c | ||
---|---|---|
1701 | 1701 |
__do_rfi(env->lr, env->ctr, 0x0000FFFF, 0); |
1702 | 1702 |
} |
1703 | 1703 |
|
1704 |
/* PowerPC 601 BAT management helper */ |
|
1705 |
void do_store_601_batu (int nr) |
|
1704 |
void do_store_hid0_601 (void) |
|
1706 | 1705 |
{ |
1707 |
do_store_ibatu(env, nr, (uint32_t)T0); |
|
1708 |
env->DBAT[0][nr] = env->IBAT[0][nr]; |
|
1709 |
env->DBAT[1][nr] = env->IBAT[1][nr]; |
|
1706 |
uint32_t hid0; |
|
1707 |
|
|
1708 |
hid0 = env->spr[SPR_HID0]; |
|
1709 |
if ((T0 ^ hid0) & 0x00000008) { |
|
1710 |
/* Change current endianness */ |
|
1711 |
env->hflags &= ~(1 << MSR_LE); |
|
1712 |
env->hflags_nmsr &= ~(1 << MSR_LE); |
|
1713 |
env->hflags_nmsr |= (1 << MSR_LE) & (((T0 >> 3) & 1) << MSR_LE); |
|
1714 |
env->hflags |= env->hflags_nmsr; |
|
1715 |
if (loglevel != 0) { |
|
1716 |
fprintf(logfile, "%s: set endianness to %c => " ADDRX "\n", |
|
1717 |
__func__, T0 & 0x8 ? 'l' : 'b', env->hflags); |
|
1718 |
} |
|
1719 |
} |
|
1720 |
env->spr[SPR_HID0] = T0; |
|
1710 | 1721 |
} |
1711 | 1722 |
#endif |
1712 | 1723 |
|
b/target-ppc/op_helper.h | ||
---|---|---|
155 | 155 |
#endif |
156 | 156 |
|
157 | 157 |
/* POWER / PowerPC 601 specific helpers */ |
158 |
void do_store_601_batu (int nr); |
|
159 | 158 |
void do_POWER_abso (void); |
160 | 159 |
void do_POWER_clcs (void); |
161 | 160 |
void do_POWER_div (void); |
... | ... | |
168 | 167 |
#if !defined(CONFIG_USER_ONLY) |
169 | 168 |
void do_POWER_rac (void); |
170 | 169 |
void do_POWER_rfsvc (void); |
170 |
void do_store_hid0_601 (void); |
|
171 | 171 |
#endif |
172 | 172 |
|
173 | 173 |
/* PowerPC 602 specific helper */ |
b/target-ppc/translate.c | ||
---|---|---|
6801 | 6801 |
opc_handler_t **table, *handler; |
6802 | 6802 |
target_ulong pc_start; |
6803 | 6803 |
uint16_t *gen_opc_end; |
6804 |
int supervisor; |
|
6804 |
int supervisor, little_endian;
|
|
6805 | 6805 |
int single_step, branch_step; |
6806 | 6806 |
int j, lj = -1; |
6807 | 6807 |
|
... | ... | |
6821 | 6821 |
#if !defined(CONFIG_USER_ONLY) |
6822 | 6822 |
ctx.supervisor = supervisor; |
6823 | 6823 |
#endif |
6824 |
little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0; |
|
6824 | 6825 |
#if defined(TARGET_PPC64) |
6825 | 6826 |
ctx.sf_mode = msr_sf; |
6826 |
ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | msr_le;
|
|
6827 |
ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
|
|
6827 | 6828 |
#else |
6828 |
ctx.mem_idx = (supervisor << 1) | msr_le;
|
|
6829 |
ctx.mem_idx = (supervisor << 1) | little_endian;
|
|
6829 | 6830 |
#endif |
6830 | 6831 |
ctx.dcache_line_size = env->dcache_line_size; |
6831 | 6832 |
ctx.fpu_enabled = msr_fp; |
... | ... | |
6880 | 6881 |
ctx.nip, supervisor, (int)msr_ir); |
6881 | 6882 |
} |
6882 | 6883 |
#endif |
6883 |
ctx.opcode = ldl_code(ctx.nip); |
|
6884 |
if (msr_le) { |
|
6885 |
ctx.opcode = ((ctx.opcode & 0xFF000000) >> 24) | |
|
6886 |
((ctx.opcode & 0x00FF0000) >> 8) | |
|
6887 |
((ctx.opcode & 0x0000FF00) << 8) | |
|
6888 |
((ctx.opcode & 0x000000FF) << 24); |
|
6884 |
if (unlikely(little_endian)) { |
|
6885 |
ctx.opcode = bswap32(ldl_code(ctx.nip)); |
|
6886 |
} else { |
|
6887 |
ctx.opcode = ldl_code(ctx.nip); |
|
6889 | 6888 |
} |
6890 | 6889 |
#if defined PPC_DEBUG_DISAS |
6891 | 6890 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
6892 | 6891 |
fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n", |
6893 | 6892 |
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode), |
6894 |
opc3(ctx.opcode), msr_le ? "little" : "big");
|
|
6893 |
opc3(ctx.opcode), little_endian ? "little" : "big");
|
|
6895 | 6894 |
} |
6896 | 6895 |
#endif |
6897 | 6896 |
ctx.nip += 4; |
... | ... | |
6986 | 6985 |
if (loglevel & CPU_LOG_TB_IN_ASM) { |
6987 | 6986 |
int flags; |
6988 | 6987 |
flags = env->bfd_mach; |
6989 |
flags |= msr_le << 16;
|
|
6988 |
flags |= little_endian << 16;
|
|
6990 | 6989 |
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); |
6991 | 6990 |
target_disas(logfile, pc_start, ctx.nip - pc_start, flags); |
6992 | 6991 |
fprintf(logfile, "\n"); |
b/target-ppc/translate_init.c | ||
---|---|---|
314 | 314 |
{ |
315 | 315 |
gen_op_store_601_rtcl(); |
316 | 316 |
} |
317 |
|
|
318 |
static void spr_write_hid0_601 (void *opaque, int sprn) |
|
319 |
{ |
|
320 |
DisasContext *ctx = opaque; |
|
321 |
|
|
322 |
gen_op_store_hid0_601(); |
|
323 |
/* Must stop the translation as endianness may have changed */ |
|
324 |
GEN_STOP(ctx); |
|
325 |
} |
|
317 | 326 |
#endif |
318 | 327 |
|
319 | 328 |
/* Unified bats */ |
... | ... | |
3259 | 3268 |
/* XXX : not implemented */ |
3260 | 3269 |
spr_register(env, SPR_HID0, "HID0", |
3261 | 3270 |
SPR_NOACCESS, SPR_NOACCESS, |
3262 |
&spr_read_generic, &spr_write_generic,
|
|
3271 |
&spr_read_generic, &spr_write_hid0_601,
|
|
3263 | 3272 |
0x80010080); |
3264 | 3273 |
/* XXX : not implemented */ |
3265 | 3274 |
spr_register(env, SPR_HID1, "HID1", |
Also available in: Unified diff