From 5b9e7bcccf52458e365b8759c8a0c4b5e51d166e Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 22 Jun 2016 11:10:42 +1000 Subject: [PATCH] SPARC disassembler improvements: [Vas Crabb] * Fix addcc/andcc in SPARCv7 mode and simplify integer op tables * Allow ASI descriptions to be supplied with MCFG macro sun4: add SPARC ASI descriptions [Vas Crabb] --- src/devices/cpu/sparc/mb86901.cpp | 2 - src/devices/cpu/sparc/sparc.h | 8 +++ src/devices/cpu/sparc/sparcdasm.cpp | 99 +++++++++++++++-------------- src/devices/cpu/sparc/sparcdasm.h | 8 ++- src/mame/drivers/sun4.cpp | 37 +++++++++++ 5 files changed, 103 insertions(+), 51 deletions(-) diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp index 04e41e94e60..4b8c1a22a0b 100644 --- a/src/devices/cpu/sparc/mb86901.cpp +++ b/src/devices/cpu/sparc/mb86901.cpp @@ -24,8 +24,6 @@ #define SPARCV8 (0) -CPU_DISASSEMBLE( sparc ); - const device_type MB86901 = &device_creator; const int mb86901_device::WINDOW_COUNT = 7; diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index a646a80040c..a5e31751ed2 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -40,6 +40,10 @@ #define SPARC_INT15 31 #define SPARC_TRAP_INSTRUCTION 128 +// TODO: when there are more SPARC CPUs, move setter to a base class +#define MCFG_SPARC_ADD_ASI_DESC(desc) \ + mb86901_device::add_asi_desc(*device, desc); + class mb86901_device : public cpu_device { public: @@ -76,7 +80,11 @@ public: void hold_bus() { m_hold_bus = true; } void release_bus() { m_hold_bus = false; } + template static void add_asi_desc(device_t &device, const T &desc) { return downcast(device).add_asi_desc(desc); } + protected: + template void add_asi_desc(const T &desc) { m_dasm.add_asi_desc(desc); } + bool invoke_queued_traps(); bool check_main_traps(UINT32 op, bool privileged, UINT32 alignment, UINT8 registeralign, bool noimmediate); diff --git a/src/devices/cpu/sparc/sparcdasm.cpp b/src/devices/cpu/sparc/sparcdasm.cpp index 357e391702d..56dd53068a8 100644 --- a/src/devices/cpu/sparc/sparcdasm.cpp +++ b/src/devices/cpu/sparc/sparcdasm.cpp @@ -86,45 +86,40 @@ const sparc_disassembler::branch_desc sparc_disassembler::CBCCC_DESC = { } }; -const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::SIMPLE_INT_OP_DESC[] = { - { 0x00, { 7, false, "add" } }, - { 0x01, { 7, true, "and" } }, - { 0x02, { 7, true, "or" } }, - { 0x03, { 7, true, "xor" } }, - { 0x04, { 7, false, "sub" } }, - { 0x05, { 7, true, "andn" } }, - { 0x06, { 7, true, "orn" } }, - { 0x07, { 7, true, "xnor" } }, - { 0x08, { 7, false, "addx" } }, - { 0x09, { 9, false, "mulx" } }, - { 0x0a, { 8, false, "umul" } }, - { 0x0b, { 8, false, "smul" } }, - { 0x0c, { 7, false, "subx" } }, - { 0x0d, { 9, false, "udivx" } }, - { 0x0e, { 8, false, "udiv" } }, - { 0x0f, { 8, false, "sdiv" } }, - { 0x10, { 8, false, "addcc" } }, - { 0x11, { 8, true, "andcc" } }, - { 0x12, { 7, true, "orcc" } }, - { 0x13, { 7, true, "xorcc" } }, - { 0x14, { 7, false, "subcc" } }, - { 0x15, { 7, true, "andncc" } }, - { 0x16, { 7, true, "orncc" } }, - { 0x17, { 7, true, "xnorcc" } }, - { 0x18, { 7, false, "addxcc" } }, - { 0x1a, { 8, false, "umulcc" } }, - { 0x1b, { 8, false, "smulcc" } }, - { 0x1c, { 7, false, "subxcc" } }, - { 0x1e, { 8, false, "udivcc" } }, - { 0x1f, { 8, false, "sdivcc" } }, - { 0x20, { 7, false, "taddcc" } }, - { 0x21, { 7, false, "tsubcc" } }, - { 0x22, { 7, false, "taddcctv" } }, - { 0x23, { 7, false, "tsubcctv" } }, - { 0x24, { 7, false, "mulscc" } }, - { 0x2d, { 9, false, "sdivx" } }, - { 0x3c, { 7, false, "save" } }, - { 0x3d, { 7, false, "restore" } } +const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::V7_INT_OP_DESC[] = { + { 0x00, { false, "add" } }, { 0x10, { false, "addcc" } }, + { 0x01, { true, "and" } }, { 0x11, { true, "andcc" } }, + { 0x02, { true, "or" } }, { 0x12, { true, "orcc" } }, + { 0x03, { true, "xor" } }, { 0x13, { true, "xorcc" } }, + { 0x04, { false, "sub" } }, { 0x14, { false, "subcc" } }, + { 0x05, { true, "andn" } }, { 0x15, { true, "andncc" } }, + { 0x06, { true, "orn" } }, { 0x16, { true, "orncc" } }, + { 0x07, { true, "xnor" } }, { 0x17, { true, "xnorcc" } }, + { 0x08, { false, "addx" } }, { 0x18, { false, "addxcc" } }, + { 0x0c, { false, "subx" } }, { 0x1c, { false, "subxcc" } }, + + { 0x20, { false, "taddcc" } }, + { 0x21, { false, "tsubcc" } }, + { 0x22, { false, "taddcctv" } }, + { 0x23, { false, "tsubcctv" } }, + { 0x24, { false, "mulscc" } }, + + { 0x3c, { false, "save" } }, + { 0x3d, { false, "restore" } } +}; + +const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::V8_INT_OP_DESC[] = { + { 0x0a, { false, "umul" } }, { 0x1a, { false, "umulcc" } }, + { 0x0b, { false, "smul" } }, { 0x1b, { false, "smulcc" } }, + { 0x0e, { false, "udiv" } }, { 0x1e, { false, "udivcc" } }, + { 0x0f, { false, "sdiv" } }, { 0x1f, { false, "sdivcc" } } +}; + +const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::V9_INT_OP_DESC[] = { + { 0x09, { false, "mulx" } }, + { 0x0d, { false, "udivx" } }, + + { 0x2d, { false, "sdivx" } } }; const sparc_disassembler::state_reg_desc_map::value_type sparc_disassembler::V9_STATE_REG_DESC[] = { @@ -301,6 +296,12 @@ inline UINT32 sparc_disassembler::freg(UINT32 val, bool shift) const return (shift && (m_version >= 9)) ? ((val & 0x1e) | ((val << 5) & 0x20)) : val; } +template inline void sparc_disassembler::add_int_op_desc(const T &desc) +{ + for (const auto &it : desc) + m_int_op_desc.insert(it); +} + template inline void sparc_disassembler::add_fpop1_desc(const T &desc) { for (const auto &it : desc) @@ -346,7 +347,7 @@ sparc_disassembler::sparc_disassembler(unsigned version) FBFCC_DESC, // branch on floating-point condition codes (version == 8) ? CBCCC_DESC : EMPTY_BRANCH_DESC // branch on coprocessor condition codes, SPARCv8 } - , m_simple_int_op_desc(std::begin(SIMPLE_INT_OP_DESC), std::end(SIMPLE_INT_OP_DESC)) + , m_int_op_desc(std::begin(V7_INT_OP_DESC), std::end(V7_INT_OP_DESC)) , m_state_reg_desc() , m_fpop1_desc(std::begin(V7_FPOP1_DESC), std::end(V7_FPOP1_DESC)) , m_fpop2_desc(std::begin(V7_FPOP2_DESC), std::end(V7_FPOP2_DESC)) @@ -354,14 +355,20 @@ sparc_disassembler::sparc_disassembler(unsigned version) , m_asi_desc() , m_prftch_desc() { + if (m_version >= 8) + { + add_int_op_desc(V8_INT_OP_DESC); + } + if (m_version >= 9) { m_op_field_width = 11; - m_simple_int_op_desc.find(0x08)->second.mnemonic = "addc"; - m_simple_int_op_desc.find(0x0c)->second.mnemonic = "subc"; - m_simple_int_op_desc.find(0x18)->second.mnemonic = "addccc"; - m_simple_int_op_desc.find(0x1c)->second.mnemonic = "subccc"; + m_int_op_desc.find(0x08)->second.mnemonic = "addc"; + m_int_op_desc.find(0x0c)->second.mnemonic = "subc"; + m_int_op_desc.find(0x18)->second.mnemonic = "addccc"; + m_int_op_desc.find(0x1c)->second.mnemonic = "subccc"; + add_int_op_desc(V9_INT_OP_DESC); add_state_reg_desc(V9_STATE_REG_DESC), add_fpop1_desc(V9_FPOP1_DESC); @@ -654,8 +661,8 @@ offs_t sparc_disassembler::dasm(char *buf, offs_t pc, UINT32 op) const break; } { - const auto it(m_simple_int_op_desc.find(OP3)); - if ((it != m_simple_int_op_desc.end()) && (m_version >= it->second.min_version)) + const auto it(m_int_op_desc.find(OP3)); + if (it != m_int_op_desc.end()) { if (!USEIMM) print(buf, "%-*s%s,%s,%s", m_op_field_width, it->second.mnemonic, REG_NAMES[RS1], REG_NAMES[RS2], REG_NAMES[RD]); diff --git a/src/devices/cpu/sparc/sparcdasm.h b/src/devices/cpu/sparc/sparcdasm.h index e745de4721d..3a37c7307c4 100644 --- a/src/devices/cpu/sparc/sparcdasm.h +++ b/src/devices/cpu/sparc/sparcdasm.h @@ -97,7 +97,6 @@ private: struct int_op_desc { - unsigned min_version; bool hex_imm; const char *mnemonic; }; @@ -152,6 +151,7 @@ private: UINT32 freg(UINT32 val, bool shift) const; + template void add_int_op_desc(const T &desc); template void add_fpop1_desc(const T &desc); template void add_fpop2_desc(const T &desc); template void add_ldst_desc(const T &desc); @@ -167,7 +167,9 @@ private: static const branch_desc FBPFCC_DESC; static const branch_desc FBFCC_DESC; static const branch_desc CBCCC_DESC; - static const int_op_desc_map::value_type SIMPLE_INT_OP_DESC[]; + static const int_op_desc_map::value_type V7_INT_OP_DESC[]; + static const int_op_desc_map::value_type V8_INT_OP_DESC[]; + static const int_op_desc_map::value_type V9_INT_OP_DESC[]; static const state_reg_desc_map::value_type V9_STATE_REG_DESC[]; static const char * const MOVCC_CC_NAMES[8]; static const char * const MOVCC_COND_NAMES[32]; @@ -185,7 +187,7 @@ private: unsigned m_version; int m_op_field_width; branch_desc m_branch_desc[8]; - int_op_desc_map m_simple_int_op_desc; + int_op_desc_map m_int_op_desc; state_reg_desc_map m_state_reg_desc; fpop1_desc_map m_fpop1_desc; fpop2_desc_map m_fpop2_desc; diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp index ba95e54f0d8..9094c285447 100644 --- a/src/mame/drivers/sun4.cpp +++ b/src/mame/drivers/sun4.cpp @@ -429,6 +429,42 @@ #define PM_ACCESSED (0x02000000) // accessed flag #define PM_MODIFIED (0x01000000) // modified flag +namespace +{ +const sparc_disassembler::asi_desc_map::value_type sun4_asi_desc[] = { + { 0x10, { nullptr, "Flush I-Cache (Segment)" } }, + { 0x11, { nullptr, "Flush I-Cache (Page)" } }, + { 0x02, { nullptr, "System Space" } }, { 0x12, { nullptr, "Flush I-Cache (Context)" } }, + { 0x03, { nullptr, "Segment Map" } }, { 0x13, { nullptr, "Flush I-Cache (User)" } }, + { 0x04, { nullptr, "Page Map" } }, { 0x14, { nullptr, "Flush D-Cache (Segment)" } }, + { 0x05, { nullptr, "Block Copy" } }, { 0x15, { nullptr, "Flush D-Cache (Page)" } }, + { 0x06, { nullptr, "Region Map" } }, { 0x16, { nullptr, "Flush D-Cache (Context)" } }, + { 0x07, { nullptr, "Flush Cache (Region)" } }, { 0x17, { nullptr, "Flush D-Cache (User)" } }, + { 0x08, { nullptr, "User Instruction" } }, + { 0x09, { nullptr, "Supervisor Instruction" } }, + { 0x0a, { nullptr, "User Data" } }, + { 0x0b, { nullptr, "Supervisor Data" } }, { 0x1b, { nullptr, "Flush I-Cache (Region)" } }, + { 0x0c, { nullptr, "Flush Cache (Segment)" } }, + { 0x0d, { nullptr, "Flush Cache (Page)" } }, + { 0x0e, { nullptr, "Flush Cache (Context)" } }, + { 0x0f, { nullptr, "Flush Cache (User)" } }, { 0x1f, { nullptr, "Flush D-Cache (Region)" } } +}; +/* TODO: make SPARCstation-1 a different machine type so it can load its own ASI descriptions - it's a subset of Sun4 +const sparc_disassembler::asi_desc_map::value_type sun4c_asi_desc[] = { + { 0x02, { nullptr, "System Space" } }, + { 0x03, { nullptr, "Segment Map" } }, + { 0x04, { nullptr, "Page Map" } }, + { 0x08, { nullptr, "User Instruction" } }, + { 0x09, { nullptr, "Supervisor Instruction" } }, + { 0x0a, { nullptr, "User Data" } }, + { 0x0b, { nullptr, "Supervisor Data" } }, + { 0x0c, { nullptr, "Flush Cache (Segment)" } }, + { 0x0d, { nullptr, "Flush Cache (Page)" } }, + { 0x0e, { nullptr, "Flush Cache (Context)" } } +}; +*/ +} + class sun4_state : public driver_device { public: @@ -822,6 +858,7 @@ static MACHINE_CONFIG_START( sun4, sun4_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", MB86901, 16670000) MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4_mem) + MCFG_SPARC_ADD_ASI_DESC(sun4_asi_desc) MCFG_RAM_ADD(RAM_TAG) MCFG_RAM_DEFAULT_SIZE("4M")