OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [sparc/] [arch/] [current/] [src/] [icontext.c] - Blame information for rev 851

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.