Add and use SuperToUser macro to handle super->user mode switch SDL-1.2
authorPatrice Mandin <patmandin@gmail.com>
Tue, 10 Jan 2012 21:12:45 +0100
branchSDL-1.2
changeset 6206 ceb6db0058f1
parent 6203 bc960ba38aae
child 6209 beb988469d26
Add and use SuperToUser macro to handle super->user mode switch
src/audio/mint/SDL_mintaudio_stfa.c
src/audio/mint/SDL_mintaudio_xbios.c
src/timer/mint/SDL_systimer.c
src/video/ataricommon/SDL_atarisuper.h
src/video/ataricommon/SDL_xbiosevents.c
--- a/src/audio/mint/SDL_mintaudio_stfa.c	Mon Jan 09 07:06:36 2012 -0500
+++ b/src/audio/mint/SDL_mintaudio_stfa.c	Tue Jan 10 21:12:45 2012 +0100
@@ -38,6 +38,7 @@
 #include "../SDL_sysaudio.h"
 
 #include "../../video/ataricommon/SDL_atarimxalloc_c.h"
+#include "../../video/ataricommon/SDL_atarisuper.h"
 
 #include "SDL_mintaudio.h"
 #include "SDL_mintaudio_stfa.h"
@@ -164,7 +165,7 @@
 	/* Stop replay */
 	oldpile=(void *)Super(0);
 	cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
-	Super(oldpile);
+	SuperToUser(oldpile);
 }
 
 static void Mint_UnlockAudio(_THIS)
@@ -174,7 +175,7 @@
 	/* Restart replay */
 	oldpile=(void *)Super(0);
 	cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
-	Super(oldpile);
+	SuperToUser(oldpile);
 }
 
 static void Mint_CloseAudio(_THIS)
@@ -184,7 +185,7 @@
 	/* Stop replay */
 	oldpile=(void *)Super(0);
 	cookie_stfa->sound_enable=STFA_PLAY_DISABLE;
-	Super(oldpile);
+	SuperToUser(oldpile);
 
 	/* Wait if currently playing sound */
 	while (SDL_MintAudio_mutex != 0) {
@@ -283,7 +284,7 @@
 	/* Restart replay */
 	cookie_stfa->sound_enable=STFA_PLAY_ENABLE|STFA_PLAY_REPEAT;
 
-	Super(oldpile);
+	SuperToUser(oldpile);
 
 	DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
 }
--- a/src/audio/mint/SDL_mintaudio_xbios.c	Mon Jan 09 07:06:36 2012 -0500
+++ b/src/audio/mint/SDL_mintaudio_xbios.c	Tue Jan 10 21:12:45 2012 +0100
@@ -41,6 +41,7 @@
 #include "../SDL_sysaudio.h"
 
 #include "../../video/ataricommon/SDL_atarimxalloc_c.h"
+#include "../../video/ataricommon/SDL_atarisuper.h"
 
 #include "SDL_mintaudio.h"
 #include "SDL_mintaudio_dma8.h"
@@ -258,7 +259,7 @@
 	DMAAUDIO_IO.dest_ctrl = dest_ctrl;
 	DMAAUDIO_IO.sync_div = sync_div;
 
-	Super(oldstack);
+	SuperToUser(oldstack);
 }
 
 static void Mint_CheckExternalClock(_THIS)
--- a/src/timer/mint/SDL_systimer.c	Mon Jan 09 07:06:36 2012 -0500
+++ b/src/timer/mint/SDL_systimer.c	Tue Jan 10 21:12:45 2012 +0100
@@ -46,6 +46,8 @@
 #include "../SDL_timer_c.h"
 #include "SDL_thread.h"
 
+#include "../../video/ataricommon/SDL_atarisuper.h"
+
 #include "SDL_vbltimer_s.h"
 
 /* from audio/mint */
@@ -64,7 +66,7 @@
 	/* Set first ticks value */
 	old_stack = (void *)Super(0);
 	start = *((volatile long *)_hz_200);
-	Super(old_stack);
+	SuperToUser(old_stack);
 
 	start *= 5;	/* One _hz_200 tic is 5ms */
 
@@ -80,7 +82,7 @@
 	} else {
 		void *old_stack = (void *)Super(0);
 		now = *((volatile long *)_hz_200);
-		Super(old_stack);
+		SuperToUser(old_stack);
 	}
 
 	return((now*5)-start);
@@ -111,7 +113,7 @@
 	/* Install RunTimer in vbl vector */
 	old_stack = (void *)Super(0);
 	timer_installed = !SDL_AtariVblInstall(SDL_ThreadedTimerCheck);
-	Super(old_stack);
+	SuperToUser(old_stack);
 
 	if (!timer_installed) {
 		return(-1);
@@ -127,7 +129,7 @@
 	if (timer_installed) {
 		void *old_stack = (void *)Super(0);
 		SDL_AtariVblUninstall(SDL_ThreadedTimerCheck);
-		Super(old_stack);
+		SuperToUser(old_stack);
 		timer_installed = SDL_FALSE;
 	}
 	read_hz200_from_vbl = SDL_FALSE;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/ataricommon/SDL_atarisuper.h	Tue Jan 10 21:12:45 2012 +0100
@@ -0,0 +1,61 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2012 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+#include "SDL_config.h"
+
+#ifndef _ATARI_SUPER_h
+#define _ATARI_SUPER_h
+
+#include "SDL_stdinc.h"
+
+#ifndef SuperToUser
+
+/*
+ * Safe binding to switch back from supervisor to user mode.
+ * On TOS or EmuTOS, if the stack pointer has changed between Super(0)
+ * and Super(oldssp), the resulting user stack pointer is wrong.
+ * This bug does not occur with FreeMiNT.
+ * So the safe way to return from supervisor to user mode is to backup
+ * the stack pointer then restore it after the trap.
+ * Sometimes, GCC optimizes the stack usage, so this matters.
+ */
+#define SuperToUser(ptr)						\
+(void)__extension__							\
+({									\
+	register long retvalue __asm__("d0");				\
+	register long sp_backup;					\
+									\
+	__asm__ volatile						\
+	(								\
+		"movl	sp,%1\n\t"					\
+		"movl	%2,sp@-\n\t"					\
+		"movw	#0x20,sp@-\n\t"					\
+		"trap	#1\n\t"						\
+		"movl	%1,sp\n\t"					\
+	: "=r"(retvalue), "=&r"(sp_backup)	/* outputs */		\
+	: "g"((long)(ptr)) 			/* inputs */		\
+	: "d1", "d2", "a0", "a1", "a2"		\
+	);								\
+})
+
+#endif /* SuperToUser */
+
+#endif /* _ATARI_SUPER_h */
--- a/src/video/ataricommon/SDL_xbiosevents.c	Mon Jan 09 07:06:36 2012 -0500
+++ b/src/video/ataricommon/SDL_xbiosevents.c	Tue Jan 10 21:12:45 2012 +0100
@@ -30,6 +30,7 @@
 #include <mint/osbind.h>
 
 #include "../../events/SDL_events_c.h"
+#include "SDL_atarisuper.h"
 #include "SDL_xbiosevents_c.h"
 #include "SDL_xbiosinterrupt_s.h"
 
@@ -75,7 +76,7 @@
 	);
 
 	/* Back to user mode */
-	Super(oldpile);
+	SuperToUser(oldpile);
 
 	SDL_AtariXbios_enabled=1;
 }
@@ -98,7 +99,7 @@
 	SDL_AtariXbios_Restore(kbdvecs);
 
 	/* Back to user mode */
-	Super(oldpile);
+	SuperToUser(oldpile);
 }
 
 static int atari_GetButton(int button)