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.h208
1 files changed, 128 insertions, 80 deletions
diff --git a/src/devices/cpu/mips/mips1.h b/src/devices/cpu/mips/mips1.h
index d77bdef3cdb..3ae34e4b69f 100644
--- a/src/devices/cpu/mips/mips1.h
+++ b/src/devices/cpu/mips/mips1.h
@@ -9,21 +9,8 @@
class mips1core_device_base : public cpu_device
{
public:
- // floating point coprocessor revision numbers recognised by RISC/os 4.52 and IRIX
- enum fpu_rev_t : u32
- {
- MIPS_R2360 = 0x0100, // MIPS R2360 Floating Point Board
- MIPS_R2010 = 0x0200, // MIPS R2010 VLSI Floating Point Chip
- MIPS_R2010A = 0x0310, // MIPS R2010A VLSI Floating Point Chip
- MIPS_R3010 = 0x0320, // MIPS R3010 VLSI Floating Point Chip
- MIPS_R3010A = 0x0330, // MIPS R3010A VLSI Floating Point Chip
- MIPS_R3010Av4 = 0x0340, // MIPS R3010A VLSI Floating Point Chip
- MIPS_R6010 = 0x0400, // MIPS R6010 Floating Point Chip
- };
-
// device configuration
void set_endianness(endianness_t endianness) { m_endianness = endianness; }
- void set_fpurev(u32 revision) { m_hasfpu = true; m_fpurev = revision; }
// input lines
template <unsigned Coprocessor> auto in_brcond() { return m_in_brcond[Coprocessor].bind(); }
@@ -31,53 +18,40 @@ public:
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);
- enum registers
+ enum registers : unsigned
{
- // general purpose cpu registers
- MIPS1_R0, MIPS1_R1, MIPS1_R2, MIPS1_R3, MIPS1_R4, MIPS1_R5, MIPS1_R6, MIPS1_R7,
- MIPS1_R8, MIPS1_R9, MIPS1_R10, MIPS1_R11, MIPS1_R12, MIPS1_R13, MIPS1_R14, MIPS1_R15,
- MIPS1_R16, MIPS1_R17, MIPS1_R18, MIPS1_R19, MIPS1_R20, MIPS1_R21, MIPS1_R22, MIPS1_R23,
- MIPS1_R24, MIPS1_R25, MIPS1_R26, MIPS1_R27, MIPS1_R28, MIPS1_R29, MIPS1_R30, MIPS1_R31,
+ MIPS1_R0 = 0,
+ MIPS1_COP0 = 32,
+ MIPS1_F0 = 64,
- // other cpu registers
+ MIPS1_PC = 80,
MIPS1_HI,
MIPS1_LO,
- MIPS1_PC,
-
- // coprocessor 0 registers
- MIPS1_COP0_INDEX, // reg 0, tlb only
- MIPS1_COP0_RANDOM, // reg 1, tlb only
- MIPS1_COP0_ENTRYLO, // reg 2, tlb only
- MIPS1_COP0_BUSCTRL, // reg 2, r3041 only
- MIPS1_COP0_CONFIG, // reg 3, r3041/r3071/r3081 only
- MIPS1_COP0_CONTEXT, // reg 4, tlb only
- MIPS1_COP0_BADVADDR, // reg 8
- MIPS1_COP0_COUNT, // reg 9, r3041 only
- MIPS1_COP0_ENTRYHI, // reg 10, tlb only
- MIPS1_COP0_PORTSIZE, // reg 10, r3041 only
- MIPS1_COP0_COMPARE, // reg 11, r3041 only
- MIPS1_COP0_SR, // reg 12
- MIPS1_COP0_CAUSE, // reg 13
- MIPS1_COP0_EPC, // reg 14
- MIPS1_COP0_PRID, // reg 15
+ MIPS1_FCR30,
+ MIPS1_FCR31,
};
- enum exception : int
+ enum exception : u32
{
- EXCEPTION_INTERRUPT = 0,
- EXCEPTION_TLBMOD = 1,
- EXCEPTION_TLBLOAD = 2,
- EXCEPTION_TLBSTORE = 3,
- EXCEPTION_ADDRLOAD = 4,
- EXCEPTION_ADDRSTORE = 5,
- EXCEPTION_BUSINST = 6,
- EXCEPTION_BUSDATA = 7,
- EXCEPTION_SYSCALL = 8,
- EXCEPTION_BREAK = 9,
- EXCEPTION_INVALIDOP = 10,
- EXCEPTION_BADCOP = 11,
- EXCEPTION_OVERFLOW = 12,
- EXCEPTION_TRAP = 13,
+ 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
@@ -127,6 +101,29 @@ protected:
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
@@ -158,7 +155,7 @@ protected:
virtual u32 execute_max_cycles() const override { return 40; }
virtual u32 execute_input_lines() const override { return 6; }
virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override { set_irq_line(inputnum, state); }
+ virtual void execute_set_input(int inputnum, int state) override;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
@@ -171,25 +168,18 @@ protected:
void dcache_map(address_map &map);
// interrupts
- void generate_exception(int exception, bool refill = false);
+ void generate_exception(u32 exception, bool refill = false);
void check_irqs();
- void set_irq_line(int irqline, int state);
// cop0
- virtual u32 get_cop0_reg(int const index);
- void set_cop0_reg(int const index, u32 const data);
virtual void handle_cop0(u32 const op);
+ virtual u32 get_cop0_reg(unsigned const reg);
+ virtual void set_cop0_reg(unsigned const reg, u32 const data);
- // cop1
- void set_cop1_creg(int const index, u32 const data);
- void handle_cop1(u32 const op);
-
- // generic coprocessor implementation
- template <unsigned Coprocessor> void handle_cop(u32 const op);
- template <unsigned Coprocessor> u32 get_cop_reg(int const index) { return m_cpr[Coprocessor][index]; }
- template <unsigned Coprocessor> void set_cop_reg(int const index, u32 const data) { m_cpr[Coprocessor][index] = data; }
- template <unsigned Coprocessor> u32 get_cop_creg(int const index) { return m_ccr[Coprocessor][index]; }
- template <unsigned Coprocessor> void set_cop_creg(int const index, u32 const data) { m_ccr[Coprocessor][index] = data; }
+ // other coprocessors
+ virtual void handle_cop1(u32 const op);
+ virtual void handle_cop2(u32 const op);
+ virtual void handle_cop3(u32 const op);
// load/store left/right opcodes
void lwl(u32 const op);
@@ -198,9 +188,13 @@ protected:
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 program_address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u32 program_address, U data);
- bool fetch(u32 program_address, std::function<void(u32)> &&apply);
+ 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);
+
+ // debug helpers
+ std::string debug_string(u32 string_pointer, unsigned const limit = 0);
+ std::string debug_string_array(u32 array_pointer);
// address spaces
const address_space_config m_program_config_be;
@@ -212,19 +206,16 @@ protected:
// configuration
u32 m_cpurev;
- bool m_hasfpu;
- u32 m_fpurev;
endianness_t m_endianness;
// core registers
u32 m_pc;
+ u32 m_r[32];
u32 m_hi;
u32 m_lo;
- u32 m_r[32];
- // COP registers
- u32 m_cpr[4][32];
- u32 m_ccr[4][32];
+ // cop0 registers
+ u32 m_cop0[32];
// internal stuff
int m_icount;
@@ -248,9 +239,54 @@ protected:
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
+ {
+ MIPS_R2360 = 0x0100, // MIPS R2360 Floating Point Board
+ MIPS_R2010 = 0x0200, // MIPS R2010 VLSI Floating Point Chip
+ MIPS_R2010A = 0x0310, // MIPS R2010A VLSI Floating Point Chip
+ MIPS_R3010 = 0x0320, // MIPS R3010 VLSI Floating Point Chip
+ MIPS_R3010A = 0x0330, // MIPS R3010A VLSI Floating Point Chip
+ MIPS_R3010Av4 = 0x0340, // MIPS R3010A VLSI Floating Point Chip
+ MIPS_R6010 = 0x0400, // MIPS R6010 Floating Point Chip
+ };
+
+ 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)
+ };
+
// device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -258,12 +294,24 @@ protected:
// device_memory_interface overrides
virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
- virtual u32 get_cop0_reg(int idx) override;
virtual void handle_cop0(u32 const op) override;
+ virtual u32 get_cop0_reg(unsigned const reg) override;
+
+ virtual void handle_cop1(u32 const op) override;
+ virtual void set_cop1_reg(unsigned const reg, u64 const data);
private:
u64 m_reset_time;
u32 m_tlb[64][2]; // 0 is hi, 1 is lo
+ unsigned m_tlb_mru[3][64];
+
+ // cop1 registers
+ u64 m_f[16];
+ u32 m_fcr0;
+ u32 m_fcr30;
+ u32 m_fcr31;
+
+ unsigned m_fpu_irq;
};
class r2000_device : public mips1_device_base
@@ -317,13 +365,13 @@ public:
r3052e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
-class r3071_device : public mips1core_device_base
+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);
};
-class r3081_device : public mips1core_device_base
+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);