2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: The task Dispatcher for m68k; taken from i386native version of Cause().
9 #include <exec/execbase.h>
10 #include <exec/tasks.h>
11 #include <aros/asmcall.h>
12 #include <exec/interrupts.h>
13 #include <proto/exec.h>
14 #include <exec_intern.h>
15 #include <exec/ptrace.h>
20 #include <aros/debug.h>
22 void SaveRegs(struct Task
*task
, struct pt_regs
*regs
)
24 /* Copy registers from struct pt_regs into the user stack */
25 struct pt_regs
* dest
= (struct pt_regs
*)task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
27 * Use this rather than memcpy! It does NOT work otherwise
40 dest
->r10
= regs
->r10
;
41 dest
->r11
= regs
->r11
;
42 dest
->r12
= regs
->r12
;
45 dest
->lr_svc
= regs
->lr_svc
;
46 dest
->cpsr
= regs
->cpsr
;
49 while (i
< sizeof(struct pt_regs
)) {
50 ((UBYTE
*)dest
)[i
] = ((UBYTE
*)regs
)[i
];
54 task
->tc_SPReg
= (APTR
)regs
->sp
;
57 void RestoreRegs(struct Task
*task
, struct pt_regs
*regs
)
59 /* Copy registers from the task's stack into struct pt_regs */
60 struct pt_regs
* src
= (struct pt_regs
*task
->tc_UnionETask
.tc_ETask
->et_RegFrame
;
63 * Use this rather than memcpy! It does NOT work otherwise
81 regs
->lr_svc
= src
->lr_svc
;
82 regs
->cpsr
= src
->cpsr
;
85 while (i
< sizeof(struct pt_regs
)) {
86 ((UBYTE
*)regs
)[i
] = ((UBYTE
*)src
)[i
];
91 task
->tc_SPReg
= (APTR
)regs
->sp
;
94 #define SC_ENABLE(regs) (regs->cpsr &= 0xffffff7f)
95 #define SC_DISABLE(regs) (regs->cpsr |= 0x000000C0)
97 void sys_Dispatch(struct pt_regs
* regs
, LONG adjust
)
99 struct ExecBase
* SysBase
= (struct ExecBase
*)*(ULONG
*)0x04;
101 /* Hmm, interrupts are nesting, not a good idea... */
102 // if(user_mode(regs)) {
106 D(bug("In %s!!!\n",__FUNCTION__
));
107 D(bug("lr_svc=%x, r0=%x, r1=%x, r2=%x, r9=%x, r12=%x, sp=%x, lr=%x, cpsr=%x\n",
118 /* Check if a task switch is necessary */
119 /* 1. There has to be another task in the ready-list */
120 /* 2. The first task in the ready list hast to have the
121 same or higher priority than the currently active task */
123 if( SysBase
->TaskReady
.lh_Head
->ln_Succ
!= NULL
/*
124 ((BYTE)SysBase->ThisTask->tc_Node.ln_Pri <=
125 (BYTE)((struct Task *)SysBase->TaskReady.lh_Head)->tc_Node.ln_Pri ) */
128 /* Check if task switch is possible */
129 if( SysBase
->TDNestCnt
< 0 )
131 if( SysBase
->ThisTask
->tc_State
== TS_RUN
)
133 SysBase
->ThisTask
->tc_State
= TS_READY
;
134 Reschedule(SysBase
->ThisTask
);
135 SysBase
->AttnResched
|= 0x8000;
137 else if( SysBase
->ThisTask
->tc_State
== TS_REMOVED
)
138 SysBase
->AttnResched
|= 0x8000;
141 SysBase
->AttnResched
|= 0x80;
145 /* Has an interrupt told us to dispatch when leaving */
146 if (SysBase
->AttnResched
& 0x8000)
148 SysBase
->AttnResched
&= ~0x8000;
150 /* Save registers for this task (if there is one...) */
151 if (SysBase
->ThisTask
&& SysBase
->ThisTask
->tc_State
!= TS_REMOVED
) {
152 regs
->lr_svc
-= adjust
; // adjust is 0 or -4
153 SaveRegs(SysBase
->ThisTask
, regs
);
156 /* Tell exec that we have actually switched tasks... */
158 //D(bug("DISPATCHER: New task: %s\n",SysBase->ThisTask->tc_Node.ln_Name));
160 /* Get the registers of the old task */
161 RestoreRegs(SysBase
->ThisTask
, regs
);
162 regs
->lr_svc
+= adjust
; // adjust is 0 or -4
164 /* Make sure that the state of the interrupts is what the task
167 if (SysBase
->IDNestCnt
< 0)
172 D(bug("after: lr_svc=%x, r0=%x, r1=%x, r2=%x, r9=%x, r12=%x, sp=%x, lr=%x, cpsr=%x (adjust=%d)\n",
184 /* Ok, the next step is to either drop back to the new task, or
185 give it its Exception() if it wants one... */
187 if (SysBase
->ThisTask
->tc_Flags
& TF_EXCEPT
) {
196 /* Leave the interrupt. */