mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-08-12 19:25:08 +00:00
Replace it wth an explicit opcode parameter that is passed around. That is both slightly easier to reason about (to trace where it comes from) and slightly faster, since it can be read from a register. On my machine takes booting to "Welcome to Macintosh" being output in a verbose boot of Mac OS X 10.2.8 from 31.8s to 30.6s (average of 5 runs, measured using deterministic mode and looking at when execution reaches PC 0x90004a88).
138 lines
4.4 KiB
C++
138 lines
4.4 KiB
C++
/*
|
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
|
Copyright (C) 2018-21 divingkatae and maximum
|
|
(theweirdo) spatium
|
|
|
|
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/** @file PowerPC Memory Management Unit definitions. */
|
|
|
|
#ifndef PPCMMU_H
|
|
#define PPCMMU_H
|
|
|
|
#include <devices/memctrl/memctrlbase.h>
|
|
|
|
#include <cinttypes>
|
|
#include <functional>
|
|
|
|
class MMIODevice;
|
|
|
|
/* Uncomment this to exhaustive MMU integrity checks. */
|
|
//#define MMU_INTEGRITY_CHECKS
|
|
|
|
/** generic PowerPC BAT descriptor (MMU internal state) */
|
|
typedef struct PPC_BAT_entry {
|
|
bool valid; /* BAT entry valid for MPC601 */
|
|
uint8_t access; /* copy of Vs | Vp bits */
|
|
uint8_t prot; /* copy of PP bits */
|
|
uint32_t phys_hi; /* high-order bits for physical address generation */
|
|
uint32_t hi_mask; /* mask for high-order logical address bits */
|
|
uint32_t bepi; /* copy of Block effective page index */
|
|
} PPC_BAT_entry;
|
|
|
|
/** Block address translation types. */
|
|
enum BATType : int {
|
|
IBAT,
|
|
DBAT
|
|
};
|
|
|
|
/** TLB types. */
|
|
enum TLBType : int {
|
|
ITLB,
|
|
DTLB
|
|
};
|
|
|
|
/** Result of the block address translation. */
|
|
typedef struct BATResult {
|
|
bool hit;
|
|
uint8_t prot;
|
|
uint32_t phys;
|
|
} BATResult;
|
|
|
|
/** Result of the page address translation. */
|
|
typedef struct PATResult {
|
|
uint32_t phys;
|
|
uint8_t prot;
|
|
uint8_t pte_c_status; // status of the C bit of the PTE
|
|
} PATResult;
|
|
|
|
/** DMA memory mapping result. */
|
|
typedef struct MapDmaResult {
|
|
uint32_t type;
|
|
bool is_writable;
|
|
// for memory regions
|
|
uint8_t* host_va;
|
|
// for MMIO regions
|
|
MMIODevice* dev_obj;
|
|
uint32_t dev_base;
|
|
} MapDmaResult;
|
|
|
|
constexpr uint32_t PPC_PAGE_SIZE_BITS = 12;
|
|
constexpr uint32_t PPC_PAGE_SIZE = (1 << PPC_PAGE_SIZE_BITS);
|
|
constexpr uint32_t PPC_PAGE_MASK = ~(PPC_PAGE_SIZE - 1);
|
|
constexpr uint32_t TLB_SIZE = 4096;
|
|
constexpr uint32_t TLB2_WAYS = 4;
|
|
constexpr uint32_t TLB_INVALID_TAG = 0xFFFFFFFF;
|
|
|
|
typedef struct TLBEntry {
|
|
uint32_t tag;
|
|
uint16_t flags;
|
|
uint16_t lru_bits;
|
|
union {
|
|
struct { // for memory pages
|
|
int64_t host_va_offs_r;
|
|
int64_t host_va_offs_w;
|
|
};
|
|
struct { // for MMIO pages
|
|
AddressMapEntry* rgn_desc;
|
|
int64_t dev_base_va;
|
|
};
|
|
};
|
|
uint32_t phys_tag;
|
|
uint32_t reserved;
|
|
} TLBEntry;
|
|
|
|
enum TLBFlags : uint16_t {
|
|
PAGE_MEM = 1 << 0, // memory page backed by host memory
|
|
PAGE_IO = 1 << 1, // memory mapped I/O page
|
|
PAGE_NOPHYS = 1 << 2, // no physical storage for this page (unmapped)
|
|
TLBE_FROM_BAT = 1 << 3, // TLB entry has been translated with BAT
|
|
TLBE_FROM_PAT = 1 << 4, // TLB entry has been translated with PAT
|
|
PAGE_WRITABLE = 1 << 5, // page is writable
|
|
PTE_SET_C = 1 << 6, // tells if C bit of the PTE needs to be updated
|
|
};
|
|
|
|
extern std::function<void(uint32_t bat_reg)> ibat_update;
|
|
extern std::function<void(uint32_t bat_reg)> dbat_update;
|
|
|
|
extern MapDmaResult mmu_map_dma_mem(uint32_t addr, uint32_t size, bool allow_mmio);
|
|
|
|
extern void mmu_change_mode(void);
|
|
extern void mmu_pat_ctx_changed();
|
|
extern void tlb_flush_entry(uint32_t ea);
|
|
|
|
extern uint64_t mem_read_dbg(uint32_t opcode, uint32_t virt_addr, uint32_t size);
|
|
uint8_t *mmu_translate_imem(uint32_t vaddr, uint32_t *paddr = nullptr);
|
|
bool mmu_translate_dbg(uint32_t guest_va, uint32_t &guest_pa);
|
|
|
|
template <class T>
|
|
extern T mmu_read_vmem(uint32_t opcode, uint32_t guest_va);
|
|
template <class T>
|
|
extern void mmu_write_vmem(uint32_t opcode, uint32_t guest_va, T value);
|
|
|
|
#endif // PPCMMU_H
|