summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/rsp/rsp.h
blob: 564f165210904dd9768016eb763aa51ba8d555cd (plain) (blame)
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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
// license:BSD-3-Clause
// copyright-holders:Ville Linde, Ryan Holtz
/***************************************************************************

    rsp.h

    Interface file for the universal machine language-based
    Reality Signal Processor (RSP) emulator.

***************************************************************************/

#pragma once

#ifndef __RSP_H__
#define __RSP_H__

#include "cpu/drcfe.h"
#include "cpu/drcuml.h"

/***************************************************************************
    REGISTER ENUMERATION
***************************************************************************/

enum
{
	RSP_PC = 1,
	RSP_R0,
	RSP_R1,
	RSP_R2,
	RSP_R3,
	RSP_R4,
	RSP_R5,
	RSP_R6,
	RSP_R7,
	RSP_R8,
	RSP_R9,
	RSP_R10,
	RSP_R11,
	RSP_R12,
	RSP_R13,
	RSP_R14,
	RSP_R15,
	RSP_R16,
	RSP_R17,
	RSP_R18,
	RSP_R19,
	RSP_R20,
	RSP_R21,
	RSP_R22,
	RSP_R23,
	RSP_R24,
	RSP_R25,
	RSP_R26,
	RSP_R27,
	RSP_R28,
	RSP_R29,
	RSP_R30,
	RSP_R31,
	RSP_SR,
	RSP_NEXTPC,
	RSP_STEPCNT,
	RSP_V0,  RSP_V1,  RSP_V2,  RSP_V3,  RSP_V4,  RSP_V5,  RSP_V6,  RSP_V7,
	RSP_V8,  RSP_V9,  RSP_V10, RSP_V11, RSP_V12, RSP_V13, RSP_V14, RSP_V15,
	RSP_V16, RSP_V17, RSP_V18, RSP_V19, RSP_V20, RSP_V21, RSP_V22, RSP_V23,
	RSP_V24, RSP_V25, RSP_V26, RSP_V27, RSP_V28, RSP_V29, RSP_V30, RSP_V31
};

/***************************************************************************
    HELPER MACROS
***************************************************************************/

#define REG_LO          32
#define REG_HI          33

#define RSREG           ((op >> 21) & 31)
#define RTREG           ((op >> 16) & 31)
#define RDREG           ((op >> 11) & 31)
#define SHIFT           ((op >> 6) & 31)

#define FRREG           ((op >> 21) & 31)
#define FTREG           ((op >> 16) & 31)
#define FSREG           ((op >> 11) & 31)
#define FDREG           ((op >> 6) & 31)

#define IS_SINGLE(o)    (((o) & (1 << 21)) == 0)
#define IS_DOUBLE(o)    (((o) & (1 << 21)) != 0)
#define IS_FLOAT(o)     (((o) & (1 << 23)) == 0)
#define IS_INTEGRAL(o)  (((o) & (1 << 23)) != 0)

#define SIMMVAL         ((INT16)op)
#define UIMMVAL         ((UINT16)op)
#define LIMMVAL         (op & 0x03ffffff)

#define RSP_STATUS_HALT          0x0001
#define RSP_STATUS_BROKE         0x0002
#define RSP_STATUS_DMABUSY       0x0004
#define RSP_STATUS_DMAFULL       0x0008
#define RSP_STATUS_IOFULL        0x0010
#define RSP_STATUS_SSTEP         0x0020
#define RSP_STATUS_INTR_BREAK    0x0040
#define RSP_STATUS_SIGNAL0       0x0080
#define RSP_STATUS_SIGNAL1       0x0100
#define RSP_STATUS_SIGNAL2       0x0200
#define RSP_STATUS_SIGNAL3       0x0400
#define RSP_STATUS_SIGNAL4       0x0800
#define RSP_STATUS_SIGNAL5       0x1000
#define RSP_STATUS_SIGNAL6       0x2000
#define RSP_STATUS_SIGNAL7       0x4000

#define RSPDRC_STRICT_VERIFY    0x0001          /* verify all instructions */

#define MCFG_RSP_DP_REG_R_CB(_devcb) \
	devcb = &rsp_device::static_set_dp_reg_r_callback(*device, DEVCB_##_devcb);

#define MCFG_RSP_DP_REG_W_CB(_devcb) \
	devcb = &rsp_device::static_set_dp_reg_w_callback(*device, DEVCB_##_devcb);

#define MCFG_RSP_SP_REG_R_CB(_devcb) \
	devcb = &rsp_device::static_set_sp_reg_r_callback(*device, DEVCB_##_devcb);

#define MCFG_RSP_SP_REG_W_CB(_devcb) \
	devcb = &rsp_device::static_set_sp_reg_w_callback(*device, DEVCB_##_devcb);

#define MCFG_RSP_SP_SET_STATUS_CB(_devcb) \
	devcb = &rsp_device::static_set_status_callback(*device, DEVCB_##_devcb);


class rsp_frontend;
class rsp_cop2;

class rsp_device : public cpu_device
{
	friend class rsp_frontend;
	friend class rsp_cop2;
	friend class rsp_cop2_drc;
	friend class rsp_cop2_simd;

public:
	// construction/destruction
	rsp_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);

	void resolve_cb();
	template<class _Object> static devcb_base &static_set_dp_reg_r_callback(device_t &device, _Object object) { return downcast<rsp_device &>(device).m_dp_reg_r_func.set_callback(object); }
	template<class _Object> static devcb_base &static_set_dp_reg_w_callback(device_t &device, _Object object) { return downcast<rsp_device &>(device).m_dp_reg_w_func.set_callback(object); }
	template<class _Object> static devcb_base &static_set_sp_reg_r_callback(device_t &device, _Object object) { return downcast<rsp_device &>(device).m_sp_reg_r_func.set_callback(object); }
	template<class _Object> static devcb_base &static_set_sp_reg_w_callback(device_t &device, _Object object) { return downcast<rsp_device &>(device).m_sp_reg_w_func.set_callback(object); }
	template<class _Object> static devcb_base &static_set_status_callback(device_t &device, _Object object) { return downcast<rsp_device &>(device).m_sp_set_status_func.set_callback(object); }

	void rspdrc_flush_drc_cache();
	void rspdrc_set_options(UINT32 options);
	void rsp_add_dmem(UINT32 *base);
	void rsp_add_imem(UINT32 *base);

	void ccfunc_read8();
	void ccfunc_read16();
	void ccfunc_read32();
	void ccfunc_write8();
	void ccfunc_write16();
	void ccfunc_write32();
	void ccfunc_get_cop0_reg();
	void ccfunc_set_cop0_reg();
	void ccfunc_unimplemented_opcode();
	void ccfunc_sp_set_status_cb();
	void ccfunc_unimplemented();

protected:
	// device-level overrides
	virtual void device_start();
	virtual void device_reset();
	virtual void device_stop();

	// device_execute_interface overrides
	virtual UINT32 execute_min_cycles() const { return 1; }
	virtual UINT32 execute_max_cycles() const { return 1; }
	virtual UINT32 execute_input_lines() const { return 1; }
	virtual UINT32 execute_default_irq_vector() const { return 0; }
	virtual void execute_run();
	virtual void execute_set_input(int inputnum, int state) { }

	// device_memory_interface overrides
	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }

	// device_state_interface overrides
	virtual void state_import(const device_state_entry &entry);
	virtual void state_export(const device_state_entry &entry);
	void state_string_export(const device_state_entry &entry, std::string &str);

	// device_disasm_interface overrides
	virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
	virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
	virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);

	void unimplemented_opcode(UINT32 op);

	/* internal compiler state */
	struct compiler_state
	{
		UINT32              cycles;                   /* accumulated cycles */
		UINT8               checkints;                /* need to check interrupts before next instruction */
		UINT8               checksoftints;            /* need to check software interrupts before next instruction */
		uml::code_label     labelnum;                 /* index for local labels */
	};

private:
	address_space_config m_program_config;

	/* fast RAM info */
	struct fast_ram_info
	{
		offs_t              start;                      /* start of the RAM block */
		offs_t              end;                        /* end of the RAM block */
		UINT8               readonly;                   /* TRUE if read-only */
		void *              base;                       /* base in memory where the RAM lives */
	};

	/* core state */
	drc_cache           m_cache;                      /* pointer to the DRC code cache */
	drcuml_state *      m_drcuml;                     /* DRC UML generator state */
	rsp_frontend *      m_drcfe;                      /* pointer to the DRC front-end state */
	UINT32              m_drcoptions;                 /* configurable DRC options */

	/* internal stuff */
	UINT8               m_cache_dirty;                /* true if we need to flush the cache */

	/* parameters for subroutines */
	UINT64              m_numcycles;                  /* return value from gettotalcycles */
	const char *        m_format;                     /* format string for print_debug */
	UINT32              m_arg2;                       /* print_debug argument 3 */
	UINT32              m_arg3;                       /* print_debug argument 4 */

	/* register mappings */
	uml::parameter   m_regmap[34];                 /* parameter to register mappings for all 32 integer registers */

	/* subroutines */
	uml::code_handle *   m_entry;                      /* entry point */
	uml::code_handle *   m_nocode;                     /* nocode exception handler */
	uml::code_handle *   m_out_of_cycles;              /* out of cycles exception handler */
	uml::code_handle *   m_read8;                      /* read byte */
	uml::code_handle *   m_write8;                     /* write byte */
	uml::code_handle *   m_read16;                     /* read half */
	uml::code_handle *   m_write16;                    /* write half */
	uml::code_handle *   m_read32;                     /* read word */
	uml::code_handle *   m_write32;                    /* write word */

	struct internal_rsp_state
	{
		UINT32 pc;
		UINT32 r[35];
		UINT32 arg0;
		UINT32 arg1;
		UINT32 jmpdest;
		int icount;
	};

	internal_rsp_state *m_rsp_state;

	FILE *m_exec_output;

	UINT32 m_sr;
	UINT32 m_step_count;

	UINT32 m_ppc;
	UINT32 m_nextpc;

	address_space *m_program;
protected:
	direct_read_data *m_direct;

private:
	rsp_cop2    *m_cop2;

	UINT32 *m_dmem32;
	UINT16 *m_dmem16;
	UINT8 *m_dmem8;

	UINT32 *m_imem32;
	UINT16 *m_imem16;
	UINT8 *m_imem8;

	UINT32 m_debugger_temp;
	bool m_isdrc;

	devcb_read32 m_dp_reg_r_func;
	devcb_write32 m_dp_reg_w_func;
	devcb_read32 m_sp_reg_r_func;
	devcb_write32 m_sp_reg_w_func;
	devcb_write32 m_sp_set_status_func;

	UINT8 READ8(UINT32 address);
	UINT16 READ16(UINT32 address);
	UINT32 READ32(UINT32 address);
	void WRITE8(UINT32 address, UINT8 data);
	void WRITE16(UINT32 address, UINT16 data);
	void WRITE32(UINT32 address, UINT32 data);
	UINT32 get_cop0_reg(int reg);
	void set_cop0_reg(int reg, UINT32 data);
	void load_fast_iregs(drcuml_block *block);
	void save_fast_iregs(drcuml_block *block);
	UINT8 DM_READ8(UINT32 address);
	UINT16 DM_READ16(UINT32 address);
	UINT32 DM_READ32(UINT32 address);
	void DM_WRITE8(UINT32 address, UINT8 data);
	void DM_WRITE16(UINT32 address, UINT16 data);
	void DM_WRITE32(UINT32 address, UINT32 data);
	void rspcom_init();
	void execute_run_drc();
	void code_flush_cache();
	void code_compile_block(offs_t pc);
	void static_generate_entry_point();
	void static_generate_nocode_handler();
	void static_generate_out_of_cycles();
	void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle *&handleptr);
	void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, int allow_exception);
	void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
	void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void generate_delay_slot_and_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg);
	void generate_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	int generate_vector_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	int generate_special(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	int generate_regimm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	int generate_cop2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	int generate_cop0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op);
};


extern const device_type RSP;


#endif /* __RSP_H__ */