1 | /* cpu_asm.s |
---|
2 | * |
---|
3 | * This file contains all assembly code for the i960CA implementation |
---|
4 | * of RTEMS. |
---|
5 | * |
---|
6 | * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. |
---|
7 | * On-Line Applications Research Corporation (OAR). |
---|
8 | * All rights assigned to U.S. Government, 1994. |
---|
9 | * |
---|
10 | * This material may be reproduced by or for the U.S. Government pursuant |
---|
11 | * to the copyright license under the clause at DFARS 252.227-7013. This |
---|
12 | * notice must appear in all copies of this file and its derivatives. |
---|
13 | * |
---|
14 | * $Id$ |
---|
15 | */ |
---|
16 | |
---|
17 | .text |
---|
18 | /* |
---|
19 | * Format of i960ca Register structure |
---|
20 | */ |
---|
21 | |
---|
22 | .set REG_R0_PFP , 0 # (r0) Previous Frame Pointer |
---|
23 | .set REG_R1_SP , REG_R0_PFP+4 # (r1) Stack Pointer |
---|
24 | .set REG_PC , REG_R1_SP+4 # (pc) Processor Controls |
---|
25 | .set REG_G8 , REG_PC+4 # (g8) Global Register 8 |
---|
26 | .set REG_G9 , REG_G8+4 # (g9) Global Register 9 |
---|
27 | .set REG_G10 , REG_G9+4 # (g10) Global Register 10 |
---|
28 | .set REG_G11 , REG_G10+4 # (g11) Global Register 11 |
---|
29 | .set REG_G12 , REG_G11+4 # (g12) Global Register 12 |
---|
30 | .set REG_G13 , REG_G12+4 # (g13) Global Register 13 |
---|
31 | .set REG_G14 , REG_G13+4 # (g14) Global Register 14 |
---|
32 | .set REG_G15_FP , REG_G14+4 # (g15) Global Register 15 |
---|
33 | .set SIZE_REGS , REG_G15_FP+4 # size of cpu_context_registers |
---|
34 | # structure |
---|
35 | |
---|
36 | /* |
---|
37 | * void _CPU_Context_switch( run_context, heir_context ) |
---|
38 | * |
---|
39 | * This routine performs a normal non-FP context. |
---|
40 | */ |
---|
41 | .align 4 |
---|
42 | .globl __CPU_Context_switch |
---|
43 | |
---|
44 | __CPU_Context_switch: |
---|
45 | modpc 0,0,g2 # get old intr level (PC) |
---|
46 | st g2,REG_PC(g0) # save pc |
---|
47 | stq g8,REG_G8(g0) # save g8-g11 |
---|
48 | stq g12,REG_G12(g0) # save g12-g15 |
---|
49 | stl pfp,REG_R0_PFP(g0) # save pfp, sp |
---|
50 | |
---|
51 | restore: flushreg # flush register cache |
---|
52 | ldconst 0x001f0000,g2 # g2 = PC mask |
---|
53 | ld REG_PC(g1),g3 # thread->Regs.pc = pc; |
---|
54 | ldq REG_G12(g1),g12 # restore g12-g15 |
---|
55 | ldl REG_R0_PFP(g1),pfp # restore pfp, sp |
---|
56 | ldq REG_G8(g1),g8 # restore g8-g11 |
---|
57 | modpc 0,g2,g3 # restore PC register |
---|
58 | ret |
---|
59 | |
---|
60 | /* |
---|
61 | * void _CPU_Context_restore( new_context ) |
---|
62 | * |
---|
63 | * This routine performs a normal non-FP context. |
---|
64 | */ |
---|
65 | |
---|
66 | .globl __CPU_Context_restore |
---|
67 | __CPU_Context_restore: |
---|
68 | mov g0,g1 # g0 = _Thread_executing |
---|
69 | b restore |
---|
70 | |
---|
71 | /*PAGE |
---|
72 | * void _CPU_Context_save_fp_context( &fp_context_ptr ) |
---|
73 | * void _CPU_Context_restore_fp_context( &fp_context_ptr ) |
---|
74 | * |
---|
75 | * There is currently no hardware floating point for the i960. |
---|
76 | */ |
---|
77 | |
---|
78 | .globl __CPU_Context_save_fp |
---|
79 | .globl __CPU_Context_restore_fp |
---|
80 | __CPU_Context_save_fp: |
---|
81 | __CPU_Context_restore_fp: |
---|
82 | #if ( I960_HAS_FPU == 1 ) |
---|
83 | #error "Floating point support for i960 family has been implemented!!!" |
---|
84 | #endif |
---|
85 | ret |
---|
86 | |
---|
87 | /*PAGE |
---|
88 | * void __ISR_Handler() |
---|
89 | * |
---|
90 | * This routine provides the RTEMS interrupt management. |
---|
91 | * |
---|
92 | * Input parameters: NONE |
---|
93 | * |
---|
94 | * Output parameters: NONE |
---|
95 | * |
---|
96 | * NOTE: |
---|
97 | * Upon entry, the supervisor stack will contain a stack frame |
---|
98 | * back to the interrupted thread and the interrupt stack will contain |
---|
99 | * an interrupt stack frame. If dispatching is enabled, this |
---|
100 | * is the outer most interrupt, and (a context switch is necessary or |
---|
101 | * the current thread has signals), then set up the supervisor stack to |
---|
102 | * transfer control to the interrupt dispatcher. |
---|
103 | */ |
---|
104 | |
---|
105 | .globl __ISR_Handler |
---|
106 | __ISR_Handler: |
---|
107 | #ldconst 1,r8 |
---|
108 | #modpc 0,r8,r8 # enable tracing |
---|
109 | |
---|
110 | # r4 = &_Thread_Dispatch_disable_level |
---|
111 | ld __Thread_Dispatch_disable_level,r4 |
---|
112 | movl g0,r8 # save g0-g1 |
---|
113 | |
---|
114 | ld -16+8(fp),g0 # g0 = vector number |
---|
115 | movl g2,r10 # save g2-g3 |
---|
116 | |
---|
117 | ld __ISR_Nest_level,r5 # r5 = &_Isr_nest_level |
---|
118 | mov g14,r7 # save g14 |
---|
119 | |
---|
120 | lda 0,g14 # NOT Branch and Link |
---|
121 | movl g4,r12 # save g4-g5 |
---|
122 | |
---|
123 | lda 1(r4),r4 # increment dispatch disable level |
---|
124 | movl g6,r14 # save g6-g7 |
---|
125 | |
---|
126 | ld __ISR_Vector_table[g0*4],g1 # g1 = Users handler |
---|
127 | addo 1,r5,r5 # increment ISR level |
---|
128 | |
---|
129 | st r4,__Thread_Dispatch_disable_level |
---|
130 | # one ISR nest level deeper |
---|
131 | subo 1,r4,r4 # decrement dispatch disable level |
---|
132 | |
---|
133 | st r5,__ISR_Nest_level # disable multitasking |
---|
134 | subo 1,r5,r5 # decrement ISR nest level |
---|
135 | |
---|
136 | callx (g1) # invoke user ISR |
---|
137 | |
---|
138 | st r4,__Thread_Dispatch_disable_level |
---|
139 | # unnest multitasking |
---|
140 | st r5,__ISR_Nest_level # one less ISR nest level |
---|
141 | cmpobne.f 0,r4,exit # If dispatch disabled, exit |
---|
142 | ldl -16(fp),g0 # g0 = threads PC reg |
---|
143 | # g1 = threads AC reg |
---|
144 | ld __Context_Switch_necessary,r6 |
---|
145 | # r6 = Is thread switch necessary? |
---|
146 | bbs.f 13,g0,exit # not outer level, then exit |
---|
147 | cmpobne.f 0,r6,bframe # Switch necessary? |
---|
148 | |
---|
149 | ld __ISR_Signals_to_thread_executing,g2 |
---|
150 | # signals sent to Run_thread |
---|
151 | # while in interrupt handler? |
---|
152 | cmpobe.f 0,g2,exit # No, then exit |
---|
153 | |
---|
154 | bframe: mov 0,g2 |
---|
155 | st g2,__ISR_Signals_to_thread_executing |
---|
156 | |
---|
157 | ldconst 0x1f0000,g2 # g2 = intr disable mask |
---|
158 | mov g2,g3 # g3 = new intr level |
---|
159 | modpc 0,g2,g3 # set new level |
---|
160 | |
---|
161 | andnot 7,pfp,r4 # r4 = pfp without ret type |
---|
162 | flushreg # flush registers |
---|
163 | # push _Isr_dispatch ret frame |
---|
164 | # build ISF in r4-r6 |
---|
165 | ldconst 64,g2 # g2 = size of stack frame |
---|
166 | ld 4(r4),g3 # g3 = previous sp |
---|
167 | addo g2,g3,r5 # r5 = _Isr_dispatch SP |
---|
168 | lda __ISR_Dispatch,r6 # r6 = _Isr_dispatch entry |
---|
169 | stt r4,(g3) # set _Isr_dispatch ret info |
---|
170 | st g1,16(g3) # set r4 = AC for ISR disp |
---|
171 | or 7,g3,pfp # pfp to _Isr_dispatch |
---|
172 | |
---|
173 | exit: mov r7,g14 # restore g14 |
---|
174 | movq r8,g0 # restore g0-g3 |
---|
175 | movq r12,g4 # restore g4-g7 |
---|
176 | ret |
---|
177 | |
---|
178 | |
---|
179 | /*PAGE |
---|
180 | * |
---|
181 | * void __ISR_Dispatch() |
---|
182 | * |
---|
183 | * Entry point from the outermost interrupt service routine exit. |
---|
184 | * The current stack is the supervisor mode stack. |
---|
185 | */ |
---|
186 | |
---|
187 | __ISR_Dispatch: |
---|
188 | mov g14,r7 |
---|
189 | mov 0,g14 |
---|
190 | movq g0,r8 |
---|
191 | movq g4,r12 |
---|
192 | call __Thread_Dispatch |
---|
193 | |
---|
194 | ldconst -1,r5 # r5 = reload mask |
---|
195 | modac r5,r4,r4 # restore threads AC register |
---|
196 | mov r7,g14 |
---|
197 | movq r8,g0 |
---|
198 | movq r12,g4 |
---|
199 | ret |
---|