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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [sparclite/] [arch/] [v2_0/] [src/] [icontext.c] - Blame information for rev 27

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

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

powered by: WebSVN 2.1.0

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