summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sparc/sparc.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sparc/sparc.h')
-rw-r--r--src/devices/cpu/sparc/sparc.h245
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,