comparison packages/hal/sparclite/arch/current/src/icontext.c @ 2:443894e2e912 ecos-v1_2_1-release

Block commit of eCos version 1.2.1
author jlarmour
date Tue, 11 May 1999 12:24:34 +0000
parents
children d376b777e2ce
comparison
equal deleted inserted replaced
1:72f549f0d891 2:443894e2e912
1 /*=============================================================================
2 //
3 // icontext.c
4 //
5 // SPARClite HAL context init function
6 //
7 //=============================================================================
8 //####COPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 // The contents of this file are subject to the Cygnus eCos Public License
12 // Version 1.0 (the "License"); you may not use this file except in
13 // compliance with the License. You may obtain a copy of the License at
14 // http://sourceware.cygnus.com/ecos
15 //
16 // Software distributed under the License is distributed on an "AS IS"
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
18 // License for the specific language governing rights and limitations under
19 // the License.
20 //
21 // The Original Code is eCos - Embedded Cygnus Operating System, released
22 // September 30, 1998.
23 //
24 // The Initial Developer of the Original Code is Cygnus. Portions created
25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved.
26 // -------------------------------------------
27 //
28 //####COPYRIGHTEND####
29 //=============================================================================
30 //#####DESCRIPTIONBEGIN####
31 //
32 // Author(s): hmt
33 // Contributors: hmt
34 // Date: 1998-12-14
35 // Purpose: HAL context initialization function
36 // Description: Initialize a HAL context for SPARClite; this is in C and out
37 // of line because there is too much of it for a simple macro.
38 //
39 //####DESCRIPTIONEND####
40 //
41 //===========================================================================*/
42
43 #include <pkgconf/hal.h>
44
45 #include <cyg/hal/hal_arch.h> // HAL header
46
47 #include <cyg/infra/cyg_type.h>
48
49 #include <cyg/hal/vectors.h> // SAVE_REGS_SIZE, __WINSIZE, ...
50
51 /*---------------------------------------------------------------------------*/
52
53 /* We lay out the stack in the manner that the PCS demands:
54 * frame pointer -----> [top of stack]
55 * Argument spill area (6 words)
56 * Return Arg pointer
57 * Initial saved register window (i[8], l[8])
58 * for use by program when it starts
59 * [rest of] saved register object (various)
60 * stack pointer -----> saved register window (i[8], l[8])
61 * to allow us to be interrupted.
62 *
63 * ie. frame pointer ->
64 * struct HAL_FrameStructure
65 * stack pointer -> struct HAL_SavedRegisters
66 *
67 * and when the context "resumes" sp is incremented by 40 * 4, the size of
68 * a _struct HAL_SavedRegisters_ which points it at the extant but unused
69 * _struct HAL_FrameStructure_ as the PCS requires. The frame pointer is
70 * left pointing off the top of stack.
71 *
72 *
73 * Thus the stack is the same if created from an already executing context:
74 *
75 * frame pointer ----->
76 * [temporaries and locals]
77 * [more arguments]
78 * Argument spill area (6 words)
79 * Return Arg pointer
80 * [sp at entry]------> Previous saved register window (i[8], l[8])
81 * for use by program when it starts
82 * [rest of] saved register object (various)
83 * stack pointer -----> saved register window (i[8], l[8])
84 * to allow us to be interrupted.
85 */
86
87 CYG_ADDRESS
88 hal_thread_init_context( CYG_WORD sparg,
89 CYG_WORD thread,
90 CYG_WORD entry,
91 CYG_WORD id )
92 {
93 register CYG_WORD fp = sparg;
94 register CYG_WORD sp = 0;
95 register HAL_SavedRegisters *regs;
96 register HAL_FrameStructure *frame;
97 int i;
98
99 if ( 0 == (id & 0xffff0000) )
100 id <<= 16;
101
102 fp &= ~7; // round down to double alignment
103
104 frame = (HAL_FrameStructure *)(
105 fp - sizeof( HAL_FrameStructure ) );
106
107 regs = (HAL_SavedRegisters *)(
108 ((CYG_WORD)frame) - sizeof(HAL_SavedRegisters) );
109
110 sp = (CYG_WORD)regs;
111
112 for ( i = 0; i < 6; i++ ) {
113 frame->spill_args[i] = id | 0xa0 | i;
114 }
115 frame->composite_return_ptr = 0;
116
117 for ( i = 0; i < 8; i++ ) {
118 frame->li.i[i] = id | ( 56 + i );
119 frame->li.l[i] = id | ( 48 + i );
120 regs ->li.i[i] = id | ( 24 + i );
121 regs ->li.l[i] = id | ( 16 + i );
122 regs ->o[i] = id | ( 8 + i );
123 regs ->g[i] = id | ( i );
124 }
125
126 // first terminate the linked list on the stack in the initial
127 // (already saved) register window:
128 frame->li.i[6] = regs->li.i[6] = (cyg_uint32)fp; // frame pointer
129 frame->li.i[7] = regs->li.i[7] = (cyg_uint32)0; // no ret addr here
130
131 // and set up other saved regs as if called from just before
132 // the entry point:
133 regs->o[7] = (entry - 8);
134 regs->o[6] = sp;
135
136 // this is the argument that the entry point is called with
137 regs->o[0] = thread;
138
139 // this is the initial CWP; quite arbitrary really, the WIM is set up
140 // accordingly in hal_thread_load_context().
141
142 regs->g[0] = 7;
143
144 return (CYG_ADDRESS)sp;
145 }
146
147 // ---------------------------------------------------------------------------
148
149 //#define THREAD_DEBUG_SERIAL_VERBOSE
150
151 #ifdef THREAD_DEBUG_SERIAL_VERBOSE // NOT INCLUDED
152
153 // This is unpleasant to try to debug, because these routines are called
154 // WHEN THE PROGRAM IS NOT RUNNING from the CygMon's GDB stubs - so you
155 // can't use any normal output: these little routines use the serial
156 // line directly, so are best used when debugging via Ethernet, so you
157 // just have a separate output stream to read. Nasty...
158
159 #include <cyg/hal/hal_diag.h>
160
161 #undef HAL_DIAG_WRITE_CHAR
162 #define HAL_DIAG_WRITE_CHAR(_c_) CYG_MACRO_START \
163 SLEB_LED = (_c_); \
164 HAL_DIAG_WRITE_CHAR_DIRECT( _c_ ); \
165 CYG_MACRO_END
166
167 static void swritec( char c )
168 {
169 HAL_DIAG_WRITE_CHAR( c );
170 }
171
172 static void swrites( char *s )
173 {
174 char c;
175 while ( 0 != (c = *s++) )
176 HAL_DIAG_WRITE_CHAR( c );
177 }
178
179 static void swritex( cyg_uint32 x )
180 {
181 int i;
182 swrites( "0x" );
183 for ( i = 28; i >= 0; i-= 4 ) {
184 char c = "0123456789abcdef"[ 0xf & (x >> i) ];
185 HAL_DIAG_WRITE_CHAR( c );
186 }
187 }
188
189 #define newline() swrites( "\n\r" )
190
191 static void x8( char *s, unsigned long *xp )
192 {
193 int i;
194 for ( i = 0; i < 8; i++ ) {
195 swrites( s );
196 swritec( '0' + i );
197 swrites( " = " );
198 swritex( xp[i] );
199 if ( 3 == (i & 3) )
200 newline();
201 else
202 swrites( " " );
203 }
204 }
205
206 #endif // THREAD_DEBUG_SERIAL_VERBOSE ... NOT INCLUDED
207
208 // ---------------------------------------------------------------------------
209 // Routines in icontext.c used here because they're quite large for
210 // the SPARClite (note param order); these are used in talking to GDB.
211
212 enum regnames {G0 = 0, G1, G2, G3, G4, G5, G6, G7,
213 O0, O1, O2, O3, O4, O5, SP, O7,
214 L0, L1, L2, L3, L4, L5, L6, L7,
215 I0, I1, I2, I3, I4, I5, FP, I7,
216
217 F0, F1, F2, F3, F4, F5, F6, F7,
218 F8, F9, F10, F11, F12, F13, F14, F15,
219 F16, F17, F18, F19, F20, F21, F22, F23,
220 F24, F25, F26, F27, F28, F29, F30, F31,
221 Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR};
222
223 typedef unsigned long target_register_t;
224
225 void
226 cyg_hal_sparc_get_gdb_regs( void *gdb_regset,
227 HAL_SavedRegisters *eCos_regset )
228 {
229 target_register_t *gdb = (target_register_t *)gdb_regset;
230 int reg;
231 cyg_uint32 scratch = 0;
232 cyg_uint32 *sptrap;
233 HAL_SavedWindow *trapli, *ctxli;
234
235 if ( 0 == eCos_regset->g[0] ||
236 0xc0 == (0xe0 & eCos_regset->g[0]) ) {
237 // Then it's an interrupt stack saved state:
238 // (either minimal, or a saved PSR with traps disabled)
239 // The saved register set is pretty minimal, so we have to grub
240 // around in the stack to find out some truth...
241 sptrap = (cyg_uint32 *)eCos_regset; // point to the IL save area for
242 sptrap -= 24; // the trap handler, for PC, NPC
243 trapli = (HAL_SavedWindow *)sptrap; // Get at those regs
244
245 ctxli = (HAL_SavedWindow *)(trapli->i[6]); // (the frame pointer)
246 // and get at the interruptee's regs
247
248 // Pick up interruptee's registers from all over the stack:
249 for ( reg = 0; reg < 8 ; reg++ ) {
250 gdb[ G0 + reg ] = eCos_regset->g[reg];
251 gdb[ O0 + reg ] = trapli->i[reg];
252 gdb[ L0 + reg ] = ctxli->l[reg];
253 gdb[ I0 + reg ] = ctxli->i[reg];
254 }
255
256 // Clear out G0 which is always 0 (but abused in eCos_regset)
257 // and the FP regs which we do not have:
258 gdb[ G0 ] = 0;
259 for ( reg = F0; reg <= F31; reg++ )
260 gdb[ reg ] = 0;
261
262 // In the save context _of the trap handler_ registers are as follows:
263 // %l0 = psr (with this CWP/window-level in it)
264 // %l1 = pc
265 // %l2 = npc
266 // %l3 = vector number (1-15 for interrupts)
267 // %l4 = Y register preserved
268 gdb[ Y ] = trapli->l[4];
269
270 scratch = trapli->l[0]; // the PSR in the trap handler
271 scratch++; // back to interupted thread's window
272 scratch &=~ 0x38; // clear ET and any CWP overflow
273 gdb[ PSR ] = scratch;
274 gdb[ WIM ] = 1 << ((__WINBITS & (1 + scratch)));
275
276 // Read _a_ TBR value and ignore the current trap details:
277 asm volatile ( "rd %%tbr, %0" : "=r"(scratch) : );
278 gdb[ TBR ] = (scratch &~ 0xfff);
279
280 gdb[ PC ] = trapli->l[1];
281 gdb[ NPC ] = trapli->l[2];
282
283 gdb[ FPSR ] = 0;
284 gdb[ CPSR ] = 0;
285
286 #ifdef THREAD_DEBUG_SERIAL_VERBOSE
287 newline();
288 swrites( "-----------------------------------------------------" ); newline();
289 swrites( "-------------- INTERRUPT STACK GET ------------------" ); newline();
290 swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
291 swrites( " trapli " ); swritex( trapli ); newline();
292 swrites( " ctxli " ); swritex( ctxli ); newline();
293 x8( "global ", &(gdb[G0]) );
294 x8( " in ", &(gdb[I0]) );
295 x8( " local ", &(gdb[L0]) );
296 x8( " out ", &(gdb[O0]) );
297 swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
298 swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
299 swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
300 #endif
301
302 }
303 else {
304 // It's a synchronous context switch that led to this object.
305 // Pick up interruptee's registers from the saved context:
306 for ( reg = 0; reg < 8 ; reg++ ) {
307 #ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
308 gdb[ G0 + reg ] = 0;
309 gdb[ O0 + reg ] = 0;
310 #else
311 gdb[ G0 + reg ] = eCos_regset->g[reg];
312 gdb[ O0 + reg ] = eCos_regset->o[reg];
313 #endif
314 gdb[ L0 + reg ] = eCos_regset->li.l[reg];
315 gdb[ I0 + reg ] = eCos_regset->li.i[reg];
316 }
317
318 #ifdef CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM
319 // Set up the stack pointer by arithmetic and the return address
320 gdb[ SP ] = ((cyg_uint32)(eCos_regset));
321 gdb[ O7 ] = eCos_regset->o[ 7 ];
322 #else
323 // Clear out G0 which is always 0 (but abused in eCos_regset)
324 gdb[ G0 ] = 0;
325 #endif
326 // and clear the FP regs which we do not have:
327 for ( reg = F0; reg <= F31; reg++ )
328 gdb[ reg ] = 0;
329
330 gdb[ Y ] = 0; // it's not preserved.
331
332 scratch = eCos_regset->g[ 0 ]; // the PSR in the saved context
333 gdb[ PSR ] = scratch; // return it verbatim.
334 gdb[ WIM ] = 1 << ((__WINBITS & (1 + scratch)));
335
336 // Read _a_ TBR value and ignore the current trap details:
337 asm volatile ( "rd %%tbr, %0" : "=r"(scratch) : );
338 gdb[ TBR ] = (scratch &~ 0xfff);
339
340 gdb[ PC ] = eCos_regset->o[ 7 ]; // the return address
341 gdb[ NPC ] = 4 + gdb[ PC ];
342
343 gdb[ FPSR ] = 0;
344 gdb[ CPSR ] = 0;
345
346 #ifdef THREAD_DEBUG_SERIAL_VERBOSE
347 newline();
348 swrites( "-----------------------------------------------------" ); newline();
349 swrites( "-------------- SYNCHRONOUS SWITCH GET----------------" ); newline();
350 swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
351 x8( "global ", &(gdb[G0]) );
352 x8( " in ", &(gdb[I0]) );
353 x8( " local ", &(gdb[L0]) );
354 x8( " out ", &(gdb[O0]) );
355 swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
356 swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
357 swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
358 #endif
359 }
360
361 }
362
363 // ---------------------------------------------------------------------------
364
365 void
366 cyg_hal_sparc_set_gdb_regs( HAL_SavedRegisters *eCos_regset,
367 void *gdb_regset )
368 {
369 target_register_t *gdb = (target_register_t *)gdb_regset;
370 int reg;
371 cyg_uint32 scratch = 0;
372 cyg_uint32 *sptrap;
373 HAL_SavedWindow *trapli, *ctxli;
374
375 // Guess where the eCos register set really is:
376 if ( 0 == eCos_regset->g[0] ||
377 0xc0 == (0xe0 & eCos_regset->g[0]) ) {
378 // Then it's an interrupt stack saved state:
379 // (either minimal, or a saved PSR with traps disabled)
380 // The saved register set is pretty minimal, so we have to grub
381 // around in the stack to find out some truth...
382 sptrap = (cyg_uint32 *)eCos_regset; // point to the IL save area for
383 sptrap -= 24; // the trap handler, for PC, NPC
384 trapli = (HAL_SavedWindow *)sptrap; // Get at those regs
385
386 ctxli = (HAL_SavedWindow *)(trapli->i[6]); // (the frame pointer)
387 // and get at the interruptee's regs
388
389 scratch = eCos_regset->g[0];
390
391 // Put back interruptee's registers all over the stack:
392 for ( reg = 0; reg < 8 ; reg++ ) {
393 eCos_regset->g[reg] = gdb[ G0 + reg ] ;
394 trapli->i[reg] = gdb[ O0 + reg ] ;
395 ctxli->l[reg] = gdb[ L0 + reg ] ;
396 ctxli->i[reg] = gdb[ I0 + reg ] ;
397 }
398
399 // Put back the eCos G0 which is always 0 (but abused in eCos_regset)
400 eCos_regset->g[0] = scratch;
401
402 // In the save context _of the trap handler_ registers are as follows:
403 // %l0 = psr (with this CWP/window-level in it)
404 // %l1 = pc
405 // %l2 = npc
406 // %l3 = vector number (1-15 for interrupts)
407 // %l4 = Y register preserved
408 trapli->l[4] = gdb[ Y ];
409
410 // I am *not* interfering with the saved PSR, nor the TBR nor WIM.
411
412 // put back return PC and NPC
413 trapli->l[1] = gdb[ PC ] ;
414 trapli->l[2] = gdb[ NPC ];
415
416 #ifdef THREAD_DEBUG_SERIAL_VERBOSE
417 newline();
418 swrites( "-----------------------------------------------------" ); newline();
419 swrites( "-------------- INTERRUPT STACK SET ------------------" ); newline();
420 swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
421 swrites( " trapli " ); swritex( trapli ); newline();
422 swrites( " ctxli " ); swritex( ctxli ); newline();
423 x8( "global ", &(gdb[G0]) );
424 x8( " in ", &(gdb[I0]) );
425 x8( " local ", &(gdb[L0]) );
426 x8( " out ", &(gdb[O0]) );
427 swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
428 swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
429 swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
430 #endif
431
432 }
433 else {
434 // It's a synchronous context switch that led to this object.
435 // Pick up interruptee's registers from the saved context:
436
437 scratch = eCos_regset->g[0];
438
439 for ( reg = 0; reg < 8 ; reg++ ) {
440 eCos_regset->g[reg] = gdb[ G0 + reg ];
441 eCos_regset->o[reg] = gdb[ O0 + reg ];
442 eCos_regset->li.l[reg] = gdb[ L0 + reg ];
443 eCos_regset->li.i[reg] = gdb[ I0 + reg ];
444 }
445
446 // Put back the eCos G0 which is always 0 (but abused in eCos_regset)
447 eCos_regset->g[0] = scratch;
448
449 // I am *not* interfering with the saved PSR, nor the TBR nor WIM.
450
451 // The PC is in o7, altering it via GDB's PC is not on.
452 // Setting the NPC in a voluntary context is meaningless.
453
454 #ifdef THREAD_DEBUG_SERIAL_VERBOSE
455 newline();
456 swrites( "-----------------------------------------------------" ); newline();
457 swrites( "-------------- SYNCHRONOUS SWITCH SET ---------------" ); newline();
458 swrites( "eCos regset at " ); swritex( eCos_regset ); newline();
459 x8( "global ", &(gdb[G0]) );
460 x8( " in ", &(gdb[I0]) );
461 x8( " local ", &(gdb[L0]) );
462 x8( " out ", &(gdb[O0]) );
463 swrites( "gdb PC = " ); swritex( gdb[ PC ] ); newline();
464 swrites( "gdb NPC = " ); swritex( gdb[ NPC ] ); newline();
465 swrites( "gdb PSR = " ); swritex( gdb[ PSR ] ); newline();
466 #endif
467 }
468
469 }
470
471 /*---------------------------------------------------------------------------*/
472 // EOF icontext.c