diff options
Diffstat (limited to 'src/devices/cpu/sparc/sparc.h')
-rw-r--r-- | src/devices/cpu/sparc/sparc.h | 245 |
1 files changed, 205 insertions, 40 deletions
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index 488a9f38dfa..f61ddb30e5e 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -12,31 +12,28 @@ #include "sparcdasm.h" #include "sparc_intf.h" -#define SPARCV8 (1) #define LOG_FCODES (0) #if LOG_FCODES #include <map> #endif -class mb86901_device : public cpu_device, public sparc_mmu_host_interface, protected sparc_disassembler::config +class sparc_base_device : public cpu_device, public sparc_mmu_host_interface, protected sparc_disassembler::config { public: - mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + sparc_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); template <typename T> void set_mmu(T &&tag) { m_mmu.set_tag(std::forward<T>(tag)); } // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_stop() override; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; virtual void device_post_load() override; - virtual void device_resolve_objects() override; + virtual void device_resolve_objects() override ATTR_COLD; // device_execute_interface overrides - virtual uint32_t execute_min_cycles() const override; - virtual uint32_t execute_max_cycles() const override; - virtual uint32_t execute_input_lines() const override; + virtual uint32_t execute_min_cycles() const noexcept override; + virtual uint32_t execute_max_cycles() const noexcept override; virtual void execute_run() override; virtual void execute_set_input(int inputnum, int state) override; @@ -75,11 +72,8 @@ protected: void execute_rett(uint32_t op); void execute_saverestore(uint32_t op); void execute_jmpl(uint32_t op); -#if SPARCV8 - void execute_mul(uint32_t op); - void execute_div(uint32_t op); -#endif inline void execute_group2(uint32_t op); + virtual bool execute_extra_group2(uint32_t op) = 0; inline void execute_ldd(uint32_t op); inline void execute_ld(uint32_t op); @@ -102,10 +96,8 @@ protected: void execute_store(uint32_t op); void execute_ldstub(uint32_t op); -#if SPARCV8 - void execute_swap(uint32_t op); -#endif inline void execute_group3(uint32_t op); + virtual bool execute_extra_group3(uint32_t op) = 0; enum set_cc { @@ -122,12 +114,23 @@ protected: bool evaluate_condition(uint32_t op); inline void execute_bicc(uint32_t op); + bool evaluate_fp_condition(uint32_t op); + inline void execute_fbfcc(uint32_t op); void execute_ticc(uint32_t op); void select_trap(); void execute_trap(); + virtual void update_tt() = 0; + + void check_fdiv_zero_exception(); + bool check_fp_exceptions(); + bool get_fpr32(uint32_t &data, const uint32_t rd); + bool get_fpr64(uint64_t &data, const uint32_t rd); + bool set_fpr32(const uint32_t rd, const uint32_t data); + bool set_fpr64(const uint32_t rd, const uint64_t data); void complete_instruction_execution(uint32_t op); inline void dispatch_instruction(uint32_t op); + virtual bool dispatch_extra_instruction(uint32_t op) = 0; void complete_fp_execution(uint32_t /*op*/); inline void execute_step(); @@ -148,14 +151,16 @@ protected: void log_fcodes(); #endif - required_device<sparc_mmu_interface> m_mmu; + optional_device<sparc_mmu_interface> m_mmu; // address spaces - address_space_config m_default_config; + address_space_config m_debugger_config; + address_space_config m_asi_config[0x10]; + memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_asi[0x20]; // memory access - uint32_t read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask); - void write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask); + inline uint32_t read_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask = 0xffffffff); + inline void write_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask = 0xffffffff); // helpers for the disassembler virtual uint64_t get_reg_r(unsigned index) const override; @@ -165,7 +170,7 @@ protected: virtual uint8_t get_fcc(unsigned index) const override; // general-purpose registers - uint32_t m_r[120]; + uint32_t m_r[136]; // FPU registers uint32_t m_fpr[32]; @@ -198,17 +203,14 @@ protected: bool m_illegal_instruction; bool m_mem_address_not_aligned; bool m_fp_disabled; + bool m_cp_disabled; bool m_fp_exception; - bool m_cp_disabled; // SPARCv8 - bool m_cp_exception; // SPARCv8 - bool m_unimplemented_FLUSH; // SPARCv8 - bool m_r_register_access_error; // SPARCv8 - bool m_instruction_access_error; // SPARCv8 + bool m_fp_exception_pending; + uint32_t m_fpr_pending; + uint32_t m_pending_fpr; + bool m_cp_exception; bool m_instruction_access_exception; - bool m_data_access_error; // SPARCv8 - bool m_data_store_error; // SPARCv8 bool m_data_access_exception; - bool m_division_by_zero; // SPARCv8 bool m_trap_instruction; bool m_window_underflow; bool m_window_overflow; @@ -221,16 +223,16 @@ protected: uint8_t m_cp_sequence_err; // fields separated out from PSR (Processor State Register) - uint8_t m_impl; // implementation (always 0 in MB86901) - uint8_t m_ver; // version (always 0 in MB86901) - uint8_t m_icc; // integer condition codes + uint8_t m_impl; // implementation (always 0 in SPARCv7) + uint8_t m_ver; // version (always 0 in SPARCv7) + uint8_t m_icc; // integer condition codes bool m_ec; // enable coprocessor bool m_ef; // enable FPU - uint8_t m_pil; // processor interrupt level + uint8_t m_pil; // processor interrupt level bool m_s; // supervisor mode bool m_ps; // prior S state bool m_et; // enable traps - uint8_t m_cwp; // current window pointer + uint8_t m_cwp; // current window pointer bool m_alu_op3_assigned[64]; bool m_ldst_op3_assigned[64]; @@ -238,6 +240,7 @@ protected: // register windowing helpers uint32_t* m_regs[32]; + int m_nwindows; // other internal states bool m_privileged_asr[32]; @@ -246,7 +249,6 @@ protected: bool m_no_annul; bool m_hold_bus; int m_icount; - int m_stashed_icount; int m_insn_space; int m_data_space; @@ -263,14 +265,171 @@ protected: bool m_log_fcodes; #endif - // processor configuration - static const int NWINDOWS; - std::function<void (sparc_disassembler *)> m_asi_desc_adder; + static const char *const DEFAULT_ASI_NAMES[16]; +}; + +class sparcv7_device : public sparc_base_device +{ +public: + sparcv7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + sparcv7_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual bool execute_extra_group2(uint32_t op) override; + virtual bool execute_extra_group3(uint32_t op) override; + virtual bool dispatch_extra_instruction(uint32_t op) override; + virtual void update_tt() override; +}; + +class sparcv8_device : public sparc_base_device +{ +public: + sparcv8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_disasm_interface overrides + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; + +protected: + sparcv8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + virtual bool execute_extra_group2(uint32_t op) override; + virtual bool execute_extra_group3(uint32_t op) override; + virtual bool dispatch_extra_instruction(uint32_t op) override; + virtual void update_tt() override; + +private: + void execute_mul(uint32_t op); + void execute_div(uint32_t op); + void execute_swap(uint32_t op); + + bool m_unimplemented_FLUSH; + bool m_r_register_access_error; + bool m_instruction_access_error; + bool m_data_access_error; + bool m_data_store_error; + bool m_division_by_zero; +}; + +class mb86930_device : public sparcv8_device +{ +public: + mb86930_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // device_disasm_interface overrides + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; + + auto cs0_read_cb() { return m_cs_r[0].bind(); } + auto cs0_write_cb() { return m_cs_w[0].bind(); } + auto cs1_read_cb() { return m_cs_r[1].bind(); } + auto cs1_write_cb() { return m_cs_w[1].bind(); } + auto cs2_read_cb() { return m_cs_r[2].bind(); } + auto cs2_write_cb() { return m_cs_w[2].bind(); } + auto cs3_read_cb() { return m_cs_r[3].bind(); } + auto cs3_write_cb() { return m_cs_w[3].bind(); } + auto cs4_read_cb() { return m_cs_r[4].bind(); } + auto cs4_write_cb() { return m_cs_w[4].bind(); } + auto cs5_read_cb() { return m_cs_r[5].bind(); } + auto cs5_write_cb() { return m_cs_w[5].bind(); } + +protected: + // device-level overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_post_load() override; + + virtual bool execute_extra_group2(uint32_t op) override; + + void execute_divscc(uint32_t op); + void execute_scan(uint32_t op); + + uint32_t biu_ctrl_r(offs_t offset, uint32_t mem_mask); + void biu_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t lock_ctrl_r(offs_t offset, uint32_t mem_mask); + void lock_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t lock_ctrl_save_r(offs_t offset, uint32_t mem_mask); + void lock_ctrl_save_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t cache_status_r(offs_t offset, uint32_t mem_mask); + void cache_status_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t restore_lock_ctrl_r(offs_t offset, uint32_t mem_mask); + void restore_lock_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t system_support_ctrl_r(offs_t offset, uint32_t mem_mask); + void system_support_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t same_page_mask_r(offs_t offset, uint32_t mem_mask); + void same_page_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t addr_range_spec_r(offs_t offset, uint32_t mem_mask); + void addr_range_spec_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t addr_mask_r(offs_t offset, uint32_t mem_mask); + void addr_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t wait_specifier_r(offs_t offset, uint32_t mem_mask); + void wait_specifier_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t timer_r(offs_t offset, uint32_t mem_mask); + void timer_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t timer_preload_r(offs_t offset, uint32_t mem_mask); + void timer_preload_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + template <uint8_t Asi> uint32_t mmu_r(offs_t offset, uint32_t mem_mask); + template <uint8_t Asi> void mmu_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t icache_lock_r(offs_t offset, uint32_t mem_mask); + void icache_lock_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t dcache_lock_r(offs_t offset, uint32_t mem_mask); + void dcache_lock_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + uint32_t icache_tag_r(offs_t offset, uint32_t mem_mask); + void icache_tag_w(offs_t offset, uint32_t data, uint32_t mem_mask); + uint32_t icache_data_r(offs_t offset, uint32_t mem_mask); + void icache_data_w(offs_t offset, uint32_t data, uint32_t mem_mask); + + u32 dcache_tag_r(offs_t offset, u32 mem_mask); + void dcache_tag_w(offs_t offset, u32 data, u32 mem_mask); + u32 dcache_data_r(offs_t offset, u32 mem_mask); + void dcache_data_w(offs_t offset, u32 data, u32 mem_mask); + + void control_map(address_map &map) ATTR_COLD; + void icache_lock_map(address_map &map) ATTR_COLD; + void dcache_lock_map(address_map &map) ATTR_COLD; + template <uint8_t Asi> void mmu_map(address_map &map) ATTR_COLD; + void icache_tag_map(address_map &map) ATTR_COLD; + void icache_data_map(address_map &map) ATTR_COLD; + void dcache_tag_map(address_map &map) ATTR_COLD; + void dcache_data_map(address_map &map) ATTR_COLD; + + void update_addr_masks(); + void update_wait_states(); + + devcb_read32::array<6> m_cs_r; + devcb_write32::array<6> m_cs_w; + + u32 m_ssctrl; + u32 m_spmr; + u64 m_spmr_mask; + u32 m_arsr[6]; + u32 m_amr[6]; + u64 m_full_masks[6]; + u64 m_full_ranges[6]; + u64 m_last_masked_addr; + int m_same_page_waits[6]; + int m_other_page_waits[6]; + + u32 m_wssr[3]; }; // device type definition -DECLARE_DEVICE_TYPE(MB86901, mb86901_device) +DECLARE_DEVICE_TYPE(SPARCV7, sparcv7_device) +DECLARE_DEVICE_TYPE(SPARCV8, sparcv8_device) +DECLARE_DEVICE_TYPE(MB86930, mb86930_device) enum { @@ -297,6 +456,12 @@ enum SPARC_S, SPARC_PS, + SPARC_FSR, + SPARC_F0, SPARC_F1, SPARC_F2, SPARC_F3, SPARC_F4, SPARC_F5, SPARC_F6, SPARC_F7, + SPARC_F8, SPARC_F9, SPARC_F10, SPARC_F11, SPARC_F12, SPARC_F13, SPARC_F14, SPARC_F15, + SPARC_F16, SPARC_F17, SPARC_F18, SPARC_F19, SPARC_F20, SPARC_F21, SPARC_F22, SPARC_F23, + SPARC_F24, SPARC_F25, SPARC_F26, SPARC_F27, SPARC_F28, SPARC_F29, SPARC_F30, SPARC_F31, + SPARC_R0, SPARC_R1, SPARC_R2, SPARC_R3, SPARC_R4, SPARC_R5, SPARC_R6, SPARC_R7, SPARC_R8, SPARC_R9, SPARC_R10, SPARC_R11, SPARC_R12, SPARC_R13, SPARC_R14, SPARC_R15, SPARC_R16, SPARC_R17, SPARC_R18, SPARC_R19, SPARC_R20, SPARC_R21, SPARC_R22, SPARC_R23, SPARC_R24, SPARC_R25, SPARC_R26, SPARC_R27, SPARC_R28, SPARC_R29, SPARC_R30, SPARC_R31, SPARC_R32, SPARC_R33, SPARC_R34, SPARC_R35, SPARC_R36, SPARC_R37, SPARC_R38, SPARC_R39, SPARC_R40, SPARC_R41, SPARC_R42, SPARC_R43, SPARC_R44, SPARC_R45, SPARC_R46, SPARC_R47, |