added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / .unmaintained / m68k-native / exec / dispatch.s
blobd0aa42ede96312c62bb7696919d55d4699b5dbf4
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /*****************************************************************************
8 NAME
10 AROS_LH0(void, Dispatch,
12 LOCATION
13 struct ExecBase *, SysBase, 10, Exec)
15 FUNCTION
16 This function switches between the task in SysBase->ThisTask and
17 the first task in the ready list. It must be called from supervisor
18 mode with all registers set to the values of the underlying user
19 context and sp pointing to the normal exception frame (just as if
20 it was a routine in one of the interrupt vectors).
22 SysBase->IDNestCnt is moved to and from the task structures and
23 the interrupt control is prepared accordingly. The routines in
24 task->tc_Launch and task->tc_Switch are called if necessary and
25 a task exception for the new task is raised if TF_EXCEPT is set.
27 INPUTS
29 RESULT
31 NOTES
32 Raising an exception for a waiting task reactivates the task
33 completely.
35 If the current task (when calling this function) is not part of
36 one of the two task lists it gets lost.
38 This function is for internal exec use only.
40 This function is processor dependant.
42 EXAMPLE
44 BUGS
45 This function currently reads the global variable sysbase instead of
46 *(struct ExecBase **)4. This makes it usable for link libraries.
48 SEE ALSO
50 INTERNALS
51 For the task lists the following conditions must always be true as
52 long as SysBase->IDNestCnt>=0. Changes are legal with interrupts
53 Disable()d only:
55 * A task is in state TS_WAIT if and only if it is part of the waiting
56 list.
58 * It is in state TS_READY if and only if it is part of the ready list.
60 * SysBase->ThisTask always points to a legal task structure.
62 * In normal user context SysBase->ThisTask->tc_State is TS_RUN.
64 There are two possible exceptions from this rule:
66 * In supervisor mode when bit 15 of SysBase->AttnResched is set
67 (dispatch pending bit).
68 This ends by calling Dispatch() before falling down to user context.
70 * In exec code. This ends by calling Switch() before going back to
71 user code.
73 * The task in SysBase->ThisTask is one of the ready tasks with the
74 highest priority (round robin). There's an exception from this rule,
75 too:
77 * If dispatching is disabled and bit 7 of SysBase->AttnResched is set
78 (switch pending bit) it is allowed to have a running task with a
79 lower priority as a waiting one. This ends by calling Switch() as
80 soon as the dispatcher is reactivated.
82 * The ready list is sorted by priority.
84 * There is always at least one task willing to run - the busy task.
86 HISTORY
88 ******************************************************************************/
90 INTENA = 0xdff09a
91 INTEN = 0x4000
92 SET = 0x8000
94 /* Dispatching routine for the 68000.
95 Higher models (with FPU) need a slightly different
96 routine or the additional registers cannot be used!
99 #include "machine.i"
101 .text
102 .balign 4
103 .globl AROS_SLIB_ENTRY(Dispatch,Exec)
104 .type AROS_SLIB_ENTRY(Dispatch,Exec),@function
105 AROS_SLIB_ENTRY(Dispatch,Exec):
107 /* preserve a5 then move user stack pointer into it */
108 move.l a5,-(sp)
109 move.l usp,a5
111 /* move whole user context to user stack */
112 move.l (sp)+,-(a5)
113 move.w (sp)+,-(a5)
114 move.l (sp)+,-(a5)
115 movem.l d0-d7/a0-a4/a6,-(a5)
117 /* get SysBase */
118 move.l _SysBase,a6
120 /* disable interrupts the simple way */
121 move.w #0x2700,sr
123 /* get current task and store usp there */
124 move.l ThisTask(a6),a2
125 move.l a5,tc_SPReg(a2)
127 /* call the switch routine if necessary */
128 btst #TB_SWITCH,tc_Flags(a2)
129 beq noswch
130 move.l tc_Switch(a2),a5
131 jsr (a5)
133 /* store IDNestCnt and reenable interrupt hardware */
134 noswch: move.b IDNestCnt(a6),tc_IDNestCnt(a2)
135 move.b #-1,IDNestCnt(a6)
136 move.w #INTEN+SET,INTENA
138 /* get address of ready list */
139 lea.l TaskReady(a6),a0
141 /* remove first ready task in the list */
142 move.l (a0),a2
143 move.l (a2),a1
144 move.l a1,(a0)
145 move.l a0,4.w(a1)
147 /* and use it as new current task */
148 move.l a2,ThisTask(a6)
149 move.b #TS_RUN,d0
150 move.b d0,tc_State(a2)
152 /* restore IDNestCnt and disable interrupt hardware if necessary */
153 move.b tc_IDNestCnt(a2),IDNestCnt(a6)
154 bpl nodis
155 move.w #INTEN,INTENA
157 /* call the launch routine if necessary */
158 nodis: btst #TB_LAUNCH,tc_Flags(a2)
159 beq nolnch
160 move.l tc_Launch(a2),a5
161 jsr (a5)
163 /* get user stack pointer */
164 nolnch: move.l tc_SPReg(a2),a5
166 /* test task exception bit */
167 btst #TB_EXCEPT,tc_Flags(a2)
168 bne exc
170 /* not set. read complete user context */
171 movem.l (a5)+,d0-d7/a0-a4/a6
172 move.l (a5)+,-(sp)
173 move.w (a5)+,-(sp)
174 move.l (a5)+,-(sp)
176 /* restore usp and a5 and return */
177 move.l a5,usp
178 move.l (sp)+,a5
181 /* Raise a task exception.
182 The user stack looks like: a5, ccr, pc, a6, a4-a0, d7-d0.
183 Change that to pc, ccr, a5, a6, a4-a0, d7-d0
184 so that it's easier to restore the context.
186 exc: move.l 14*4(a5),d0
187 move.l 14*4+6(a5),14*4(a5)
188 move.l d0,14*4+6(a5)
190 /* do a Disable() to fall down to user context atomically */
191 jsr Disable(a6)
193 /* prepare going to user mode */
194 move.l a5,usp
195 move.l #usrexc,-(sp)
196 clr.w -(sp)
199 /* handle exception */
200 usrexc: jsr Exception(a6)
201 jsr Enable(a6)
203 /* restore context */
204 movem.l (sp)+,d0-d7/a0-a4/a6
205 move.l (sp)+,a5
206 move.w (sp)+,ccr
210 .globl AROS_SLIB_ENTRY(DispatchSup,Exec)
211 .type AROS_SLIB_ENTRY(DispatchSup,Exec),@function
212 AROS_SLIB_ENTRY(DispatchSup,Exec):
213 move.l AROS_SLIB_ENTRY(Dispatch,Exec),a5
214 jsr Supervisor(a5)