summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/mips1.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/mips1.h')
-rw-r--r--src/devices/cpu/mips/mips1.h294
1 files changed, 80 insertions, 214 deletions
diff --git a/src/devices/cpu/mips/mips1.h b/src/devices/cpu/mips/mips1.h
index 306944d358f..5de7238281c 100644
--- a/src/devices/cpu/mips/mips1.h
+++ b/src/devices/cpu/mips/mips1.h
@@ -17,163 +17,28 @@ public:
void berr_w(int state) { m_bus_error = bool(state); }
protected:
- mips1core_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size);
+ mips1core_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size, bool cache_pws);
- enum registers : unsigned
- {
- MIPS1_R0 = 0,
- MIPS1_COP0 = 32,
- MIPS1_F0 = 64,
-
- MIPS1_PC = 80,
- MIPS1_HI,
- MIPS1_LO,
- MIPS1_FCR30,
- MIPS1_FCR31,
- };
-
- enum exception : u32
- {
- EXCEPTION_INTERRUPT = 0x00000000,
- EXCEPTION_TLBMOD = 0x00000004,
- EXCEPTION_TLBLOAD = 0x00000008,
- EXCEPTION_TLBSTORE = 0x0000000c,
- EXCEPTION_ADDRLOAD = 0x00000010,
- EXCEPTION_ADDRSTORE = 0x00000014,
- EXCEPTION_BUSINST = 0x00000018,
- EXCEPTION_BUSDATA = 0x0000001c,
- EXCEPTION_SYSCALL = 0x00000020,
- EXCEPTION_BREAK = 0x00000024,
- EXCEPTION_INVALIDOP = 0x00000028,
- EXCEPTION_BADCOP = 0x0000002c,
- EXCEPTION_OVERFLOW = 0x00000030,
- EXCEPTION_TRAP = 0x00000034,
-
- EXCEPTION_BADCOP0 = 0x0000002c,
- EXCEPTION_BADCOP1 = 0x1000002c,
- EXCEPTION_BADCOP2 = 0x2000002c,
- EXCEPTION_BADCOP3 = 0x3000002c,
- };
-
- enum cop0_reg : u8
- {
- COP0_Index = 0,
- COP0_Random = 1,
- COP0_EntryLo = 2,
- COP0_BusCtrl = 2, // r3041 only
- COP0_Config = 3, // r3041/r3071/r3081 only
- COP0_Context = 4,
- COP0_BadVAddr = 8,
- COP0_Count = 9, // r3041 only
- COP0_EntryHi = 10,
- COP0_PortSize = 10, // r3041 only
- COP0_Compare = 11, // r3041 only
- COP0_Status = 12,
- COP0_Cause = 13,
- COP0_EPC = 14,
- COP0_PRId = 15,
- };
-
- enum sr_mask : u32
- {
- SR_IEc = 0x00000001, // interrupt enable (current)
- SR_KUc = 0x00000002, // user mode (current)
- SR_IEp = 0x00000004, // interrupt enable (previous)
- SR_KUp = 0x00000008, // user mode (previous)
- SR_IEo = 0x00000010, // interrupt enable (old)
- SR_KUo = 0x00000020, // user mode (old)
- SR_IMSW0 = 0x00000100, // software interrupt 0 enable
- SR_IMSW1 = 0x00000200, // software interrupt 1 enable
- SR_IMEX0 = 0x00000400, // external interrupt 0 enable
- SR_IMEX1 = 0x00000800, // external interrupt 1 enable
- SR_IMEX2 = 0x00001000, // external interrupt 2 enable
- SR_IMEX3 = 0x00002000, // external interrupt 3 enable
- SR_IMEX4 = 0x00004000, // external interrupt 4 enable
- SR_IMEX5 = 0x00008000, // external interrupt 5 enable
- SR_IsC = 0x00010000, // isolate (data) cache
- SR_SwC = 0x00020000, // swap caches
- SR_PZ = 0x00040000, // cache parity zero
- SR_CM = 0x00080000, // cache match
- SR_PE = 0x00100000, // cache parity error
- SR_TS = 0x00200000, // tlb shutdown
- SR_BEV = 0x00400000, // boot exception vectors
- SR_RE = 0x02000000, // reverse endianness in user mode
- SR_COP0 = 0x10000000, // coprocessor 0 usable
- SR_COP1 = 0x20000000, // coprocessor 1 usable
- SR_COP2 = 0x40000000, // coprocessor 2 usable
- SR_COP3 = 0x80000000, // coprocessor 3 usable
-
- SR_KUIE = 0x0000003f, // all interrupt enable and user mode bits
- SR_KUIEpc = 0x0000000f, // previous and current interrupt enable and user mode bits
- SR_KUIEop = 0x0000003c, // old and previous interrupt enable and user mode bits
- SR_IM = 0x0000ff00, // all interrupt mask bits
- };
-
- enum cause_mask : u32
- {
- CAUSE_EXCCODE = 0x0000007c, // exception code
- CAUSE_IPSW0 = 0x00000100, // software interrupt 0 pending
- CAUSE_IPSW1 = 0x00000200, // software interrupt 1 pending
- CAUSE_IPEX0 = 0x00000400, // external interrupt 0 pending
- CAUSE_IPEX1 = 0x00000800, // external interrupt 1 pending
- CAUSE_IPEX2 = 0x00001000, // external interrupt 2 pending
- CAUSE_IPEX3 = 0x00002000, // external interrupt 3 pending
- CAUSE_IPEX4 = 0x00004000, // external interrupt 4 pending
- CAUSE_IPEX5 = 0x00008000, // external interrupt 5 pending
- CAUSE_IP = 0x0000ff00, // interrupt pending
- CAUSE_CE = 0x30000000, // co-processor error
- CAUSE_BD = 0x80000000, // branch delay
-
- CAUSE_IPEX = 0x0000fc00, // external interrupt pending
- };
-
- enum entryhi_mask : u32
- {
- EH_VPN = 0xfffff000, // virtual page number
- EH_ASID = 0x00000fc0, // address space identifier
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- EH_WM = 0xffffffc0, // write mask
- };
- enum entrylo_mask : u32
- {
- EL_PFN = 0xfffff000, // physical frame
- EL_N = 0x00000800, // noncacheable
- EL_D = 0x00000400, // dirty
- EL_V = 0x00000200, // valid
- EL_G = 0x00000100, // global
-
- EL_WM = 0xffffff00, // write mask
- };
- enum context_mask : u32
- {
- PTE_BASE = 0xffe00000, // base address of page table
- BAD_VPN = 0x001ffffc, // virtual address bits 30..12
- };
-
- // device_t overrides
- virtual void device_add_mconfig(machine_config &config) override;
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 40; }
- virtual u32 execute_input_lines() const override { return 6; }
+ // device_execute_interface implementation
+ virtual u32 execute_min_cycles() const noexcept override { return 1; }
+ virtual u32 execute_max_cycles() const noexcept override { return 40; }
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
- // device_memory_interface overrides
+ // device_memory_interface implementation
virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
- // device_disasm_interface overrides
+ // device_disasm_interface implementation
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- void icache_map(address_map &map);
- void dcache_map(address_map &map);
-
- // interrupts
+ // exceptions
void generate_exception(u32 exception, bool refill = false);
+ void address_error(int intention, u32 const address);
// cop0
virtual void handle_cop0(u32 const op);
@@ -191,25 +56,54 @@ protected:
void swl(u32 const op);
void swr(u32 const op);
- // memory accessors
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> load(u32 address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u32 address, U data, T mem_mask = ~T(0));
- bool fetch(u32 address, std::function<void(u32)> &&apply);
+ // memory
+ enum translate_result : unsigned { ERROR, UNCACHED, CACHED };
+ virtual translate_result translate(int intention, offs_t &address, bool debug);
+ template <typename T, bool Aligned = true, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> load(u32 address, U &&apply);
+ template <typename T, bool Aligned = true> void store(u32 address, T data, T mem_mask = ~T(0));
+ void fetch(u32 address, std::function<void(u32)> &&apply);
- // debug helpers
- std::string debug_string(u32 string_pointer, unsigned const limit = 0);
- std::string debug_string_array(u32 array_pointer);
+ // cache
+ template <typename T> unsigned shift_factor(u32 address) const;
+ struct cache
+ {
+ cache(size_t size)
+ : size(size)
+ {
+ }
+
+ struct line
+ {
+ enum tag_mask : u32
+ {
+ INV = 0x0000'0001, // cache line invalid
+ };
+
+ void invalidate() { tag = INV; }
+ void update(u32 data, u32 mask = 0xffff'ffffU)
+ {
+ this->tag &= ~INV;
+ this->data = (this->data & ~mask) | (data & mask);
+ }
+
+ u32 tag;
+ u32 data;
+ };
+
+ size_t lines() const { return size / 4; }
+ void start() { line = std::make_unique<struct line[]>(lines()); }
+
+ size_t const size;
+ std::unique_ptr<struct line[]> line;
+ };
+ std::tuple<struct cache::line &, bool> cache_lookup(u32 address, bool invalidate, bool icache = false);
// address spaces
- const address_space_config m_program_config_be;
- const address_space_config m_program_config_le;
- const address_space_config m_icache_config;
- const address_space_config m_dcache_config;
-
- int m_data_spacenum;
+ address_space_config const m_program_config_be;
+ address_space_config const m_program_config_le;
// configuration
- u32 m_cpurev;
+ u32 const m_cpurev;
endianness_t m_endianness;
// core registers
@@ -223,7 +117,7 @@ protected:
// internal stuff
int m_icount;
- enum branch_state_t : unsigned
+ enum branch_state : unsigned
{
NONE = 0,
DELAY = 1, // delay slot instruction active
@@ -234,11 +128,13 @@ protected:
u32 m_branch_target;
// cache memory
- size_t const m_icache_size;
- size_t const m_dcache_size;
+ struct cache m_icache;
+ struct cache m_dcache;
+ translate_result const m_cache;
+ bool const m_cache_pws; // cache supports partial-word store
// I/O
- devcb_read_line m_in_brcond[4];
+ devcb_read_line::array<4> m_in_brcond;
bool m_bus_error;
};
@@ -246,7 +142,7 @@ class mips1_device_base : public mips1core_device_base
{
public:
// floating point coprocessor revision numbers recognised by RISC/os 4.52 and IRIX
- enum fpu_rev_t : u32
+ enum fpu_rev : u32
{
MIPS_R2360 = 0x0100, // MIPS R2360 Floating Point Board
MIPS_R2010 = 0x0200, // MIPS R2010 VLSI Floating Point Chip
@@ -260,44 +156,13 @@ public:
void set_fpu(u32 revision, unsigned interrupt = 3) { m_fcr0 = revision; m_fpu_irq = interrupt; }
protected:
- mips1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size);
-
- enum cp1_fcr31_mask : u32
- {
- FCR31_RM = 0x00000003, // rounding mode
-
- FCR31_FI = 0x00000004, // inexact operation flag
- FCR31_FU = 0x00000008, // underflow flag
- FCR31_FO = 0x00000010, // overflow flag
- FCR31_FZ = 0x00000020, // divide by zero flag
- FCR31_FV = 0x00000040, // invalid operation flag
-
- FCR31_EI = 0x00000080, // inexact operation enable
- FCR31_EU = 0x00000100, // underflow enable
- FCR31_EO = 0x00000200, // overflow enable
- FCR31_EZ = 0x00000400, // divide by zero enable
- FCR31_EV = 0x00000800, // invalid operation enable
-
- FCR31_CI = 0x00001000, // inexact operation cause
- FCR31_CU = 0x00002000, // underflow cause
- FCR31_CO = 0x00004000, // overflow cause
- FCR31_CZ = 0x00008000, // divide by zero cause
- FCR31_CV = 0x00010000, // invalid operation cause
- FCR31_CE = 0x00020000, // unimplemented operation cause
-
- FCR31_C = 0x00800000, // condition
-
- FCR31_FM = 0x0000007c, // flag mask
- FCR31_EM = 0x00000f80, // enable mask
- FCR31_CM = 0x0001f000, // cause mask (except unimplemented)
- };
+ mips1_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size, bool cache_pws);
- // device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
- // device_memory_interface overrides
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+ virtual translate_result translate(int intention, offs_t &address, bool debug) override;
virtual void handle_cop0(u32 const op) override;
virtual u32 get_cop0_reg(unsigned const reg) override;
@@ -323,70 +188,71 @@ private:
class r2000_device : public mips1_device_base
{
public:
- r2000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r2000_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
class r2000a_device : public mips1_device_base
{
public:
- r2000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r2000a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
class r3000_device : public mips1_device_base
{
public:
- r3000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r3000_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
class r3000a_device : public mips1_device_base
{
public:
- r3000a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
+ r3000a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size = 0, size_t dcache_size = 0);
};
class r3041_device : public mips1core_device_base
{
public:
- r3041_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ r3041_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
protected:
- virtual void device_start() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
};
class r3051_device : public mips1core_device_base
{
public:
- r3051_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ r3051_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class r3052_device : public mips1core_device_base
{
public:
- r3052_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ r3052_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class r3052e_device : public mips1_device_base
{
public:
- r3052e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ r3052e_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
class r3071_device : public mips1_device_base
{
public:
- r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
+ r3071_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
};
class r3081_device : public mips1_device_base
{
public:
- r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
+ r3081_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
};
class iop_device : public mips1core_device_base
{
public:
- iop_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ iop_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
};
DECLARE_DEVICE_TYPE(R2000, r2000_device)