mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 05:29:43 +00:00
ppcmmu: re-arrange code to avoid formward declarations.
This commit is contained in:
parent
89e79d05cb
commit
bde5b71167
@ -699,14 +699,247 @@ uint8_t *mmu_translate_imem(uint32_t vaddr)
|
|||||||
return host_va;
|
return host_va;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tlb_flush_entry(uint32_t ea)
|
||||||
|
{
|
||||||
|
TLBEntry *tlb_entry, *tlb1, *tlb2;
|
||||||
|
|
||||||
|
const uint32_t tag = ea & ~0xFFFUL;
|
||||||
|
|
||||||
|
for (int m = 0; m < 6; m++) {
|
||||||
|
switch (m) {
|
||||||
|
case 0:
|
||||||
|
tlb1 = &itlb1_mode1[0];
|
||||||
|
tlb2 = &itlb2_mode1[0];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tlb1 = &itlb1_mode2[0];
|
||||||
|
tlb2 = &itlb2_mode2[0];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tlb1 = &itlb1_mode3[0];
|
||||||
|
tlb2 = &itlb2_mode3[0];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
tlb1 = &dtlb1_mode1[0];
|
||||||
|
tlb2 = &dtlb2_mode1[0];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
tlb1 = &dtlb1_mode2[0];
|
||||||
|
tlb2 = &dtlb2_mode2[0];
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
tlb1 = &dtlb1_mode3[0];
|
||||||
|
tlb2 = &dtlb2_mode3[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush primary TLB
|
||||||
|
tlb_entry = &tlb1[(ea >> PAGE_SIZE_BITS) & tlb_size_mask];
|
||||||
|
if (tlb_entry->tag == tag) {
|
||||||
|
tlb_entry->tag = TLB_INVALID_TAG;
|
||||||
|
//LOG_F(INFO, "Invalidated primary TLB entry at 0x%X", ea);
|
||||||
|
}
|
||||||
|
|
||||||
|
// flush secondary TLB
|
||||||
|
tlb_entry = &tlb2[((ea >> PAGE_SIZE_BITS) & tlb_size_mask) * TLB2_WAYS];
|
||||||
|
for (int i = 0; i < TLB2_WAYS; i++) {
|
||||||
|
if (tlb_entry[i].tag == tag) {
|
||||||
|
tlb_entry[i].tag = TLB_INVALID_TAG;
|
||||||
|
//LOG_F(INFO, "Invalidated secondary TLB entry at 0x%X", ea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <const TLBType tlb_type>
|
||||||
|
void tlb_flush_entries(TLBFlags type)
|
||||||
|
{
|
||||||
|
TLBEntry *m1_tlb, *m2_tlb, *m3_tlb;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (tlb_type == TLBType::ITLB) {
|
||||||
|
m1_tlb = &itlb1_mode1[0];
|
||||||
|
m2_tlb = &itlb1_mode2[0];
|
||||||
|
m3_tlb = &itlb1_mode3[0];
|
||||||
|
} else {
|
||||||
|
m1_tlb = &dtlb1_mode1[0];
|
||||||
|
m2_tlb = &dtlb1_mode2[0];
|
||||||
|
m3_tlb = &dtlb1_mode3[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush entries from the primary TLBs
|
||||||
|
for (i = 0; i < TLB_SIZE; i++) {
|
||||||
|
if (m1_tlb[i].flags & type) {
|
||||||
|
m1_tlb[i].tag = TLB_INVALID_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m2_tlb[i].flags & type) {
|
||||||
|
m2_tlb[i].tag = TLB_INVALID_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m3_tlb[i].flags & type) {
|
||||||
|
m3_tlb[i].tag = TLB_INVALID_TAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tlb_type == TLBType::ITLB) {
|
||||||
|
m1_tlb = &itlb2_mode1[0];
|
||||||
|
m2_tlb = &itlb2_mode2[0];
|
||||||
|
m3_tlb = &itlb2_mode3[0];
|
||||||
|
} else {
|
||||||
|
m1_tlb = &dtlb2_mode1[0];
|
||||||
|
m2_tlb = &dtlb2_mode2[0];
|
||||||
|
m3_tlb = &dtlb2_mode3[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush entries from the secondary TLBs
|
||||||
|
for (i = 0; i < TLB_SIZE * TLB2_WAYS; i++) {
|
||||||
|
if (dtlb2_mode1[i].flags & type) {
|
||||||
|
dtlb2_mode1[i].tag = TLB_INVALID_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dtlb2_mode2[i].flags & type) {
|
||||||
|
dtlb2_mode2[i].tag = TLB_INVALID_TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dtlb2_mode3[i].flags & type) {
|
||||||
|
dtlb2_mode3[i].tag = TLB_INVALID_TAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gTLBFlushBatEntries = false;
|
||||||
|
bool gTLBFlushPatEntries = false;
|
||||||
|
|
||||||
|
template <const TLBType tlb_type>
|
||||||
|
void tlb_flush_bat_entries()
|
||||||
|
{
|
||||||
|
if (!gTLBFlushBatEntries)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tlb_flush_entries<tlb_type>(TLBE_FROM_BAT);
|
||||||
|
|
||||||
|
gTLBFlushBatEntries = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <const TLBType tlb_type>
|
||||||
|
void tlb_flush_pat_entries()
|
||||||
|
{
|
||||||
|
if (!gTLBFlushPatEntries)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tlb_flush_entries<tlb_type>(TLBE_FROM_PAT);
|
||||||
|
|
||||||
|
gTLBFlushPatEntries = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mpc601_bat_update(uint32_t bat_reg)
|
||||||
|
{
|
||||||
|
PPC_BAT_entry *ibat_entry, *dbat_entry;
|
||||||
|
uint32_t bsm, hi_mask;
|
||||||
|
uint8_t key, pp, prot;
|
||||||
|
int upper_reg_num;
|
||||||
|
|
||||||
|
upper_reg_num = bat_reg & 0xFFFFFFFE;
|
||||||
|
|
||||||
|
ibat_entry = &ibat_array[(bat_reg - 528) >> 1];
|
||||||
|
dbat_entry = &dbat_array[(bat_reg - 528) >> 1];
|
||||||
|
|
||||||
|
if (ppc_state.spr[bat_reg | 1] & 0x40) {
|
||||||
|
bsm = ppc_state.spr[upper_reg_num + 1] & 0x3F;
|
||||||
|
hi_mask = ~((bsm << 17) | 0x1FFFF);
|
||||||
|
|
||||||
|
ibat_entry->valid = true;
|
||||||
|
ibat_entry->access = (ppc_state.spr[upper_reg_num] >> 2) & 3;
|
||||||
|
ibat_entry->prot = ppc_state.spr[upper_reg_num] & 3;
|
||||||
|
ibat_entry->hi_mask = hi_mask;
|
||||||
|
ibat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
|
||||||
|
ibat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
|
||||||
|
|
||||||
|
// copy IBAT entry to DBAT entry
|
||||||
|
*dbat_entry = *ibat_entry;
|
||||||
|
} else {
|
||||||
|
// disable the corresponding BAT paars
|
||||||
|
ibat_entry->valid = false;
|
||||||
|
dbat_entry->valid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MPC601 has unified BATs so we're going to fush both ITLB and DTLB
|
||||||
|
if (!gTLBFlushBatEntries) {
|
||||||
|
gTLBFlushBatEntries = true;
|
||||||
|
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::ITLB>);
|
||||||
|
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::DTLB>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppc_ibat_update(uint32_t bat_reg)
|
||||||
|
{
|
||||||
|
int upper_reg_num;
|
||||||
|
uint32_t bl, hi_mask;
|
||||||
|
PPC_BAT_entry* bat_entry;
|
||||||
|
|
||||||
|
upper_reg_num = bat_reg & 0xFFFFFFFE;
|
||||||
|
|
||||||
|
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
|
||||||
|
bat_entry = &ibat_array[(bat_reg - 528) >> 1];
|
||||||
|
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
|
||||||
|
hi_mask = ~((bl << 17) | 0x1FFFF);
|
||||||
|
|
||||||
|
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
|
||||||
|
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
|
||||||
|
bat_entry->hi_mask = hi_mask;
|
||||||
|
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
|
||||||
|
bat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
|
||||||
|
|
||||||
|
if (!gTLBFlushBatEntries) {
|
||||||
|
gTLBFlushBatEntries = true;
|
||||||
|
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::ITLB>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ppc_dbat_update(uint32_t bat_reg)
|
||||||
|
{
|
||||||
|
int upper_reg_num;
|
||||||
|
uint32_t bl, hi_mask;
|
||||||
|
PPC_BAT_entry* bat_entry;
|
||||||
|
|
||||||
|
upper_reg_num = bat_reg & 0xFFFFFFFE;
|
||||||
|
|
||||||
|
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
|
||||||
|
bat_entry = &dbat_array[(bat_reg - 536) >> 1];
|
||||||
|
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
|
||||||
|
hi_mask = ~((bl << 17) | 0x1FFFF);
|
||||||
|
|
||||||
|
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
|
||||||
|
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
|
||||||
|
bat_entry->hi_mask = hi_mask;
|
||||||
|
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
|
||||||
|
bat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
|
||||||
|
|
||||||
|
if (!gTLBFlushBatEntries) {
|
||||||
|
gTLBFlushBatEntries = true;
|
||||||
|
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::DTLB>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmu_pat_ctx_changed()
|
||||||
|
{
|
||||||
|
// Page address translation context changed so we need to flush
|
||||||
|
// all PAT entries from both ITLB and DTLB
|
||||||
|
if (!gTLBFlushPatEntries) {
|
||||||
|
gTLBFlushPatEntries = true;
|
||||||
|
add_ctx_sync_action(&tlb_flush_pat_entries<TLBType::ITLB>);
|
||||||
|
add_ctx_sync_action(&tlb_flush_pat_entries<TLBType::DTLB>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Forward declarations.
|
// Forward declarations.
|
||||||
static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size);
|
static uint32_t read_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t size);
|
||||||
static void write_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t value,
|
static void write_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t value,
|
||||||
uint32_t size);
|
uint32_t size);
|
||||||
|
|
||||||
template <const TLBType tlb_type>
|
|
||||||
void tlb_flush_bat_entries();
|
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
inline T mmu_read_vmem(uint32_t guest_va)
|
inline T mmu_read_vmem(uint32_t guest_va)
|
||||||
{
|
{
|
||||||
@ -969,242 +1202,6 @@ static void write_unaligned(uint32_t guest_va, uint8_t *host_va, uint32_t value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tlb_flush_entry(uint32_t ea)
|
|
||||||
{
|
|
||||||
TLBEntry *tlb_entry, *tlb1, *tlb2;
|
|
||||||
|
|
||||||
const uint32_t tag = ea & ~0xFFFUL;
|
|
||||||
|
|
||||||
for (int m = 0; m < 6; m++) {
|
|
||||||
switch (m) {
|
|
||||||
case 0:
|
|
||||||
tlb1 = &itlb1_mode1[0];
|
|
||||||
tlb2 = &itlb2_mode1[0];
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
tlb1 = &itlb1_mode2[0];
|
|
||||||
tlb2 = &itlb2_mode2[0];
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
tlb1 = &itlb1_mode3[0];
|
|
||||||
tlb2 = &itlb2_mode3[0];
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
tlb1 = &dtlb1_mode1[0];
|
|
||||||
tlb2 = &dtlb2_mode1[0];
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
tlb1 = &dtlb1_mode2[0];
|
|
||||||
tlb2 = &dtlb2_mode2[0];
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
tlb1 = &dtlb1_mode3[0];
|
|
||||||
tlb2 = &dtlb2_mode3[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush primary TLB
|
|
||||||
tlb_entry = &tlb1[(ea >> PAGE_SIZE_BITS) & tlb_size_mask];
|
|
||||||
if (tlb_entry->tag == tag) {
|
|
||||||
tlb_entry->tag = TLB_INVALID_TAG;
|
|
||||||
//LOG_F(INFO, "Invalidated primary TLB entry at 0x%X", ea);
|
|
||||||
}
|
|
||||||
|
|
||||||
// flush secondary TLB
|
|
||||||
tlb_entry = &tlb2[((ea >> PAGE_SIZE_BITS) & tlb_size_mask) * TLB2_WAYS];
|
|
||||||
for (int i = 0; i < TLB2_WAYS; i++) {
|
|
||||||
if (tlb_entry[i].tag == tag) {
|
|
||||||
tlb_entry[i].tag = TLB_INVALID_TAG;
|
|
||||||
//LOG_F(INFO, "Invalidated secondary TLB entry at 0x%X", ea);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <const TLBType tlb_type>
|
|
||||||
void tlb_flush_entries(TLBFlags type)
|
|
||||||
{
|
|
||||||
TLBEntry *m1_tlb, *m2_tlb, *m3_tlb;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (tlb_type == TLBType::ITLB) {
|
|
||||||
m1_tlb = &itlb1_mode1[0];
|
|
||||||
m2_tlb = &itlb1_mode2[0];
|
|
||||||
m3_tlb = &itlb1_mode3[0];
|
|
||||||
} else {
|
|
||||||
m1_tlb = &dtlb1_mode1[0];
|
|
||||||
m2_tlb = &dtlb1_mode2[0];
|
|
||||||
m3_tlb = &dtlb1_mode3[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush entries from the primary TLBs
|
|
||||||
for (i = 0; i < TLB_SIZE; i++) {
|
|
||||||
if (m1_tlb[i].flags & type) {
|
|
||||||
m1_tlb[i].tag = TLB_INVALID_TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m2_tlb[i].flags & type) {
|
|
||||||
m2_tlb[i].tag = TLB_INVALID_TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m3_tlb[i].flags & type) {
|
|
||||||
m3_tlb[i].tag = TLB_INVALID_TAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tlb_type == TLBType::ITLB) {
|
|
||||||
m1_tlb = &itlb2_mode1[0];
|
|
||||||
m2_tlb = &itlb2_mode2[0];
|
|
||||||
m3_tlb = &itlb2_mode3[0];
|
|
||||||
} else {
|
|
||||||
m1_tlb = &dtlb2_mode1[0];
|
|
||||||
m2_tlb = &dtlb2_mode2[0];
|
|
||||||
m3_tlb = &dtlb2_mode3[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush entries from the secondary TLBs
|
|
||||||
for (i = 0; i < TLB_SIZE * TLB2_WAYS; i++) {
|
|
||||||
if (dtlb2_mode1[i].flags & type) {
|
|
||||||
dtlb2_mode1[i].tag = TLB_INVALID_TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dtlb2_mode2[i].flags & type) {
|
|
||||||
dtlb2_mode2[i].tag = TLB_INVALID_TAG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dtlb2_mode3[i].flags & type) {
|
|
||||||
dtlb2_mode3[i].tag = TLB_INVALID_TAG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool gTLBFlushBatEntries = false;
|
|
||||||
bool gTLBFlushPatEntries = false;
|
|
||||||
|
|
||||||
template <const TLBType tlb_type>
|
|
||||||
void tlb_flush_bat_entries()
|
|
||||||
{
|
|
||||||
if (!gTLBFlushBatEntries)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tlb_flush_entries<tlb_type>(TLBE_FROM_BAT);
|
|
||||||
|
|
||||||
gTLBFlushBatEntries = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <const TLBType tlb_type>
|
|
||||||
void tlb_flush_pat_entries()
|
|
||||||
{
|
|
||||||
if (!gTLBFlushPatEntries)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tlb_flush_entries<tlb_type>(TLBE_FROM_PAT);
|
|
||||||
|
|
||||||
gTLBFlushPatEntries = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpc601_bat_update(uint32_t bat_reg)
|
|
||||||
{
|
|
||||||
PPC_BAT_entry *ibat_entry, *dbat_entry;
|
|
||||||
uint32_t bsm, hi_mask;
|
|
||||||
uint8_t key, pp, prot;
|
|
||||||
int upper_reg_num;
|
|
||||||
|
|
||||||
upper_reg_num = bat_reg & 0xFFFFFFFE;
|
|
||||||
|
|
||||||
ibat_entry = &ibat_array[(bat_reg - 528) >> 1];
|
|
||||||
dbat_entry = &dbat_array[(bat_reg - 528) >> 1];
|
|
||||||
|
|
||||||
if (ppc_state.spr[bat_reg | 1] & 0x40) {
|
|
||||||
bsm = ppc_state.spr[upper_reg_num + 1] & 0x3F;
|
|
||||||
hi_mask = ~((bsm << 17) | 0x1FFFF);
|
|
||||||
|
|
||||||
ibat_entry->valid = true;
|
|
||||||
ibat_entry->access = (ppc_state.spr[upper_reg_num] >> 2) & 3;
|
|
||||||
ibat_entry->prot = ppc_state.spr[upper_reg_num] & 3;
|
|
||||||
ibat_entry->hi_mask = hi_mask;
|
|
||||||
ibat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
|
|
||||||
ibat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
|
|
||||||
|
|
||||||
// copy IBAT entry to DBAT entry
|
|
||||||
*dbat_entry = *ibat_entry;
|
|
||||||
} else {
|
|
||||||
// disable the corresponding BAT paars
|
|
||||||
ibat_entry->valid = false;
|
|
||||||
dbat_entry->valid = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MPC601 has unified BATs so we're going to fush both ITLB and DTLB
|
|
||||||
if (!gTLBFlushBatEntries) {
|
|
||||||
gTLBFlushBatEntries = true;
|
|
||||||
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::ITLB>);
|
|
||||||
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::DTLB>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ppc_ibat_update(uint32_t bat_reg)
|
|
||||||
{
|
|
||||||
int upper_reg_num;
|
|
||||||
uint32_t bl, hi_mask;
|
|
||||||
PPC_BAT_entry* bat_entry;
|
|
||||||
|
|
||||||
upper_reg_num = bat_reg & 0xFFFFFFFE;
|
|
||||||
|
|
||||||
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
|
|
||||||
bat_entry = &ibat_array[(bat_reg - 528) >> 1];
|
|
||||||
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
|
|
||||||
hi_mask = ~((bl << 17) | 0x1FFFF);
|
|
||||||
|
|
||||||
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
|
|
||||||
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
|
|
||||||
bat_entry->hi_mask = hi_mask;
|
|
||||||
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
|
|
||||||
bat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
|
|
||||||
|
|
||||||
if (!gTLBFlushBatEntries) {
|
|
||||||
gTLBFlushBatEntries = true;
|
|
||||||
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::ITLB>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ppc_dbat_update(uint32_t bat_reg)
|
|
||||||
{
|
|
||||||
int upper_reg_num;
|
|
||||||
uint32_t bl, hi_mask;
|
|
||||||
PPC_BAT_entry* bat_entry;
|
|
||||||
|
|
||||||
upper_reg_num = bat_reg & 0xFFFFFFFE;
|
|
||||||
|
|
||||||
if (ppc_state.spr[upper_reg_num] & 3) { // is that BAT pair valid?
|
|
||||||
bat_entry = &dbat_array[(bat_reg - 536) >> 1];
|
|
||||||
bl = (ppc_state.spr[upper_reg_num] >> 2) & 0x7FF;
|
|
||||||
hi_mask = ~((bl << 17) | 0x1FFFF);
|
|
||||||
|
|
||||||
bat_entry->access = ppc_state.spr[upper_reg_num] & 3;
|
|
||||||
bat_entry->prot = ppc_state.spr[upper_reg_num + 1] & 3;
|
|
||||||
bat_entry->hi_mask = hi_mask;
|
|
||||||
bat_entry->phys_hi = ppc_state.spr[upper_reg_num + 1] & hi_mask;
|
|
||||||
bat_entry->bepi = ppc_state.spr[upper_reg_num] & hi_mask;
|
|
||||||
|
|
||||||
if (!gTLBFlushBatEntries) {
|
|
||||||
gTLBFlushBatEntries = true;
|
|
||||||
add_ctx_sync_action(&tlb_flush_bat_entries<TLBType::DTLB>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void mmu_pat_ctx_changed()
|
|
||||||
{
|
|
||||||
// Page address translation context changed so we need to flush
|
|
||||||
// all PAT entries from both ITLB and DTLB
|
|
||||||
if (!gTLBFlushPatEntries) {
|
|
||||||
gTLBFlushPatEntries = true;
|
|
||||||
add_ctx_sync_action(&tlb_flush_pat_entries<TLBType::ITLB>);
|
|
||||||
add_ctx_sync_action(&tlb_flush_pat_entries<TLBType::DTLB>);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MMU profiling. */
|
/* MMU profiling. */
|
||||||
#ifdef MMU_PROFILING
|
#ifdef MMU_PROFILING
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user