summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/adsp2100/adsp2100.h
blob: 337de47771d6f88136893c6918a4719a8885d015 (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
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    adsp2100.h

    ADSP-21xx series emulator.

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

#ifndef MAME_CPU_ADSP2100_ADSP2100_H
#define MAME_CPU_ADSP2100_ADSP2100_H

#pragma once


//**************************************************************************
//  DEBUGGING
//**************************************************************************

#define ADSP_TRACK_HOTSPOTS     0



//**************************************************************************
//  CONSTANTS
//**************************************************************************

// ADSP-2100 IRQs
const int ADSP2100_IRQ0         = 0;        // IRQ0
const int ADSP2100_SPORT1_RX    = 0;        // SPORT1 receive IRQ
const int ADSP2100_IRQ1         = 1;        // IRQ1
const int ADSP2100_SPORT1_TX    = 1;        // SPORT1 transmit IRQ
const int ADSP2100_IRQ2         = 2;        // IRQ2
const int ADSP2100_IRQ3         = 3;        // IRQ3

// ADSP-2101 IRQs
const int ADSP2101_IRQ0         = 0;        // IRQ0
const int ADSP2101_SPORT1_RX    = 0;        // SPORT1 receive IRQ
const int ADSP2101_IRQ1         = 1;        // IRQ1
const int ADSP2101_SPORT1_TX    = 1;        // SPORT1 transmit IRQ
const int ADSP2101_IRQ2         = 2;        // IRQ2
const int ADSP2101_SPORT0_RX    = 3;        // SPORT0 receive IRQ
const int ADSP2101_SPORT0_TX    = 4;        // SPORT0 transmit IRQ
const int ADSP2101_TIMER        = 5;        // internal timer IRQ

// ADSP-2104 IRQs
const int ADSP2104_IRQ0         = 0;        // IRQ0
const int ADSP2104_SPORT1_RX    = 0;        // SPORT1 receive IRQ
const int ADSP2104_IRQ1         = 1;        // IRQ1
const int ADSP2104_SPORT1_TX    = 1;        // SPORT1 transmit IRQ
const int ADSP2104_IRQ2         = 2;        // IRQ2
const int ADSP2104_SPORT0_RX    = 3;        // SPORT0 receive IRQ
const int ADSP2104_SPORT0_TX    = 4;        // SPORT0 transmit IRQ
const int ADSP2104_TIMER        = 5;        // internal timer IRQ

// ADSP-2105 IRQs
const int ADSP2105_IRQ0         = 0;        // IRQ0
const int ADSP2105_SPORT1_RX    = 0;        // SPORT1 receive IRQ
const int ADSP2105_IRQ1         = 1;        // IRQ1
const int ADSP2105_SPORT1_TX    = 1;        // SPORT1 transmit IRQ
const int ADSP2105_IRQ2         = 2;        // IRQ2
const int ADSP2105_TIMER        = 5;        // internal timer IRQ

// ADSP-2115 IRQs
const int ADSP2115_IRQ0         = 0;        // IRQ0
const int ADSP2115_SPORT1_RX    = 0;        // SPORT1 receive IRQ
const int ADSP2115_IRQ1         = 1;        // IRQ1
const int ADSP2115_SPORT1_TX    = 1;        // SPORT1 transmit IRQ
const int ADSP2115_IRQ2         = 2;        // IRQ2
const int ADSP2115_SPORT0_RX    = 3;        // SPORT0 receive IRQ
const int ADSP2115_SPORT0_TX    = 4;        // SPORT0 transmit IRQ
const int ADSP2115_TIMER        = 5;        // internal timer IRQ

// ADSP-2181 IRQs
const int ADSP2181_IRQ0         = 0;        // IRQ0
const int ADSP2181_SPORT1_RX    = 0;        // SPORT1 receive IRQ
const int ADSP2181_IRQ1         = 1;        // IRQ1
const int ADSP2181_SPORT1_TX    = 1;        // SPORT1 transmit IRQ
const int ADSP2181_IRQ2         = 2;        // IRQ2
const int ADSP2181_SPORT0_RX    = 3;        // SPORT0 receive IRQ
const int ADSP2181_SPORT0_TX    = 4;        // SPORT0 transmit IRQ
const int ADSP2181_TIMER        = 5;        // internal timer IRQ
const int ADSP2181_IRQE         = 6;        // IRQE
const int ADSP2181_BDMA         = 7;        // BDMA
const int ADSP2181_IRQL1        = 8;        // IRQL1
const int ADSP2181_IRQL0        = 9;        // IRQL0

// register enumeration
enum
{
	ADSP2100_PC = STATE_GENPC,
	ADSP2100_AX0 = 0,
	ADSP2100_AX1,
	ADSP2100_AY0,
	ADSP2100_AY1,
	ADSP2100_AR,
	ADSP2100_AF,
	ADSP2100_MX0,
	ADSP2100_MX1,
	ADSP2100_MY0,
	ADSP2100_MY1,
	ADSP2100_MR0,
	ADSP2100_MR1,
	ADSP2100_MR2,
	ADSP2100_MF,
	ADSP2100_SI,
	ADSP2100_SE,
	ADSP2100_SB,
	ADSP2100_SR0,
	ADSP2100_SR1,
	ADSP2100_I0,
	ADSP2100_I1,
	ADSP2100_I2,
	ADSP2100_I3,
	ADSP2100_I4,
	ADSP2100_I5,
	ADSP2100_I6,
	ADSP2100_I7,
	ADSP2100_L0,
	ADSP2100_L1,
	ADSP2100_L2,
	ADSP2100_L3,
	ADSP2100_L4,
	ADSP2100_L5,
	ADSP2100_L6,
	ADSP2100_L7,
	ADSP2100_M0,
	ADSP2100_M1,
	ADSP2100_M2,
	ADSP2100_M3,
	ADSP2100_M4,
	ADSP2100_M5,
	ADSP2100_M6,
	ADSP2100_M7,
	ADSP2100_PX,
	ADSP2100_CNTR,
	ADSP2100_ASTAT,
	ADSP2100_SSTAT,
	ADSP2100_MSTAT,
	ADSP2100_PCSP,
	ADSP2100_CNTRSP,
	ADSP2100_STATSP,
	ADSP2100_LOOPSP,
	ADSP2100_IMASK,
	ADSP2100_ICNTL,
	ADSP2100_IRQSTATE0,
	ADSP2100_IRQSTATE1,
	ADSP2100_IRQSTATE2,
	ADSP2100_IRQSTATE3,
	ADSP2100_FLAGIN,
	ADSP2100_FLAGOUT,
	ADSP2100_FL0,
	ADSP2100_FL1,
	ADSP2100_FL2,
	ADSP2100_AX0_SEC,
	ADSP2100_AX1_SEC,
	ADSP2100_AY0_SEC,
	ADSP2100_AY1_SEC,
	ADSP2100_AR_SEC,
	ADSP2100_AF_SEC,
	ADSP2100_MX0_SEC,
	ADSP2100_MX1_SEC,
	ADSP2100_MY0_SEC,
	ADSP2100_MY1_SEC,
	ADSP2100_MR0_SEC,
	ADSP2100_MR1_SEC,
	ADSP2100_MR2_SEC,
	ADSP2100_MF_SEC,
	ADSP2100_SI_SEC,
	ADSP2100_SE_SEC,
	ADSP2100_SB_SEC,
	ADSP2100_SR0_SEC,
	ADSP2100_SR1_SEC
};



//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_ADSP21XX_SPORT_RX_CB(_devcb) \
	downcast<adsp21xx_device &>(*device).set_sport_rx_callback(DEVCB_##_devcb);

#define MCFG_ADSP21XX_SPORT_TX_CB(_devcb) \
	downcast<adsp21xx_device &>(*device).set_sport_tx_callback(DEVCB_##_devcb);

#define MCFG_ADSP21XX_TIMER_FIRED_CB(_devcb) \
	downcast<adsp21xx_device &>(*device).set_timer_fired_callback(DEVCB_##_devcb);

#define MCFG_ADSP21XX_DMOVLAY_CB(_devcb) \
	downcast<adsp21xx_device &>(*device).set_dmovlay_callback(DEVCB_##_devcb);

//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> adsp21xx_device

class adsp21xx_device : public cpu_device
{
public:
	virtual ~adsp21xx_device();

	// inline configuration helpers
	template <class Object> devcb_base &set_sport_rx_callback(Object &&cb) { return m_sport_rx_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_sport_tx_callback(Object &&cb) { return m_sport_tx_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_timer_fired_callback(Object &&cb) { return m_timer_fired_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_dmovlay_callback(Object &&cb) { return m_dmovlay_cb.set_callback(std::forward<Object>(cb)); }

	// public interfaces
	void load_boot_data(uint8_t *srcdata, uint32_t *dstdata);
	// Returns base address for circular dag
	uint32_t get_ibase(int index) { return m_base[index]; };

protected:
	enum
	{
		CHIP_TYPE_ADSP2100,
		CHIP_TYPE_ADSP2101,
		CHIP_TYPE_ADSP2104,
		CHIP_TYPE_ADSP2105,
		CHIP_TYPE_ADSP2115,
		CHIP_TYPE_ADSP2181
	};

	// construction/destruction
	adsp21xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t chiptype);

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	// device_execute_interface overrides
	virtual uint32_t execute_min_cycles() const override;
	virtual uint32_t execute_max_cycles() const override;
	virtual void execute_run() override;
	virtual void execute_set_input(int inputnum, int state) override;

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

	// device_disasm_interface overrides
	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;

	// helpers
	void create_tables();
	inline void update_mstat();
	inline uint32_t pc_stack_top();
	inline void set_pc_stack_top(uint32_t top);
	inline void pc_stack_push();
	inline void pc_stack_push_val(uint32_t val);
	inline void pc_stack_pop();
	inline uint32_t pc_stack_pop_val();
	inline uint32_t cntr_stack_top();
	inline void cntr_stack_push();
	inline void cntr_stack_pop();
	inline uint32_t loop_stack_top();
	inline void loop_stack_push(uint32_t value);
	inline void loop_stack_pop();
	inline void stat_stack_push();
	inline void stat_stack_pop();
//  inline int condition(int c);
	int slow_condition();
	inline void modify_address(uint32_t ireg, uint32_t mreg);
	inline void data_write_dag1(uint32_t op, int32_t val);
	inline uint32_t data_read_dag1(uint32_t op);
	inline void data_write_dag2(uint32_t op, int32_t val);
	inline uint32_t data_read_dag2(uint32_t op);
	inline void pgm_write_dag2(uint32_t op, int32_t val);
	inline uint32_t pgm_read_dag2(uint32_t op);
	void alu_op_ar(int op);
	void alu_op_ar_const(int op);
	void alu_op_af(int op);
	void alu_op_af_const(int op);
	void alu_op_none(int op);
	void mac_op_mr(int op);
	void mac_op_mr_xop(int op);
	void mac_op_mf(int op);
	void mac_op_mf_xop(int op);
	void shift_op(int op);
	void shift_op_imm(int op);

	// memory access
	inline uint16_t data_read(uint32_t addr);
	inline void data_write(uint32_t addr, uint16_t data);
	inline uint16_t io_read(uint32_t addr);
	inline void io_write(uint32_t addr, uint16_t data);
	inline uint32_t program_read(uint32_t addr);
	inline void program_write(uint32_t addr, uint32_t data);
	inline uint32_t opcode_read();

	// register read/write
	inline void update_i(int which);
	inline void update_l(int which);
	inline void write_reg0(int regnum, int32_t val);
	inline void write_reg1(int regnum, int32_t val);
	inline void write_reg2(int regnum, int32_t val);
	inline void write_reg3(int regnum, int32_t val);
	inline int32_t read_reg0(int regnum);
	inline int32_t read_reg1(int regnum);
	inline int32_t read_reg2(int regnum);
	inline int32_t read_reg3(int regnum);

	// interrupts
	virtual bool generate_irq(int which, int indx = 0) = 0;
	virtual void check_irqs() = 0;

	// internal state
	static const int PC_STACK_DEPTH     = 16;
	static const int CNTR_STACK_DEPTH   = 4;
	static const int STAT_STACK_DEPTH   = 4;
	static const int LOOP_STACK_DEPTH   = 4;

	// 16-bit registers that can be loaded signed or unsigned
	union adsp_reg16
	{
		uint16_t  u;
		int16_t   s;
	};

	// the SHIFT result register is 32 bits
	union adsp_shift
	{
#ifdef LSB_FIRST
		struct { adsp_reg16 sr0, sr1; } srx;
#else
		struct { adsp_reg16 sr1, sr0; } srx;
#endif
		uint32_t sr;
	};

	// the MAC result register is 40 bits
	union adsp_mac
	{
#ifdef LSB_FIRST
		struct { adsp_reg16 mr0, mr1, mr2, mrzero; } mrx;
		struct { uint32_t mr0, mr1; } mry;
#else
		struct { adsp_reg16 mrzero, mr2, mr1, mr0; } mrx;
		struct { uint32_t mr1, mr0; } mry;
#endif
		uint64_t mr;
	};

	// core registers which are replicated
	struct adsp_core
	{
		// ALU registers
		adsp_reg16  ax0, ax1;
		adsp_reg16  ay0, ay1;
		adsp_reg16  ar;
		adsp_reg16  af;

		// MAC registers
		adsp_reg16  mx0, mx1;
		adsp_reg16  my0, my1;
		adsp_mac    mr;
		adsp_reg16  mf;

		// SHIFT registers
		adsp_reg16  si;
		adsp_reg16  se;
		adsp_reg16  sb;
		adsp_shift  sr;

		// dummy registers
		adsp_reg16  zero;
	};

	// configuration
	const address_space_config      m_program_config;
	const address_space_config      m_data_config;
	uint32_t                          m_chip_type;

	// other CPU registers
	uint32_t              m_pc;
	uint32_t              m_ppc;
	uint32_t              m_loop;
	uint32_t              m_loop_condition;
	uint32_t              m_cntr;

	// status registers
	uint32_t              m_astat;
	uint32_t              m_sstat;
	uint32_t              m_mstat;
	uint32_t              m_mstat_prev;
	uint32_t              m_astat_clear;
	uint32_t              m_idle;

	// live set of core registers
	adsp_core           m_core;

	// memory addressing registers
	uint32_t              m_i[8];
	int32_t               m_m[8];
	uint32_t              m_l[8];
	uint32_t              m_lmask[8];
	uint32_t              m_base[8];
	uint8_t               m_px;

	// stacks
	uint32_t              m_loop_stack[LOOP_STACK_DEPTH];
	uint32_t              m_cntr_stack[CNTR_STACK_DEPTH];
	uint32_t              m_pc_stack[PC_STACK_DEPTH];
	uint16_t              m_stat_stack[STAT_STACK_DEPTH][3];
	int32_t               m_pc_sp;
	int32_t               m_cntr_sp;
	int32_t               m_stat_sp;
	int32_t               m_loop_sp;

	// external I/O
	uint8_t               m_flagout;
	uint8_t               m_flagin;
	uint8_t               m_fl0;
	uint8_t               m_fl1;
	uint8_t               m_fl2;
	uint16_t              m_idma_addr;
	uint16_t              m_idma_cache;
	uint8_t               m_idma_offs;

	// interrupt handling
	uint16_t              m_imask;
	uint8_t               m_icntl;
	uint16_t              m_ifc;
	uint8_t               m_irq_state[10];
	uint8_t               m_irq_latch[10];

	// other internal states
	int                 m_icount;
	int                 m_mstat_mask;
	int                 m_imask_mask;

	// register maps
	int16_t *             m_read0_ptr[16];
	uint32_t *            m_read1_ptr[16];
	uint32_t *            m_read2_ptr[16];
	void *              m_alu_xregs[8];
	void *              m_alu_yregs[4];
	void *              m_mac_xregs[8];
	void *              m_mac_yregs[4];
	void *              m_shift_xregs[8];

	// alternate core registers (at end for performance)
	adsp_core           m_alt;

	// address spaces
	address_space *     m_program;
	address_space *     m_data;
	address_space *     m_io;
	memory_access_cache<2, -2, ENDIANNESS_LITTLE> *m_cache;

	// tables
	uint8_t               m_condition_table[0x1000];
	uint16_t              m_mask_table[0x4000];
	uint16_t              m_reverse_table[0x4000];

	devcb_read32            m_sport_rx_cb;    // callback for serial receive
	devcb_write32           m_sport_tx_cb;    // callback for serial transmit
	devcb_write_line        m_timer_fired_cb;          // callback for timer fired
	devcb_write_line        m_dmovlay_cb;          // callback for DMOVLAY instruction

	// debugging
#if ADSP_TRACK_HOTSPOTS
	uint32_t              m_pcbucket[0x4000];
#endif

	// flag definitions
	static const int SSFLAG     = 0x80;
	static const int MVFLAG     = 0x40;
	static const int QFLAG      = 0x20;
	static const int SFLAG      = 0x10;
	static const int CFLAG      = 0x08;
	static const int VFLAG      = 0x04;
	static const int NFLAG      = 0x02;
	static const int ZFLAG      = 0x01;
};


// ======================> adsp2100_device

class adsp2100_device : public adsp21xx_device
{
public:
	// construction/destruction
	adsp2100_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	// device_execute_interface overrides
	virtual uint32_t execute_input_lines() const override;

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	// interrupts
	virtual bool generate_irq(int which, int indx) override;
	virtual void check_irqs() override;
};


// ======================> adsp2101_device

class adsp2101_device : public adsp21xx_device
{
public:
	// construction/destruction
	adsp2101_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	adsp2101_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t chiptype);

	// device_execute_interface overrides
	virtual uint32_t execute_input_lines() const override;

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	// interrupts
	virtual bool generate_irq(int which, int indx) override;
	virtual void check_irqs() override;
};


// ======================> adsp2181_device

class adsp2181_device : public adsp21xx_device
{
public:
	// construction/destruction
	adsp2181_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

protected:
	// device_execute_interface overrides
	virtual uint32_t execute_input_lines() const override;

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	// interrupts
	virtual bool generate_irq(int which, int indx) override;
	virtual void check_irqs() override;

	// address spaces
	const address_space_config      m_io_config;

public:
	// public interfaces
	void idma_addr_w(uint16_t data);
	uint16_t idma_addr_r();
	void idma_data_w(uint16_t data);
	uint16_t idma_data_r();
};


// ======================> trivial variants

class adsp2104_device : public adsp2101_device
{
public:
	adsp2104_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class adsp2105_device : public adsp2101_device
{
public:
	adsp2105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};

class adsp2115_device : public adsp2101_device
{
public:
	adsp2115_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};



// device type definition
DECLARE_DEVICE_TYPE(ADSP2100, adsp2100_device)
DECLARE_DEVICE_TYPE(ADSP2101, adsp2101_device)
DECLARE_DEVICE_TYPE(ADSP2104, adsp2104_device)
DECLARE_DEVICE_TYPE(ADSP2105, adsp2105_device)
DECLARE_DEVICE_TYPE(ADSP2115, adsp2115_device)
DECLARE_DEVICE_TYPE(ADSP2181, adsp2181_device)


#endif // MAME_CPU_ADSP2100_ADSP2100_H