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]
This commit is contained in:
Vas Crabb 2016-06-22 11:10:42 +10:00
parent 496fb0609b
commit 5b9e7bcccf
5 changed files with 103 additions and 51 deletions

View File

@ -24,8 +24,6 @@
#define SPARCV8 (0)
CPU_DISASSEMBLE( sparc );
const device_type MB86901 = &device_creator<mb86901_device>;
const int mb86901_device::WINDOW_COUNT = 7;

View File

@ -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<typename T> static void add_asi_desc(device_t &device, const T &desc) { return downcast<mb86901_device &>(device).add_asi_desc(desc); }
protected:
template<typename T> 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);

View File

@ -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 <typename T> inline void sparc_disassembler::add_int_op_desc(const T &desc)
{
for (const auto &it : desc)
m_int_op_desc.insert(it);
}
template <typename T> 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]);

View File

@ -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 <typename T> void add_int_op_desc(const T &desc);
template <typename T> void add_fpop1_desc(const T &desc);
template <typename T> void add_fpop2_desc(const T &desc);
template <typename T> 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;

View File

@ -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")