mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
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:
parent
cde8e14fb6
commit
a1625d2220
@ -2378,6 +2378,7 @@ end
|
|||||||
if (CPUS["MB86901"]~=null) then
|
if (CPUS["MB86901"]~=null) then
|
||||||
files {
|
files {
|
||||||
MAME_DIR .. "src/devices/cpu/sparc/mb86901.cpp",
|
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/sparcdefs.h",
|
||||||
MAME_DIR .. "src/devices/cpu/sparc/sparc.h",
|
MAME_DIR .. "src/devices/cpu/sparc/sparc.h",
|
||||||
}
|
}
|
||||||
|
@ -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)
|
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__)
|
: cpu_device(mconfig, MB86901, "Fujitsu MB86901", tag, owner, clock, "mb86901", __FILE__)
|
||||||
, m_program_config("program", ENDIANNESS_BIG, 32, 32)
|
, 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)
|
offs_t mb86901_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
|
||||||
{
|
{
|
||||||
extern CPU_DISASSEMBLE( sparc );
|
UINT32 op = *reinterpret_cast<const UINT32 *>(oprom);
|
||||||
return CPU_DISASSEMBLE_NAME(sparc)(this, buffer, pc, oprom, opram, options);
|
return m_dasm.dasm(buffer, pc, BIG_ENDIANIZE_INT32(op));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
SPARC v7 emulator
|
SPARC v7 emulator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef __SPARC_H__
|
#ifndef __SPARC_H__
|
||||||
#define __SPARC_H__
|
#define __SPARC_H__
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sparcdasm.h"
|
||||||
|
|
||||||
#define SPARC_NO_TRAP 256
|
#define SPARC_NO_TRAP 256
|
||||||
#define SPARC_RESET 0
|
#define SPARC_RESET 0
|
||||||
#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
|
#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
|
||||||
@ -142,6 +144,7 @@ protected:
|
|||||||
|
|
||||||
// debugger helpers
|
// debugger helpers
|
||||||
UINT32 m_dbgregs[24];
|
UINT32 m_dbgregs[24];
|
||||||
|
sparc_disassembler m_dasm;
|
||||||
|
|
||||||
// address spaces
|
// address spaces
|
||||||
address_space *m_program;
|
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
|
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__ */
|
#endif /* __SPARC_H__ */
|
||||||
|
File diff suppressed because it is too large
Load Diff
201
src/devices/cpu/sparc/sparcdasm.h
Normal file
201
src/devices/cpu/sparc/sparcdasm.h
Normal 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
|
@ -83,20 +83,39 @@
|
|||||||
#define OP2 ((op >> 22) & 7)
|
#define OP2 ((op >> 22) & 7)
|
||||||
#define OP3 ((op >> 19) & 63)
|
#define OP3 ((op >> 19) & 63)
|
||||||
#define OPF ((op >> 5) & 0x1ff)
|
#define OPF ((op >> 5) & 0x1ff)
|
||||||
|
#define OPC ((op >> 5) & 0x1ff)
|
||||||
|
#define OPFLOW ((op >> 5) & 0x3f)
|
||||||
|
|
||||||
#define DISP30 (op << 2)
|
#define DISP30 (INT32(op << 2))
|
||||||
#define DISP22 (((INT32)(op << 10)) >> 8)
|
#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 IMM22 (op << 10)
|
||||||
#define CONST22 (op & 0x3fffff)
|
#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 IMM7 (op & 0x7f)
|
||||||
#define SIMM7 (((INT32)(op << 25)) >> 25)
|
#define SIMM7 (INT32(op << 25) >> 25)
|
||||||
#define OPIMM (op & 0x00002000)
|
#define SIMM8 (INT32(op << 24) >> 24)
|
||||||
|
#define SHCNT32 (op & 31)
|
||||||
|
#define SHCNT64 (op & 63)
|
||||||
#define USEIMM ((op >> 13) & 1)
|
#define USEIMM ((op >> 13) & 1)
|
||||||
|
#define USEEXT ((op >> 12) & 1)
|
||||||
|
|
||||||
|
|
||||||
#define COND ((op >> 25) & 15)
|
#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 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 RD ((op >> 25) & 31)
|
||||||
#define RS1 ((op >> 14) & 31)
|
#define RS1 ((op >> 14) & 31)
|
||||||
@ -107,7 +126,7 @@
|
|||||||
#define RS1REG *m_regs[RS1]
|
#define RS1REG *m_regs[RS1]
|
||||||
#define RS2REG *m_regs[RS2]
|
#define RS2REG *m_regs[RS2]
|
||||||
#define SET_RDREG(x) if(RD) { RDREG = x; }
|
#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 PC m_pc
|
||||||
#define nPC m_npc
|
#define nPC m_npc
|
||||||
|
Loading…
Reference in New Issue
Block a user