summaryrefslogtreecommitdiff
path: root/Source/Core/DSPCore/Src/DSPCore.h
blob: 0e093f57d4373b9ac541792c399fa4670df41268 (plain)
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
/*====================================================================

   filename:     DSPCore.h
   project:      GCemu
   created:      2004-6-18
   mail:		  duddie@walla.com

   Copyright (c) 2005 Duddie & Tratax

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

   ====================================================================*/

#ifndef _DSPCORE_H
#define _DSPCORE_H

#include "Thread.h"

#include "DSPBreakpoints.h"

#define DSP_IRAM_BYTE_SIZE	0x2000
#define DSP_IRAM_SIZE		0x1000
#define DSP_IRAM_MASK		0x0fff

#define DSP_IROM_BYTE_SIZE	0x2000
#define DSP_IROM_SIZE		0x1000
#define DSP_IROM_MASK		0x0fff

#define DSP_DRAM_BYTE_SIZE	0x2000
#define DSP_DRAM_SIZE		0x1000
#define DSP_DRAM_MASK		0x0fff

#define DSP_COEF_BYTE_SIZE	0x1000
#define DSP_COEF_SIZE		0x800
#define DSP_COEF_MASK		0x7ff

#define DSP_RESET_VECTOR	0x8000

#define DSP_STACK_DEPTH	0x20
#define DSP_STACK_MASK	0x1f

#define DSP_CR_IMEM		2
#define DSP_CR_DMEM		0
#define DSP_CR_TO_CPU	1
#define DSP_CR_FROM_CPU	0


// Register table taken from libasnd
#define DSP_REG_AR0		0x00 // address registers
#define DSP_REG_AR1		0x01
#define DSP_REG_AR2		0x02
#define DSP_REG_AR3		0x03

#define DSP_REG_IX0		0x04 // indexing registers (actually, mostly used as increments)
#define DSP_REG_IX1		0x05
#define DSP_REG_IX2		0x06
#define DSP_REG_IX3		0x07

#define DSP_REG_WR0		0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
#define DSP_REG_WR1		0x09
#define DSP_REG_WR2		0x0a
#define DSP_REG_WR3		0x0b

#define DSP_REG_ST0		0x0c // stacks.
#define DSP_REG_ST1		0x0d
#define DSP_REG_ST2		0x0e
#define DSP_REG_ST3		0x0f

#define DSP_REG_CR		0x12 // Seems to be the top 8 bits of LRS/SRS.
#define DSP_REG_SR		0x13

#define DSP_REG_PRODL	0x14 // product.
#define DSP_REG_PRODM	0x15
#define DSP_REG_PRODH	0x16
#define DSP_REG_PRODM2	0x17

#define DSP_REG_AXL0	0x18
#define DSP_REG_AXL1	0x19
#define DSP_REG_AXH0	0x1a
#define DSP_REG_AXH1	0x1b

#define DSP_REG_ACC0	0x1c // accumulator (global)
#define DSP_REG_ACC1	0x1d

#define DSP_REG_ACL0	0x1c // Low accumulator
#define DSP_REG_ACL1	0x1d
#define DSP_REG_ACM0	0x1e // Mid accumulator
#define DSP_REG_ACM1	0x1f
#define DSP_REG_ACH0	0x10 // Sign extended 8 bit register 0
#define DSP_REG_ACH1	0x11 // Sign extended 8 bit register 1

// Hardware registers address

#define DSP_COEF_A1_0	0xa0

#define DSP_DSCR		0xc9 // DSP DMA Control Reg
#define DSP_DSPA		0xcd // DSP DMA Address (DSP)
#define DSP_DSBL		0xcb // DSP DMA Block Length
#define DSP_DSMAH		0xce // DSP DMA Address High (External)
#define DSP_DSMAL		0xcf // DSP DMA Address Low (External)

#define DSP_FORMAT		0xd1 // Sample format
#define DSP_ACUNK		0xd2 // Set to 3 on my dumps
#define DSP_ACDATA1		0xd3 // used only by Zelda ucodes
#define DSP_ACSAH		0xd4 // Start of loop
#define DSP_ACSAL		0xd5
#define DSP_ACEAH		0xd6 // End of sample (and loop)
#define DSP_ACEAL		0xd7
#define DSP_ACCAH		0xd8 // Current playback position
#define DSP_ACCAL		0xd9
#define DSP_PRED_SCALE	0xda // ADPCM predictor and scale
#define DSP_YN1			0xdb
#define DSP_YN2			0xdc
#define DSP_ACCELERATOR	0xdd // ADPCM accelerator read. Used by AX.
#define DSP_GAIN		0xde
#define DSP_ACUNK2		0xdf // Set to 0xc on my dumps

#define DSP_AMDM		0xef // ARAM DMA Request Mask 0: DMA with ARAM unmasked 1: masked

#define DSP_DIRQ		0xfb // DSP Irq Rest
#define DSP_DMBH		0xfc // DSP Mailbox H
#define DSP_DMBL		0xfd // DSP Mailbox L
#define DSP_CMBH		0xfe // CPU Mailbox H
#define DSP_CMBL		0xff // CPU Mailbox L

#define DMA_TO_DSP		0
#define DMA_TO_CPU		1

// Stacks
#define DSP_STACK_C		0
#define DSP_STACK_D		1

// cr (Not g_dsp.r[CR]) bits
// See HW/DSP.cpp.
#define CR_EXTERNAL_INT	0x0002
#define CR_HALT			0x0004
#define CR_INIT			0x0400


// SR bits
#define SR_CARRY		0x0001
#define SR_OVERFLOW		0x0002
#define SR_ARITH_ZERO	0x0004
#define SR_SIGN			0x0008
#define SR_OVER_S32		0x0010 // set when there there was mod/tst/cmp on accu and result is over s32
#define SR_TOP2BITS		0x0020 // if the upper (ac?.m/ax?.h) 2 bits are equal
#define SR_LOGIC_ZERO	0x0040
#define SR_80			0x0080 // Unknown, set by add, sub
#define SR_INT_ENABLE	0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
#define SR_EXT_INT_ENABLE	0x0800 // Appears in zelda - seems to disable external interupts
#define SR_MUL_MODIFY	0x2000 // 1 = normal. 0 = x2   (M0, M2)
#define SR_40_MODE_BIT	0x4000 // 0 = "16", 1 = "40"  (SET16, SET40)  Controls sign extension when loading mid accums.
#define SR_MUL_UNSIGNED	0x8000 // 0 = normal. 1 = unsigned  (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.

// This should be the bits affected by CMP. Does not include logic zero.
#define SR_CMP_MASK		0x3f

// exceptions vector
#define EXP_STOVF		1 // 0x0002 stack under/over flow
#define EXP_2			2 // 0x0004
#define EXP_3			3 // 0x0006
#define EXP_4			4 // 0x0008
#define EXP_ACCOV		5 // 0x000a accelerator address overflow
#define EXP_6			6 // 0x000c
#define EXP_INT			7 // 0x000e external int (message from cpu)

// All the state of the DSP should be in this struct. Any DSP state that is not filled on init
// should be moved here.
struct SDSP
{
	u16 r[32];
	u16 pc;
#if PROFILE
	u16 err_pc;
#endif
	
	// This is NOT the same cr as r[DSP_REG_CR].
	// This register is shared with the main emulation, see DSP.cpp
	// The plugin has control over 0x0C07 of this reg.
	// Bits are defined in a struct in DSP.cpp.
	u16 cr;

	u8 reg_stack_ptr[4];
	u8 exceptions;   // pending exceptions
	int exception_in_progress;  // inside exp flag

	// DSP hardware stacks. They're mapped to a bunch of registers, such that writes
	// to them push and reads pop.
	// Let's make stack depth 32 for now, which is way more than what's needed.
	// The real DSP has different depths for the different stacks, but it would
	// be strange if any ucode relied on stack overflows since on the DSP, when
	// the stack overflows, you're screwed.
	u16 reg_stack[4][DSP_STACK_DEPTH];

	// For debugging.
	u32 iram_crc;
	u64 step_counter;

	// Mailbox.
	volatile u16 mbox[2][2];

	// Mutex protecting the mailbox.
	Common::CriticalSection g_CriticalSection;

	// Accelerator / DMA / other hardware registers. Not GPRs.
	u16 ifx_regs[256];

	// When state saving, all of the above can just be memcpy'd into the save state.
	// The below needs special handling.
	u16 *iram;
	u16 *dram;
	u16 *irom;
	u16 *coef;

	// This one doesn't really belong here.
	u8  *cpu_ram;
};

extern SDSP g_dsp;
extern DSPBreakpoints dsp_breakpoints;

bool DSPCore_Init(const char *irom_filename, const char *coef_filename);

void DSPCore_Reset();
void DSPCore_Shutdown(); // Frees all allocated memory.

void DSPCore_CheckExternalInterrupt();
void DSPCore_CheckExceptions();

// sets a flag in the pending exception register.
void DSPCore_SetException(u8 level);

enum DSPCoreState
{
	DSPCORE_RUNNING = 0,
	DSPCORE_STEPPING = 1,
};

int DSPCore_RunCycles(int cycles);

// These are meant to be called from the UI thread.
void DSPCore_SetState(DSPCoreState new_state);
DSPCoreState DSPCore_GetState();

void DSPCore_Step();

#endif // _DSPCORE_H