Removed __startup attribute. It is already present in AROS_SHxx definition, and doubl...
[AROS.git] / arch / m68k-mac / exec / superstate.S
blobd4d1e0a182f1fee2d1f24e9a9fd2b741c3b1ef0f
1 /*
2     Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3     $Id$
4 */
6 /*****************************************************************************
7  
8     NAME
9  
10         AROS_LH0(ULONG, SuperState,
12     LOCATION
13         struct ExecBase *, SysBase, 25, Exec)
15     FUNCTION
16         Enter supervisor mode (like Supervisor()), but return on the user
17         stack. This will mean that the user stack variables are still there.
18         A call to UserState() will end this mode.
20     INPUTS
21         None.
23     RESULT
24         The old supervisor stack. This must be passed to UserState(). If the
25         processor was already in supervisor mode, then this function will
26         return NULL. In that case do NOT call UserState().
28     NOTES
29         This is not a good function to use, it has limited scope, and will
30         probably be even less useful in the future.
32     EXAMPLE
34     BUGS
35         You can easily cause your system to cease operating normally.
37     SEE ALSO
38         Supervisor(), UserState()
40     INTERNALS
41         For extra details see Supervisor().
43     HISTORY
45 ******************************************************************************/
47         #include "aros/m68k/asm.h"
49         .text
50         .balign 4
51         .globl  AROS_SLIB_ENTRY(SuperState,Exec,25)
53 AROS_SLIB_ENTRY(SuperState,Exec,25):
54 #if DoRegisterCalls
55         move.l  $4,%a6         // Get SysBase
56 #endif
57         movem.l %d0/%d1,-(%sp)
58         clr.l   %d0
59         clr.l   %d1
60         jmp     SetSR(%a6)     // %d0 will contain current state
61                                // (supervisor/user)
62         and.w   0x2000,%d0     // this should test the user or superstate
63                                // bit
64         beq     go_on
65         movem.l (%sp)+,%d0/%d1 // already in superstate
66         clr.l   %d0
67         rts
69 go_on:  movem.l (%sp)+,%d0/%d1 // switch to superstate
71         move.l  %d7,-(%sp)
72         move.l  #12,%d7     // #12 => call _sys_trap1_SuperState
73         trap    #1
74         move.l  (%sp)+,%d7  // should never get here!!!
75         rts
77         .balign 4
78         .globl _sys_trap1_SuperState
79 _sys_trap1_SuperState:
80         /*
81          * This is how the supervisor stack looks like...
82          * 0(%ssp) SR (WORD)
83          * 2(%ssp) PC (LONG) - contains address of instruction after
84          *                     trap #1 above
85          *
86          * And this is how the user stack looks like
87          * 0(%usp) PC (LONG) - instruction after from where the SuperState()
88          *                     was called
89          * 4(%usp) D7 (LONG)
90          */
91         move.l  %ssp,%d0
92         move.l  %a0,-4(%sp)   // save %a0 on -4(SSP)
93         move.l  %usp,%a0
94         move.l  %a0,%ssp      // load ssp with usp
96         move.l  4(%ssp),%d7   // restore d7
97         move.l  (%ssp),%a0    // move the return PC to where D7 was
98         move.l  %a0,4(%ssp)
99         move.l  %d0,%a0       // %a0 = initial ssp
100         move.l  -4(%a0),%a0   // restore %a0
101         adda.l  #4,%ssp       // now (%ssp) is the return PC
102         rts