1/*
2    SDL - Simple DirectMedia Layer
3    Copyright (C) 1997-2012 Sam Lantinga
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with this library; if not, write to the Free
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
19    Sam Lantinga
20    slouken@libsdl.org
21*/
22
23/*
24	Audio interrupts
25
26	Patrice Mandin, Didier M�quignon
27 */
28
29	.text
30
31	.globl	_SDL_MintAudio_Callback
32
33	.globl	_SDL_MintAudio_XbiosInterrupt
34	.globl	_SDL_MintAudio_XbiosInterruptMeasureClock
35	.globl	_SDL_MintAudio_Dma8Interrupt
36	.globl	_SDL_MintAudio_StfaInterrupt
37
38	.globl	_SDL_MintAudio_mutex
39	.globl	_SDL_MintAudio_audiobuf
40	.globl	_SDL_MintAudio_numbuf
41	.globl	_SDL_MintAudio_audiosize
42	.globl	_SDL_MintAudio_clocktics
43	.globl	_SDL_MintAudio_hasfpu
44
45	.globl	_SDL_MintAudio_stfa
46
47/*
48	How it works:
49	- Audio is playing buffer #0 (resp. #1)
50	- We must calculate a sample in buffer #1 (resp. #0)
51	  so we first call the callback to do it
52	- Then we swap the buffers
53*/
54
55#define	savptr	0x4a2
56#define	savamt	0x46
57
58/*--- Save/restore FPU context ---*/
59
60#if defined(__mcoldfire__)
61
62#define SAVE_FPU_CONTEXT \
63	lea		sp@(-216),sp;	\
64	fsave		sp@;	\
65	fmovel		fpiar,sp@-;	\
66	lea		sp@(-64),sp;	\
67	fmovemd	fp0-fp7,sp@
68
69#define RESTORE_FPU_CONTEXT	\
70	fmovemd		sp@,fp0-fp7;	\
71	lea		sp@(64),sp;	\
72	fmovel		sp@+,fpiar;	\
73	frestore	sp@;	\
74	lea		sp@(216),sp
75
76#else
77
78#define SAVE_FPU_CONTEXT	\
79	.chip	68k/68881;	\
80	fsave	sp@-;	\
81	fmoveml fpcr/fpsr/fpiar,sp@-;	\
82	fmovemx	fp0-fp7,sp@-;	\
83	.chip	68k
84
85#define RESTORE_FPU_CONTEXT	\
86	.chip	68k/68881;	\
87	fmovemx	sp@+,fp0-fp7;	\
88	fmoveml	sp@+,fpcr/fpsr/fpiar;	\
89	frestore	sp@+;	\
90	.chip	68k
91
92#endif
93
94/*--- Xbios interrupt vector to measure Falcon external clock ---*/
95
96_SDL_MintAudio_XbiosInterruptMeasureClock:          /* 1 mS */
97#if defined(__mcoldfire__)
98	movel	d0,sp@-
99
100	moveql	#0,d0
101	btst	d0,0xFFFF8901:w	/* state DMA sound */
102#else
103	btst	#0,0xFFFF8901:w	/* state DMA sound */
104#endif
105	beqs	SDL_MintAudio_EndIntMeasure
106	addql	#1,_SDL_MintAudio_clocktics
107SDL_MintAudio_EndIntMeasure:
108#if defined(__mcoldfire__)
109	moveql	#5,d0
110	bclr	d0,0xFFFFFA0F:w	/* Clear service bit */
111
112	movel	sp@+,d0
113#else
114	bclr	#5,0xFFFFFA0F:w	/* Clear service bit */
115#endif
116	rte
117
118/*--- Xbios interrupt vector ---*/
119
120_SDL_MintAudio_XbiosInterrupt:
121#if defined(__mcoldfire__)
122	lea	sp@(-60),sp
123	moveml	d0-d7/a0-a6,sp@
124#else
125	moveml	d0-d7/a0-a6,sp@-
126#endif
127
128	/* Reenable interrupts, so other interrupts can work */
129	movew	#0x2300,sr
130
131	/* Clear service bit, so other MFP interrupts can work */
132#if defined(__mcoldfire__)
133	moveql	#5,d0
134	bclr	d0,0xfffffa0f:w
135#else
136	bclr	#5,0xfffffa0f:w
137#endif
138
139	/* Check if we are not already running */
140	tstw	_SDL_MintAudio_mutex
141	bne	SDL_MintAudio_XbiosEnd
142
143#if defined(__mcoldfire__)
144	movew	_SDL_MintAudio_mutex,d0
145	notl	d0
146	movew	d0,_SDL_MintAudio_mutex
147
148	movew	_SDL_MintAudio_numbuf,d1
149	eorl	#1,d1
150	movew	d1,_SDL_MintAudio_numbuf
151#else
152	notw	_SDL_MintAudio_mutex
153
154	/* Swap buffers */
155	eorw	#1,_SDL_MintAudio_numbuf
156#endif
157
158	/* Save FPU if needed */
159	tstw	_SDL_MintAudio_hasfpu
160	beqs	SDL_MintAudio_Xbios_nofpu1
161	SAVE_FPU_CONTEXT
162SDL_MintAudio_Xbios_nofpu1:
163
164	/* Callback */
165	jsr	_SDL_MintAudio_Callback
166
167	/* Restore FPU if needed */
168	tstw	_SDL_MintAudio_hasfpu
169	beqs	SDL_MintAudio_Xbios_nofpu2
170	RESTORE_FPU_CONTEXT
171SDL_MintAudio_Xbios_nofpu2:
172
173	/* Reserve space for registers */
174#if defined(__mcoldfire__)
175	movel	#savamt,d0
176	subl	d0,savptr
177#else
178	subl	#savamt,savptr
179#endif
180
181	/* Set new buffer */
182
183	moveq	#0,d0
184	movel	_SDL_MintAudio_audiosize,d1
185
186	movew	_SDL_MintAudio_numbuf,d0
187	lsll	#2,d0
188	lea	_SDL_MintAudio_audiobuf,a0
189	movel	a0@(d0:l),a1
190
191	lea	a1@(d1:l),a2
192
193	movel	a2,sp@-
194	movel	a1,sp@-
195	clrw	sp@-
196	movew	#131,sp@-
197	trap	#14
198	lea	sp@(12),sp
199
200	/* Restore registers space */
201#if defined(__mcoldfire__)
202	movel	#savamt,d0
203	addl	d0,savptr
204#else
205	addl	#savamt,savptr
206#endif
207
208	clrw	_SDL_MintAudio_mutex
209SDL_MintAudio_XbiosEnd:
210#if defined(__mcoldfire__)
211	moveml	sp@,d0-d7/a0-a6
212	lea	sp@(60),sp
213#else
214	moveml	sp@+,d0-d7/a0-a6
215#endif
216	rte
217
218/*--- DMA 8 bits interrupt vector ---*/
219
220_SDL_MintAudio_Dma8Interrupt:
221#if defined(__mcoldfire__)
222	lea	sp@(-16),sp
223	moveml	d0-d1/a0-a1,sp@
224#else
225	moveml	d0-d1/a0-a1,sp@-
226#endif
227
228	/* Reenable interrupts, so other interrupts can work */
229	movew	#0x2300,sr
230
231	/* Clear service bit, so other MFP interrupts can work */
232#if defined(__mcoldfire__)
233	moveql	#5,d0
234	bclr	d0,0xfffffa0f:w
235#else
236	bclr	#5,0xfffffa0f:w
237#endif
238	/* Check if we are not already running */
239	tstw	_SDL_MintAudio_mutex
240	bne	SDL_MintAudio_Dma8End
241
242#if defined(__mcoldfire__)
243	movew	_SDL_MintAudio_mutex,d0
244	notl	d0
245	movew	d0,_SDL_MintAudio_mutex
246
247	movew	_SDL_MintAudio_numbuf,d1
248	eorl	#1,d1
249	movew	d1,_SDL_MintAudio_numbuf
250#else
251	notw	_SDL_MintAudio_mutex
252
253	/* Swap buffers */
254	eorw	#1,_SDL_MintAudio_numbuf
255#endif
256
257	/* Save FPU if needed */
258	tstw	_SDL_MintAudio_hasfpu
259	beqs	SDL_MintAudio_Dma8_nofpu1
260	SAVE_FPU_CONTEXT
261SDL_MintAudio_Dma8_nofpu1:
262
263	/* Callback */
264	jsr	_SDL_MintAudio_Callback
265
266	/* Restore FPU if needed */
267	tstw	_SDL_MintAudio_hasfpu
268	beqs	SDL_MintAudio_Dma8_nofpu2
269	RESTORE_FPU_CONTEXT
270SDL_MintAudio_Dma8_nofpu2:
271
272	/* Set new buffer */
273
274	moveq	#0,d0
275
276	movew	_SDL_MintAudio_numbuf,d0
277	lsll	#2,d0
278	lea	_SDL_MintAudio_audiobuf,a0
279	movel	a0@(d0:l),d1
280
281	/* Modify DMA addresses */
282	lea	0xffff8900:w,a0
283
284	movel	d1,d0
285
286	moveb	d0,a0@(0x07)	/* Start address */
287	lsrl	#8,d0
288	moveb	d0,a0@(0x05)
289	lsrl	#8,d0
290	moveb	d0,a0@(0x03)
291
292	addl	_SDL_MintAudio_audiosize,d1
293
294	movel	d1,d0
295
296	moveb	d0,a0@(0x13)	/* End address */
297	lsrl	#8,d0
298	moveb	d0,a0@(0x11)
299	lsrl	#8,d0
300	moveb	d0,a0@(0x0f)
301
302	clrw	_SDL_MintAudio_mutex
303SDL_MintAudio_Dma8End:
304#if defined(__mcoldfire__)
305	moveml	sp@,d0-d1/a0-a1
306	lea	sp@(16),sp
307#else
308	moveml	sp@+,d0-d1/a0-a1
309#endif
310	rte
311
312/*--- STFA interrupt vector ---*/
313
314STFA_SOUND_START	=	6
315STFA_SOUND_END		=	STFA_SOUND_START+8
316
317_SDL_MintAudio_StfaInterrupt:
318	/* Reenable interrupts, so other interrupts can work */
319	movew	#0x2300,sr
320
321	/* Check if we are not already running */
322	tstw	_SDL_MintAudio_mutex
323
324#if defined(__mcoldfire__)
325	bne	SDL_MintAudio_StfaEnd
326
327	lea	sp@(-60),sp
328	moveml	d0-d7/a0-a6,sp@
329
330	movew	_SDL_MintAudio_mutex,d0
331	notl	d0
332	movew	d0,_SDL_MintAudio_mutex
333
334	movew	_SDL_MintAudio_numbuf,d1
335	eorl	#1,d1
336	movew	d1,_SDL_MintAudio_numbuf
337#else
338	bnes	SDL_MintAudio_StfaEnd
339
340	moveml	d0-d7/a0-a6,sp@-
341
342	notw	_SDL_MintAudio_mutex
343
344	/* Swap buffers */
345	eorw	#1,_SDL_MintAudio_numbuf
346#endif
347
348	/* Save FPU if needed */
349	tstw	_SDL_MintAudio_hasfpu
350	beqs	SDL_MintAudio_Stfa_nofpu1
351	SAVE_FPU_CONTEXT
352SDL_MintAudio_Stfa_nofpu1:
353
354	/* Callback */
355	jsr	_SDL_MintAudio_Callback
356
357	/* Restore FPU if needed */
358	tstw	_SDL_MintAudio_hasfpu
359	beqs	SDL_MintAudio_Stfa_nofpu2
360	RESTORE_FPU_CONTEXT
361SDL_MintAudio_Stfa_nofpu2:
362
363	/* Set new buffer */
364
365	moveq	#0,d0
366	movel	_SDL_MintAudio_stfa,a1
367
368	movew	_SDL_MintAudio_numbuf,d0
369	lsll	#2,d0
370	lea	_SDL_MintAudio_audiobuf,a0
371	movel	a0@(d0:l),d1
372
373	/* Modify STFA replay buffers */
374	movel	d1,a1@(STFA_SOUND_START)
375	addl	_SDL_MintAudio_audiosize,d1
376	movel	d1,a1@(STFA_SOUND_END)
377
378#if defined(__mcoldfire__)
379	moveml	sp@,d0-d7/a0-a6
380	lea	sp@(60),sp
381#else
382	moveml	sp@+,d0-d7/a0-a6
383#endif
384	clrw	_SDL_MintAudio_mutex
385SDL_MintAudio_StfaEnd:
386	rte
387