1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
// 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_debug_state
{
public:
virtual uint64_t get_reg_r(unsigned index) const = 0;
virtual uint64_t get_translated_pc() const = 0;
virtual uint8_t get_icc() const = 0;
virtual uint8_t get_xcc() const = 0;
virtual uint8_t get_fcc(unsigned index) const = 0; // ?><=
protected:
~sparc_debug_state() { }
};
class sparc_disassembler
{
public:
enum vis_level { vis_none, vis_1, vis_2, vis_2p, vis_3, vis_3b };
struct asi_desc
{
asi_desc() { }
asi_desc(const char *name_, const char *desc_) : name(name_), desc(desc_) { }
const char *name = nullptr;
const char *desc = nullptr;
};
typedef std::map<uint8_t, asi_desc> asi_desc_map;
struct state_reg_desc
{
state_reg_desc() { }
state_reg_desc(bool reserved_, const char *read_name_, const char *write_name_) : reserved(reserved_), read_name(read_name_), write_name(write_name_) { }
bool reserved = false;
const char *read_name = nullptr;
const char *write_name = nullptr;
};
typedef std::map<uint8_t, state_reg_desc> state_reg_desc_map;
struct prftch_desc
{
prftch_desc() { }
prftch_desc(const char *name_) : name(name_) { }
const char *name = nullptr;
};
typedef std::map<uint8_t, prftch_desc> prftch_desc_map;
sparc_disassembler(const sparc_debug_state *state, unsigned version);
sparc_disassembler(const sparc_debug_state *state, unsigned version, vis_level vis);
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(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm(char *buf, offs_t pc, uint32_t op) const;
private:
struct branch_desc
{
int32_t (*get_disp)(uint32_t op);
const char * (*get_comment)(const sparc_debug_state *state, bool use_cc, offs_t pc, uint32_t op);
int disp_width;
bool use_pred, use_cc;
const char *reg_cc[4];
const char *mnemonic[16];
};
struct int_op_desc
{
bool hex_imm;
const char *mnemonic;
const char *g0_synth;
};
typedef std::map<uint8_t, int_op_desc> int_op_desc_map;
struct fpop1_desc
{
fpop1_desc() { }
fpop1_desc(bool three_op_, bool rs1_shift_, bool rs2_shift_, bool rd_shift_, const char *mnemonic_) : three_op(three_op_), rs1_shift(rs1_shift_), rs2_shift(rs2_shift_), rd_shift(rd_shift_), mnemonic(mnemonic_) { }
bool three_op = true;
bool rs1_shift = false;
bool rs2_shift = false;
bool rd_shift = false;
const char *mnemonic = nullptr;
};
typedef std::map<uint16_t, fpop1_desc> fpop1_desc_map;
struct fpop2_desc
{
fpop2_desc() { }
fpop2_desc(bool int_rs1_, bool shift_, const char *mnemonic_) : int_rs1(int_rs1_), shift(shift_), mnemonic(mnemonic_) { }
bool int_rs1 = false;
bool shift = false;
const char *mnemonic = nullptr;
};
typedef std::map<uint16_t, fpop2_desc> fpop2_desc_map;
struct ldst_desc
{
ldst_desc() { }
ldst_desc(bool rd_first_, bool alternate_, char rd_alt_reg_, bool rd_shift_, const char *mnemonic_, const char *g0_synth_) : rd_first(rd_first_), alternate(alternate_), rd_alt_reg(rd_alt_reg_), rd_shift(rd_shift_), mnemonic(mnemonic_), g0_synth(g0_synth_) { }
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_t, ldst_desc> ldst_desc_map;
struct vis_op_desc
{
enum arg { X, R, Fs, Fd };
vis_op_desc() { }
vis_op_desc(arg rs1_, arg rs2_, arg rd_, bool collapse_, const char *mnemonic_) : rs1(rs1_), rs2(rs2_), rd(rd_), collapse(collapse_), mnemonic(mnemonic_) { }
arg rs1 = X;
arg rs2 = X;
arg rd = X;
bool collapse = false;
const char *mnemonic = nullptr;
};
typedef std::map<uint16_t, vis_op_desc> vis_op_desc_map;
offs_t dasm_invalid(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_branch(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_shift(std::ostream &stream, offs_t pc, uint32_t op, const char *mnemonic, const char *mnemonicx, const char *mnemonicx0) const;
offs_t dasm_read_state_reg(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_write_state_reg(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_move_cond(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_move_reg_cond(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_fpop1(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_fpop2(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_impdep1(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_jmpl(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_return(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_tcc(std::ostream &stream, offs_t pc, uint32_t op) const;
offs_t dasm_ldst(std::ostream &stream, offs_t pc, uint32_t op) const;
void dasm_address(std::ostream &stream, uint32_t op) const;
void dasm_asi(std::ostream &stream, uint32_t op) const;
void dasm_asi_comment(std::ostream &stream, uint32_t op) const;
void dasm_vis_arg(std::ostream &stream, bool &args, vis_op_desc::arg fmt, uint32_t reg) const;
uint32_t freg(uint32_t 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);
template <typename T> void add_vis_op_desc(const T &desc);
void pad_op_field(std::ostream &stream, std::streampos start_position) const;
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 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];
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[];
static const vis_op_desc_map::value_type VIS1_OP_DESC[];
static const state_reg_desc_map::value_type VIS1_STATE_REG_DESC[];
static const asi_desc_map::value_type VIS1_ASI_DESC[];
static const vis_op_desc_map::value_type VIS2_OP_DESC[];
static const asi_desc_map::value_type VIS2P_ASI_DESC[];
static const fpop1_desc_map::value_type VIS3_FPOP1_DESC[];
static const vis_op_desc_map::value_type VIS3_OP_DESC[];
static const vis_op_desc_map::value_type VIS3B_OP_DESC[];
//const sparc_debug_state *m_state;
unsigned m_version;
vis_level m_vis_level;
int m_op_field_width;
branch_desc m_branch_desc[8];
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;
ldst_desc_map m_ldst_desc;
asi_desc_map m_asi_desc;
prftch_desc_map m_prftch_desc;
vis_op_desc_map m_vis_op_desc;
};
#endif // MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
|