improve SPARC disassembler: [Vas Crabb]

* Support SPARCv9
* Allow plug-in ASI comments
* Fix format of some opcodes
* Produce clr synthetic
* Allow running in v7, v8 and v9 modes
This commit is contained in:
Vas Crabb 2016-06-22 04:36:41 +10:00
parent cde8e14fb6
commit a1625d2220
6 changed files with 1369 additions and 565 deletions

View File

@ -2378,6 +2378,7 @@ end
if (CPUS["MB86901"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/sparc/mb86901.cpp",
MAME_DIR .. "src/devices/cpu/sparc/sparcdasm.h",
MAME_DIR .. "src/devices/cpu/sparc/sparcdefs.h",
MAME_DIR .. "src/devices/cpu/sparc/sparc.h",
}

View File

@ -37,6 +37,7 @@ const int mb86901_device::WINDOW_COUNT = 7;
mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: cpu_device(mconfig, MB86901, "Fujitsu MB86901", tag, owner, clock, "mb86901", __FILE__)
, m_program_config("program", ENDIANNESS_BIG, 32, 32)
, m_dasm(7)
{
}
@ -351,8 +352,8 @@ UINT32 mb86901_device::disasm_max_opcode_bytes() const
offs_t mb86901_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
extern CPU_DISASSEMBLE( sparc );
return CPU_DISASSEMBLE_NAME(sparc)(this, buffer, pc, oprom, opram, options);
UINT32 op = *reinterpret_cast<const UINT32 *>(oprom);
return m_dasm.dasm(buffer, pc, BIG_ENDIANIZE_INT32(op));
}

View File

@ -4,11 +4,13 @@
SPARC v7 emulator
*/
#pragma once
#ifndef __SPARC_H__
#define __SPARC_H__
#pragma once
#include "sparcdasm.h"
#define SPARC_NO_TRAP 256
#define SPARC_RESET 0
#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
@ -142,6 +144,7 @@ protected:
// debugger helpers
UINT32 m_dbgregs[24];
sparc_disassembler m_dasm;
// address spaces
address_space *m_program;
@ -190,6 +193,4 @@ enum
SPARC_R96, SPARC_R97, SPARC_R98, SPARC_R99, SPARC_R100, SPARC_R101, SPARC_R102, SPARC_R103, SPARC_R104, SPARC_R105, SPARC_R106, SPARC_R107, SPARC_R108, SPARC_R109, SPARC_R110, SPARC_R111
};
CPU_DISASSEMBLE( sparc );
#endif /* __SPARC_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,201 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz, Vas Crabb
/*
SPARC disassembler
*/
#ifndef MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
#define MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
#pragma once
#include <map>
class sparc_disassembler
{
public:
struct asi_desc
{
const char *name = nullptr;
const char *desc = nullptr;
};
typedef std::map<UINT8, asi_desc> asi_desc_map;
struct state_reg_desc
{
bool reserved = false;
const char *read_name = nullptr;
const char *write_name = nullptr;
};
typedef std::map<UINT8, state_reg_desc> state_reg_desc_map;
struct prftch_desc
{
const char *name = nullptr;
};
typedef std::map<UINT8, prftch_desc> prftch_desc_map;
sparc_disassembler(unsigned version);
template <typename T> void add_state_reg_desc(const T &desc)
{
for (const auto &it : desc)
{
auto ins = m_state_reg_desc.insert(it);
if (!ins.second)
{
ins.first->second.reserved = it.second.reserved;
if (it.second.read_name)
ins.first->second.read_name = it.second.read_name;
if (it.second.write_name)
ins.first->second.write_name = it.second.write_name;
}
}
}
template <typename T> void add_asi_desc(const T &desc)
{
// TODO: support ranges
for (const auto &it : desc)
{
auto ins = m_asi_desc.insert(it);
if (!ins.second)
{
if (it.second.name)
ins.first->second.name = it.second.name;
if (it.second.desc)
ins.first->second.desc = it.second.desc;
}
}
}
template <typename T> void add_prftch_desc(const T &desc)
{
for (const auto &it : desc)
{
auto ins = m_prftch_desc.insert(it);
if (!ins.second)
{
if (it.second.name)
ins.first->second.name = it.second.name;
}
}
}
offs_t dasm(char *buf, offs_t pc, UINT32 op) const;
private:
struct branch_desc
{
INT32 (*get_disp)(UINT32 op);
int disp_width;
bool use_pred, use_cc;
const char *reg_cc[4];
const char *mnemonic[16];
};
struct int_op_desc
{
unsigned min_version;
bool hex_imm;
const char *mnemonic;
};
typedef std::map<UINT8, int_op_desc> int_op_desc_map;
struct fpop1_desc
{
bool three_op = true;
bool rs1_shift = false;
bool rs2_shift = false;
bool rd_shift = false;
const char *mnemonic = nullptr;
};
typedef std::map<UINT16, fpop1_desc> fpop1_desc_map;
struct fpop2_desc
{
bool int_rs1 = false;
bool shift = false;
const char *mnemonic = nullptr;
};
typedef std::map<UINT16, fpop2_desc> fpop2_desc_map;
struct ldst_desc
{
bool rd_first = false;
bool alternate = false;
char rd_alt_reg = '\0';
bool rd_shift = false;
const char *mnemonic = nullptr;
const char *g0_synth = nullptr;
};
typedef std::map<UINT8, ldst_desc> ldst_desc_map;
offs_t dasm_invalid(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_branch(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_shift(char *buf, offs_t pc, UINT32 op, const char *mnemonic, const char *mnemonicx, const char *mnemonicx0) const;
offs_t dasm_read_state_reg(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_write_state_reg(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_move_cond(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_move_reg_cond(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_fpop1(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_fpop2(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_jmpl(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_return(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_tcc(char *buf, offs_t pc, UINT32 op) const;
offs_t dasm_ldst(char *buf, offs_t pc, UINT32 op) const;
void dasm_address(char *&output, UINT32 op) const;
void dasm_asi(char *&output, UINT32 op) const;
void dasm_asi_comment(char *&output, UINT32 op) const;
UINT32 freg(UINT32 val, bool shift) const;
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);
void pad_op_field(char *buf, char *&output) const;
ATTR_PRINTF(2, 3) static void print(char *&output, const char *fmt, ...);
static const char * const REG_NAMES[32];
static const branch_desc EMPTY_BRANCH_DESC;
static const branch_desc BPCC_DESC;
static const branch_desc BICC_DESC;
static const branch_desc BPR_DESC;
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 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];
static const char * const MOVE_INT_COND_MNEMONICS[8];
static const char * const V9_PRIV_REG_NAMES[32];
static const fpop1_desc_map::value_type V7_FPOP1_DESC[];
static const fpop1_desc_map::value_type V9_FPOP1_DESC[];
static const fpop2_desc_map::value_type V7_FPOP2_DESC[];
static const fpop2_desc_map::value_type V9_FPOP2_DESC[];
static const ldst_desc_map::value_type V7_LDST_DESC[];
static const ldst_desc_map::value_type V9_LDST_DESC[];
static const asi_desc_map::value_type V9_ASI_DESC[];
static const prftch_desc_map::value_type V9_PRFTCH_DESC[];
unsigned m_version;
int m_op_field_width;
branch_desc m_branch_desc[8];
int_op_desc_map m_simple_int_op_desc;
state_reg_desc_map m_state_reg_desc;
fpop1_desc_map m_fpop1_desc;
fpop2_desc_map m_fpop2_desc;
ldst_desc_map m_ldst_desc;
asi_desc_map m_asi_desc;
prftch_desc_map m_prftch_desc;
};
CPU_DISASSEMBLE( sparcv7 );
CPU_DISASSEMBLE( sparcv8 );
CPU_DISASSEMBLE( sparcv9 );
#endif // MAME_DEVICES_CPU_SPARC_SPARC_DASM_H

View File

@ -83,20 +83,39 @@
#define OP2 ((op >> 22) & 7)
#define OP3 ((op >> 19) & 63)
#define OPF ((op >> 5) & 0x1ff)
#define OPC ((op >> 5) & 0x1ff)
#define OPFLOW ((op >> 5) & 0x3f)
#define DISP30 (op << 2)
#define DISP22 (((INT32)(op << 10)) >> 8)
#define DISP30 (INT32(op << 2))
#define DISP22 (INT32(op << 10) >> 8)
#define DISP19 (INT32(op << 13) >> 11)
#define DISP16 (INT32(((op << 10) & 0xc0000000) | ((op << 16) & 0x3fff0000)) >> 14)
#define IMM22 (op << 10)
#define CONST22 (op & 0x3fffff)
#define SIMM13 (((INT32)(op << 19)) >> 19)
#define SIMM13 (INT32(op << 19) >> 19)
#define SIMM11 (INT32(op << 21) >> 21)
#define SIMM10 (INT32(op << 22) >> 22)
#define IMM7 (op & 0x7f)
#define SIMM7 (((INT32)(op << 25)) >> 25)
#define OPIMM (op & 0x00002000)
#define SIMM7 (INT32(op << 25) >> 25)
#define SIMM8 (INT32(op << 24) >> 24)
#define SHCNT32 (op & 31)
#define SHCNT64 (op & 63)
#define USEIMM ((op >> 13) & 1)
#define USEEXT ((op >> 12) & 1)
#define COND ((op >> 25) & 15)
#define RCOND ((op >> 10) & 7)
#define MOVCOND ((op >> 14) & 15)
#define PRED ((op >> 19) & 1)
#define ANNUL ((op >> 29) & 1)
#define ASI ((op >> 5) & 0xff)
#define BRCC ((op >> 20) & 3)
#define MOVCC (((op >> 11) & 3) | ((op >> 16) & 4))
#define OPFCC ((op >> 11) & 7)
#define TCCCC ((op >> 11) & 3)
#define ASI ((op >> 5) & 255)
#define MMASK (op & 15)
#define CMASK ((op >> 4) & 7)
#define RD ((op >> 25) & 31)
#define RS1 ((op >> 14) & 31)
@ -107,7 +126,7 @@
#define RS1REG *m_regs[RS1]
#define RS2REG *m_regs[RS2]
#define SET_RDREG(x) if(RD) { RDREG = x; }
#define ADDRESS (OPIMM ? (RS1REG + SIMM13) : (RS1REG + RS2REG))
#define ADDRESS (USEIMM ? (RS1REG + SIMM13) : (RS1REG + RS2REG))
#define PC m_pc
#define nPC m_npc