1 // license:GPL-2.0+
2 // copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood
3 /*****************************************************************************
4 
5     SunPlus µ'nSP emulator
6 
7     Copyright 2008-2017  Segher Boessenkool  <segher@kernel.crashing.org>
8     Licensed under the terms of the GNU GPL, version 2
9     http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10 
11     Ported to MAME framework by Ryan Holtz
12 
13 *****************************************************************************/
14 
15 #ifndef MAME_CPU_UNSP_UNSP_H
16 #define MAME_CPU_UNSP_UNSP_H
17 
18 #pragma once
19 
20 #include "cpu/drcfe.h"
21 #include "cpu/drcuml.h"
22 #include "cpu/drcumlsh.h"
23 #include "unspdefs.h"
24 
25 /***************************************************************************
26     CONSTANTS
27 ***************************************************************************/
28 
29 /* map variables */
30 #define MAPVAR_PC               M0
31 #define MAPVAR_CYCLES           M1
32 
33 #define SINGLE_INSTRUCTION_MODE (0)
34 
35 #define ENABLE_UNSP_DRC         (0)
36 
37 #define UNSP_LOG_OPCODES        (0)
38 #define UNSP_LOG_REGS           (0)
39 
40 //**************************************************************************
41 //  TYPE DEFINITIONS
42 //**************************************************************************
43 
44 class unsp_frontend;
45 
46 // ======================> unsp_device
47 
48 enum
49 {
50 	UNSP_SP = 1,
51 	UNSP_R1,
52 	UNSP_R2,
53 	UNSP_R3,
54 	UNSP_R4,
55 	UNSP_BP,
56 	UNSP_SR,
57 	UNSP_PC,
58 
59 	UNSP_GPR_COUNT = UNSP_PC,
60 
61 	UNSP_IRQ_EN,
62 	UNSP_FIQ_EN,
63 	UNSP_FIR_MOV_EN,
64 	UNSP_SB,
65 	UNSP_AQ,
66 	UNSP_FRA,
67 	UNSP_BNK,
68 	UNSP_INE,
69 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS
70 	UNSP_PRI,
71 	UNSP_LOG_OPS
72 #else
73 	UNSP_PRI
74 #endif
75 };
76 
77 enum
78 {
79 	UNSP_FIQ_LINE = 0,
80 	UNSP_IRQ0_LINE,
81 	UNSP_IRQ1_LINE,
82 	UNSP_IRQ2_LINE,
83 	UNSP_IRQ3_LINE,
84 	UNSP_IRQ4_LINE,
85 	UNSP_IRQ5_LINE,
86 	UNSP_IRQ6_LINE,
87 	UNSP_IRQ7_LINE,
88 	UNSP_BRK_LINE,
89 
90 	UNSP_NUM_LINES
91 };
92 
93 class unsp_device : public cpu_device
94 {
95 	friend class unsp_frontend;
96 
97 public:
98 	// construction/destruction
99 	unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
100 	virtual ~unsp_device();
101 
102 	uint8_t get_csb();
103 
104 	void set_ds(uint16_t ds);
105 	uint16_t get_ds();
106 
107 	void set_fr(uint16_t fr);
108 	uint16_t get_fr();
109 
110 	inline void ccfunc_unimplemented();
111 	void invalidate_cache();
112 
113 #if UNSP_LOG_REGS
114 	void log_regs();
115 	void log_write(uint32_t addr, uint32_t data);
116 	void cfunc_log_write();
117 #endif
118 
119 	void cfunc_muls();
120 
121 protected:
122 	unsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal);
123 
124 	// device-level overrides
125 	virtual void device_start() override;
126 	virtual void device_reset() override;
127 	virtual void device_stop() override;
128 
129 	// device_execute_interface overrides
execute_min_cycles()130 	virtual uint32_t execute_min_cycles() const noexcept override { return 5; }
execute_max_cycles()131 	virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
execute_input_lines()132 	virtual uint32_t execute_input_lines() const noexcept override { return 0; }
133 	virtual void execute_run() override;
134 	virtual void execute_set_input(int inputnum, int state) override;
135 
136 	// device_memory_interface overrides
137 	virtual space_config_vector memory_space_config() const override;
138 
139 	// device_state_interface overrides
140 	virtual void state_import(const device_state_entry& entry) override;
141 	virtual void state_export(const device_state_entry& entry) override;
142 	virtual void state_string_export(const device_state_entry& entry, std::string& str) const override;
143 
144 	// device_disasm_interface overrides
145 	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
146 
147 	// HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself.
148 	// Therefore, to avoid an unnecessary scheduler sync when the derived spg2xx_device sets or
149 	// clears an interrupt line, we provide this direct accessor.
150 	void set_state_unsynced(int inputnum, int state);
151 
152 	enum : uint32_t
153 	{
154 		REG_SP = 0,
155 		REG_R1,
156 		REG_R2,
157 		REG_R3,
158 		REG_R4,
159 		REG_BP,
160 		REG_SR,
161 		REG_PC,
162 
163 		REG_SR1 = 0,
164 		REG_SR2,
165 		REG_SR3,
166 		REG_SR4
167 	};
168 
169 	/* internal compiler state */
170 	struct compiler_state
171 	{
172 		compiler_state(compiler_state const&) = delete;
173 		compiler_state& operator=(compiler_state const&) = delete;
174 
175 		uint32_t m_cycles;          /* accumulated cycles */
176 		uml::code_label m_labelnum; /* index for local labels */
177 	};
178 
179 	struct internal_unsp_state
180 	{
181 		uint32_t m_r[16]; // required to be 32 bits due to DRC
182 		uint32_t m_secbank[4];
183 		uint32_t m_enable_irq;
184 		uint32_t m_enable_fiq;
185 		uint32_t m_fir_move;
186 		uint32_t m_fiq;
187 		uint32_t m_irq;
188 		uint32_t m_sirq;
189 		uint32_t m_sb;
190 		uint32_t m_aq;
191 		uint32_t m_fra;
192 		uint32_t m_bnk;
193 		uint32_t m_ine;
194 		uint32_t m_pri;
195 
196 		uint32_t m_divq_bit;
197 		uint32_t m_divq_dividend;
198 		uint32_t m_divq_divisor;
199 		uint32_t m_divq_a;
200 
201 		uint32_t m_arg0;
202 		uint32_t m_arg1;
203 		uint32_t m_jmpdest;
204 
205 		int m_icount;
206 	};
207 
208 	/* core state */
209 	internal_unsp_state* m_core;
210 
211 protected:
read16(uint32_t address)212 	uint16_t read16(uint32_t address) { return m_program.read_word(address); }
213 
write16(uint32_t address,uint16_t data)214 	void write16(uint32_t address, uint16_t data)
215 	{
216 	#if UNSP_LOG_REGS
217 		log_write(address, data);
218 	#endif
219 		m_program.write_word(address, data);
220 	}
221 
add_lpc(const int32_t offset)222 	void add_lpc(const int32_t offset)
223 	{
224 		const uint32_t new_lpc = UNSP_LPC + offset;
225 		m_core->m_r[REG_PC] = (uint16_t)new_lpc;
226 		m_core->m_r[REG_SR] &= 0xffc0;
227 		m_core->m_r[REG_SR] |= (new_lpc >> 16) & 0x3f;
228 	}
229 
230 	void execute_fxxx_000_group(uint16_t op);
231 	void execute_fxxx_001_group(uint16_t op);
232 	void execute_fxxx_010_group(uint16_t op);
233 	void execute_fxxx_011_group(uint16_t op);
234 	virtual void execute_fxxx_101_group(uint16_t op);
235 	void execute_fxxx_110_group(uint16_t op);
236 	void execute_fxxx_111_group(uint16_t op);
237 	void execute_fxxx_group(uint16_t op);
238 	void execute_fxxx_100_group(uint16_t op);
239 	virtual void execute_extended_group(uint16_t op);
240 	virtual void execute_exxx_group(uint16_t op);
241 	void execute_muls_ss(const uint16_t rd, const uint16_t rs, const uint16_t size);
242 	void unimplemented_opcode(uint16_t op);
243 	void unimplemented_opcode(uint16_t op, uint16_t ximm);
244 	void unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2);
op_is_divq(const uint16_t op)245 	virtual bool op_is_divq(const uint16_t op) { return false; }
246 
247 	int m_iso;
248 
249 	static char const *const regs[];
250 	static char const *const extregs[];
251 	static char const *const bitops[];
252 	static char const *const lsft[];
253 	static char const *const aluops[];
254 	static char const *const forms[];
255 
256 	void push(uint32_t value, uint32_t *reg);
257 	uint16_t pop(uint32_t *reg);
258 
259 	void update_nz(uint32_t value);
260 	void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1);
261 	bool do_basic_alu_ops(const uint16_t& op0, uint32_t& lres, uint16_t& r0, uint16_t& r1, uint32_t& r2, bool update_flags);
262 
263 private:
264 	// compilation boundaries -- how far back/forward does the analysis extend?
265 	enum : uint32_t
266 	{
267 		COMPILE_BACKWARDS_BYTES     = 128,
268 		COMPILE_FORWARDS_BYTES      = 512,
269 		COMPILE_MAX_INSTRUCTIONS    = (COMPILE_BACKWARDS_BYTES / 4) + (COMPILE_FORWARDS_BYTES / 4),
270 		COMPILE_MAX_SEQUENCE        = 64
271 	};
272 
273 	// exit codes
274 	enum : int
275 	{
276 		EXECUTE_OUT_OF_CYCLES       = 0,
277 		EXECUTE_MISSING_CODE        = 1,
278 		EXECUTE_UNMAPPED_CODE       = 2,
279 		EXECUTE_RESET_CACHE         = 3
280 	};
281 
282 
283 	void execute_jumps(const uint16_t op);
284 	void execute_remaining(const uint16_t op);
285 	void execute_one(const uint16_t op);
286 
287 
288 
289 	address_space_config m_program_config;
290 	memory_access<23, 1, -1, ENDIANNESS_BIG>::cache m_cache;
291 	memory_access<23, 1, -1, ENDIANNESS_BIG>::specific m_program;
292 
293 	uint32_t m_debugger_temp;
294 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS
295 	uint32_t m_log_ops;
296 #endif
297 
298 	inline void trigger_fiq();
299 	inline void trigger_irq(int line);
300 	void check_irqs();
301 
302 	drc_cache m_drccache;
303 	std::unique_ptr<drcuml_state> m_drcuml;
304 	std::unique_ptr<unsp_frontend> m_drcfe;
305 	uint32_t m_drcoptions;
306 	uint8_t m_cache_dirty;
307 
308 	uml::parameter   m_regmap[16];
309 	uml::code_handle *m_entry;
310 	uml::code_handle *m_nocode;
311 	uml::code_handle *m_out_of_cycles;
312 	uml::code_handle *m_check_interrupts;
313 	uml::code_handle *m_trigger_fiq;
314 	uml::code_handle *m_trigger_irq;
315 
316 	uml::code_handle *m_mem_read;
317 	uml::code_handle *m_mem_write;
318 
319 	bool m_enable_drc;
320 
321 	void execute_run_drc();
322 	void flush_drc_cache();
323 	void code_flush_cache();
324 	void code_compile_block(offs_t pc);
325 	void load_fast_iregs(drcuml_block &block);
326 	void save_fast_iregs(drcuml_block &block);
327 
328 	void static_generate_entry_point();
329 	void static_generate_nocode_handler();
330 	void static_generate_out_of_cycles();
331 	void static_generate_check_interrupts();
332 	void static_generate_trigger_fiq();
333 	void static_generate_trigger_irq();
334 	void static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr);
335 
336 	void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
337 	void generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param);
338 	void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
339 	void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
340 	void generate_add_lpc(drcuml_block &block, int32_t offset);
341 	void generate_update_nzsc(drcuml_block &block);
342 	void generate_update_nz(drcuml_block &block);
343 	void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op);
344 	bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
345 
346 #if UNSP_LOG_REGS
347 	FILE *m_log_file;
348 #endif
349 protected:
350 	int m_numregs;
351 };
352 
353 
354 class unsp_11_device : public unsp_device
355 {
356 public:
357 	// construction/destruction
358 	unsp_11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
359 
360 protected:
361 	unsp_11_device(const machine_config& mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal);
362 
363 private:
364 };
365 
366 class unsp_12_device : public unsp_11_device
367 {
368 public:
369 	// construction/destruction
370 	unsp_12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
371 
372 protected:
373 	unsp_12_device(const machine_config& mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal);
374 
375 	virtual void execute_fxxx_101_group(uint16_t op) override;
376 	virtual void execute_exxx_group(uint16_t op) override;
377 	void execute_divq(uint16_t op);
378 	bool op_is_divq(const uint16_t op) override;
379 
380 	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
381 };
382 
383 class unsp_20_device : public unsp_12_device
384 {
385 public:
386 	// construction/destruction
387 	unsp_20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
388 
389 protected:
390 	unsp_20_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal);
391 
392 	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
393 	virtual void execute_extended_group(uint16_t op) override;
394 
395 	virtual void device_start() override;
396 	virtual void device_reset() override;
397 
398 private:
399 	enum
400 	{
401 		UNSP20_R8 = 0,
402 		UNSP20_R9,
403 		UNSP20_R10,
404 		UNSP20_R11,
405 		UNSP20_R12,
406 		UNSP20_R13,
407 		UNSP20_R14,
408 		UNSP20_R15
409 	};
410 };
411 
412 
413 
414 DECLARE_DEVICE_TYPE(UNSP,    unsp_device)
415 DECLARE_DEVICE_TYPE(UNSP_11, unsp_11_device)
416 DECLARE_DEVICE_TYPE(UNSP_12, unsp_12_device)
417 DECLARE_DEVICE_TYPE(UNSP_20, unsp_20_device)
418 
419 
420 #endif // MAME_CPU_UNSP_UNSP_H
421