summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/gen68340/console/Modif_cpu_asm.S
blob: 0da5865fb3dbb2ba6c869b879b884ea38c3c2e9d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*  cpu_asm.s
 *
 *  This file contains all assembly code for the MC68020 implementation
 *  of RTEMS.
 *
 *  ATTENTION: Modified for benchmarks
 *
 *  COPYRIGHT (c) 1989-1998.
 *  On-Line Applications Research Corporation (OAR).
 *  Copyright assigned to U.S. Government, 1994.
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.OARcorp.com/rtems/license.html.
 *
 *  $Id$
 */


#include <asm.h>

        .text

/*PAGE
 *  void _Debug_ISR_Handler_Console()
 *
 *  This routine provides the RTEMS interrupt management.
 *
 *  NOTE:
 *    Upon entry, the master stack will contain an interrupt stack frame
 *    back to the interrupted thread and the interrupt stack will contain
 *    a throwaway interrupt stack frame.  If dispatching is enabled, this
 *    is the outer most interrupt, and (a context switch is necessary or
 *    the current thread has signals), then set up the master stack to
 *    transfer control to the interrupt dispatcher.
 *  NOTE:
 *    USED TO MESURE THE TIME SPENT IN THE INTERRUPT SUBROUTINE
 *    CS5 - CS8 are linked to an oscilloscope so that you can mesure
 *    RTEMS overhead (BTW it's very short :) )
 */

/*
 *  With this approach, lower priority interrupts may
 *  execute twice if a higher priority interrupt is
 *  acknowledged before _Thread_Dispatch_disable is
 *  increamented and the higher priority interrupt
 *  preforms a context switch after executing. The lower
 *  priority intterrupt will execute (1) at the end of the
 *  higher priority interrupt in the new context if
 *  permitted by the new interrupt level mask, and (2) when
 *  the original context regains the cpu.
 */
 
#if ( M68K_HAS_VBR == 1)
.set SR_OFFSET,    0                     | Status register offset
.set PC_OFFSET,    2                     | Program Counter offset
.set FVO_OFFSET,   6                     | Format/vector offset
#else
.set SR_OFFSET,    2                     | Status register offset
.set PC_OFFSET,    4                     | Program Counter offset
.set FVO_OFFSET,   0                     | Format/vector offset placed in the stack
#endif /* M68K_HAS_VBR */
 
.set SAVED,        16                    | space for saved registers

        .align  4
        .global SYM (_Debug_ISR_Handler_Console)

SYM (_Debug_ISR_Handler_Console):

					 |
	tst.w	0x14000000		 | ALLUME CS5 
					 |

        addql   #1,SYM (_Thread_Dispatch_disable_level) | disable multitasking
        moveml  d0-d1/a0-a1,a7@-         | save d0-d1,a0-a1
        movew   a7@(SAVED+FVO_OFFSET),d0 | d0 = F/VO
        andl    #0x0fff,d0               | d0 = vector offset in vbr


#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 )
	movew	sr,d1			| Save status register
	oriw	#0x700,sr		| Disable interrupts
	tstl	SYM (_ISR_Nest_level)	| Interrupting an interrupt handler?
	bne	1f			| Yes, just skip over stack switch code
	movel	SYM(_CPU_Interrupt_stack_high),a0	| End of interrupt stack
	movel	a7,a0@-			| Save task stack pointer
	movel	a0,a7			| Switch to interrupt stack
1:
	addql   #1,SYM(_ISR_Nest_level)	| one nest level deeper
	movew	d1,sr			| Restore status register
#else
	addql   #1,SYM (_ISR_Nest_level) | one nest level deeper
#endif /* CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 */

#if ( M68K_HAS_PREINDEXING == 1 )
        movel   @( SYM (_ISR_Vector_table),d0:w:1),a0| fetch the ISR
#else
        movel   # SYM (_ISR_Vector_table),a0   | a0 = base of RTEMS table
        addal   d0,a0                    | a0 = address of vector
        movel   (a0),a0                  | a0 = address of user routine
#endif

        lsrl    #2,d0                    | d0 = vector number
        movel   d0,a7@-                  | push vector number

					 |
	tst.w	0x18000000		 | ALLUME CS6
					 |

        jbsr    a0@                      | invoke the user ISR

					 |
	tst.w	0x18000000		 | ALLUME CS6
					 |

        addql   #4,a7                    | remove vector number

#if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 )
	movew	sr,d0			| Save status register
	oriw	#0x700,sr		| Disable interrupts
	subql	#1,SYM(_ISR_Nest_level)	| Reduce interrupt-nesting count
	bne	1f			| Skip if return to interrupt
	movel	(a7),a7			| Restore task stack pointer
1:
	movew	d0,sr			| Restore status register
#else
	subql   #1,SYM (_ISR_Nest_level) | one less nest level
#endif /* CPU_HAS_SOFTWARE_INTERRUPT_STACK == 1 */

        subql   #1,SYM (_Thread_Dispatch_disable_level)
                                         | unnest multitasking
        bne     Debug_exit                     | If dispatch disabled, Debug_exit

#if ( M68K_HAS_SEPARATE_STACKS == 1 )
        movew   #0xf000,d0               | isolate format nibble
        andw    a7@(SAVED+FVO_OFFSET),d0 | get F/VO
        cmpiw   #0x1000,d0               | is it a throwaway isf?
        bne     Debug_exit                     | NOT outer level, so branch
#endif

        tstl    SYM (_Context_Switch_necessary)
                                         | Is thread switch necessary?
        bne     bframe                   | Yes, invoke dispatcher

        tstl    SYM (_ISR_Signals_to_thread_executing)
                                         | signals sent to Run_thread
                                         |   while in interrupt handler?
        beq     Debug_exit               | No, then Debug_exit


bframe: clrl    SYM (_ISR_Signals_to_thread_executing)
                                         | If sent, will be processed
#if ( M68K_HAS_SEPARATE_STACKS == 1 )
        movec   msp,a0                   | a0 = master stack pointer
        movew   #0,a0@-                  | push format word
        movel   # SYM (_ISR_Dispatch),a0@- | push return addr
        | filter out the trace bit to stop single step debugging breaking
        movew   a0@(6+SR_OFFSET),d0
        andw    #0x7FFF,d0
        movew   d0,a0@-                  | push thread sr
        movec   a0,msp                   | set master stack pointer
#else

        | filter out the trace bit to stop single step debugging breaking
        movew   a7@(16+SR_OFFSET),d0
        andw    #0x7FFF,d0
        movew   d0,sr
        jsr SYM (_Thread_Dispatch)
#endif

Debug_exit:   moveml  a7@+,d0-d1/a0-a1         | restore d0-d1,a0-a1
#if ( M68K_HAS_VBR == 0 )
        addql   #2,a7                    | pop format/id
#endif /* M68K_HAS_VBR */

					 |
	tst.w	0x1C000000		 | ALLUME CS7
					 |

        rte                              | return to thread
                                         |   OR _Isr_dispatch