diff options
Diffstat (limited to 'src/devices/cpu/mips/mips1.h')
-rw-r--r-- | src/devices/cpu/mips/mips1.h | 208 |
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); |