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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [powerpc/] [arch/] [v2_0/] [include/] [hal_arch.h] - Blame information for rev 27

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

Line No. Rev Author Line
1 27 unneback
#ifndef CYGONCE_HAL_ARCH_H
2
#define CYGONCE_HAL_ARCH_H
3
 
4
//=============================================================================
5
//
6
//      hal_arch.h
7
//
8
//      Architecture specific abstractions
9
//
10
//=============================================================================
11
//####ECOSGPLCOPYRIGHTBEGIN####
12
// -------------------------------------------
13
// This file is part of eCos, the Embedded Configurable Operating System.
14
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
15
//
16
// eCos is free software; you can redistribute it and/or modify it under
17
// the terms of the GNU General Public License as published by the Free
18
// Software Foundation; either version 2 or (at your option) any later version.
19
//
20
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
22
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23
// for more details.
24
//
25
// You should have received a copy of the GNU General Public License along
26
// with eCos; if not, write to the Free Software Foundation, Inc.,
27
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
28
//
29
// As a special exception, if other files instantiate templates or use macros
30
// or inline functions from this file, or you compile this file and link it
31
// with other works to produce a work based on this file, this file does not
32
// by itself cause the resulting work to be covered by the GNU General Public
33
// License. However the source code for this file must still be made available
34
// in accordance with section (3) of the GNU General Public License.
35
//
36
// This exception does not invalidate any other reasons why a work based on
37
// this file might be covered by the GNU General Public License.
38
//
39
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
40
// at http://sources.redhat.com/ecos/ecos-license/
41
// -------------------------------------------
42
//####ECOSGPLCOPYRIGHTEND####
43
//=============================================================================
44
//#####DESCRIPTIONBEGIN####
45
//
46
// Author(s):   nickg
47
// Contributors:  nickg
48
// Date:        1997-09-08
49
// Purpose:     Define architecture abstractions
50
// Usage:       #include <cyg/hal/hal_arch.h>
51
 
52
//              
53
//####DESCRIPTIONEND####
54
//
55
//=============================================================================
56
 
57
#include <pkgconf/hal.h>
58
#include <cyg/infra/cyg_type.h>
59
 
60
#include <cyg/hal/ppc_regs.h>           // CYGARC_REG_MSR_EE
61
 
62
//-----------------------------------------------------------------------------
63
// Processor saved states:
64
 
65
typedef struct
66
{
67
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
68
    cyg_uint32   wall_head;
69
#endif
70
 
71
    // These are common to all saved states
72
    cyg_uint32   d[32];                 // Data regs
73
#ifdef CYGHWR_HAL_POWERPC_FPU
74
    double       f[32];                 // Floating point registers
75
#endif   
76
    cyg_uint32   cr;                    // Condition Reg
77
    cyg_uint32   xer;                   // XER
78
    cyg_uint32   lr;                    // Link Reg
79
    cyg_uint32   ctr;                   // Count Reg
80
 
81
    // These are saved for exceptions and interrupts, but may also
82
    // be saved in a context switch if thread-aware debugging is enabled.
83
    cyg_uint32   msr;                   // Machine State Reg
84
    cyg_uint32   pc;                    // Program Counter
85
 
86
    // This marks the limit of state saved during a context switch and
87
    // is used to calculate necessary stack allocation for context switches.
88
    // It would probably be better to have a union instead...
89
    cyg_uint32   context_size[0];
90
 
91
    // These are only saved for exceptions and interrupts
92
    cyg_uint32   vector;                // Vector number
93
 
94
#ifdef CYGDBG_HAL_POWERPC_FRAME_WALLS
95
    cyg_uint32   wall_tail;
96
#endif
97
} HAL_SavedRegisters;
98
 
99
//-----------------------------------------------------------------------------
100
// Exception handling function.
101
// This function is defined by the kernel according to this prototype. It is
102
// invoked from the HAL to deal with any CPU exceptions that the HAL does
103
// not want to deal with itself. It usually invokes the kernel's exception
104
// delivery mechanism.
105
 
106
externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data );
107
 
108
//-----------------------------------------------------------------------------
109
// Bit manipulation macros
110
 
111
#define HAL_LSBIT_INDEX(index, mask)    \
112
    asm ( "neg    11,%1;"               \
113
          "and    11,11,%1;"            \
114
          "cntlzw %0,11;"               \
115
          "subfic %0,%0,31;"            \
116
          : "=r" (index)                \
117
          : "r" (mask)                  \
118
          : "r11"                       \
119
        );
120
 
121
#define HAL_MSBIT_INDEX(index, mask)            \
122
    asm ( "cntlzw %0,%1\n"                      \
123
          "subfic %0,%0,31;"                    \
124
          : "=r" (index)                        \
125
          : "r" (mask)                          \
126
        );
127
 
128
//-----------------------------------------------------------------------------
129
// eABI
130
#define CYGARC_PPC_STACK_FRAME_SIZE     56      // size of a stack frame
131
 
132
//-----------------------------------------------------------------------------
133
// Context Initialization
134
// Initialize the context of a thread.
135
// Arguments:
136
// _sparg_ name of variable containing current sp, will be written with new sp
137
// _thread_ thread object address, passed as argument to entry point
138
// _entry_ entry point address.
139
// _id_ bit pattern used in initializing registers, for debugging.
140
 
141
#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ )           \
142
    CYG_MACRO_START                                                           \
143
    register CYG_WORD _sp_ = (((CYG_WORD)_sparg_) &~15)                       \
144
                                 - CYGARC_PPC_STACK_FRAME_SIZE;               \
145
    register HAL_SavedRegisters *_regs_;                                      \
146
    int _i_;                                                                  \
147
    _regs_ = (HAL_SavedRegisters *)((_sp_) - sizeof(HAL_SavedRegisters));     \
148
    for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_;            \
149
    (_regs_)->d[01] = (CYG_WORD)(_sp_);        /* SP = top of stack      */   \
150
    (_regs_)->d[03] = (CYG_WORD)(_thread_);    /* R3 = arg1 = thread ptr */   \
151
    (_regs_)->cr = 0;                          /* CR = 0                 */   \
152
    (_regs_)->xer = 0;                         /* XER = 0                */   \
153
    (_regs_)->lr = (CYG_WORD)(_entry_);        /* LR = entry point       */   \
154
    (_regs_)->pc = (CYG_WORD)(_entry_);        /* set PC for thread dbg  */   \
155
    (_regs_)->ctr = 0;                         /* CTR = 0                */   \
156
    (_regs_)->msr = CYGARC_REG_MSR_EE;         /* MSR = enable irqs      */   \
157
    _sparg_ = (CYG_ADDRESS)_regs_;                                            \
158
    CYG_MACRO_END
159
 
160
//-----------------------------------------------------------------------------
161
// Context switch macros.
162
// The arguments are pointers to locations where the stack pointer
163
// of the current thread is to be stored, and from where the sp of the
164
// next thread is to be fetched.
165
 
166
externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from );
167
externC void hal_thread_load_context( CYG_ADDRESS to )
168
    __attribute__ ((noreturn));
169
 
170
#define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_)                    \
171
        hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_);
172
 
173
#define HAL_THREAD_LOAD_CONTEXT(_tspptr_)                               \
174
        hal_thread_load_context( (CYG_ADDRESS)_tspptr_ );
175
 
176
//-----------------------------------------------------------------------------
177
// Execution reorder barrier.
178
// When optimizing the compiler can reorder code. In multithreaded systems
179
// where the order of actions is vital, this can sometimes cause problems.
180
// This macro may be inserted into places where reordering should not happen.
181
 
182
#define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" )
183
 
184
//-----------------------------------------------------------------------------
185
// Breakpoint support
186
// HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen
187
// if executed.
188
// HAL_BREAKINST is the value of the breakpoint instruction and 
189
// HAL_BREAKINST_SIZE is its size in bytes.
190
 
191
#define HAL_BREAKPOINT(_label_)                 \
192
asm volatile (" .globl  " #_label_ ";"          \
193
              #_label_":"                       \
194
              " trap"                           \
195
    );
196
 
197
#define HAL_BREAKINST           0x7d821008
198
 
199
#define HAL_BREAKINST_SIZE      4
200
 
201
//-----------------------------------------------------------------------------
202
// Thread register state manipulation for GDB support.
203
 
204
// Translate a stack pointer as saved by the thread context macros above into
205
// a pointer to a HAL_SavedRegisters structure.
206
#define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ )  \
207
        (_regs_) = (HAL_SavedRegisters *)(_sp_)
208
 
209
// Copy a set of registers from a HAL_SavedRegisters structure into a
210
// GDB ordered array.    
211
#define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ )              \
212
    CYG_MACRO_START                                             \
213
    CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_);       \
214
    int _i_;                                                    \
215
                                                                \
216
    for( _i_ = 0; _i_ < 32; _i_++ )                             \
217
        _regval_[_i_] = (_regs_)->d[_i_];                       \
218
                                                                \
219
    _regval_[64] = (_regs_)->pc;                                \
220
    _regval_[65] = (_regs_)->msr;                               \
221
    _regval_[66] = (_regs_)->cr;                                \
222
    _regval_[67] = (_regs_)->lr;                                \
223
    _regval_[68] = (_regs_)->ctr;                               \
224
    _regval_[69] = (_regs_)->xer;                               \
225
    CYG_MACRO_END
226
 
227
// Copy a GDB ordered array into a HAL_SavedRegisters structure.
228
#define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ )             \
229
    CYG_MACRO_START                                             \
230
    CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_);       \
231
    int _i_;                                                    \
232
                                                                \
233
    for( _i_ = 0; _i_ < 32; _i_++ )                             \
234
        (_regs_)->d[_i_] = _regval_[_i_];                       \
235
                                                                \
236
    (_regs_)->pc  = _regval_[64];                               \
237
    (_regs_)->msr = _regval_[65];                               \
238
    (_regs_)->cr  = _regval_[66];                               \
239
    (_regs_)->lr  = _regval_[67];                               \
240
    (_regs_)->ctr = _regval_[68];                               \
241
    (_regs_)->xer = _regval_[69];                               \
242
    CYG_MACRO_END
243
 
244
//-----------------------------------------------------------------------------
245
// HAL setjmp
246
 
247
typedef struct {
248
    cyg_uint32 sp;
249
    cyg_uint32 r2;
250
    cyg_uint32 r13;
251
    cyg_uint32 r14;
252
    cyg_uint32 r15;
253
    cyg_uint32 r16;
254
    cyg_uint32 r17;
255
    cyg_uint32 r18;
256
    cyg_uint32 r19;
257
    cyg_uint32 r20;
258
    cyg_uint32 r21;
259
    cyg_uint32 r22;
260
    cyg_uint32 r23;
261
    cyg_uint32 r24;
262
    cyg_uint32 r25;
263
    cyg_uint32 r26;
264
    cyg_uint32 r27;
265
    cyg_uint32 r28;
266
    cyg_uint32 r29;
267
    cyg_uint32 r30;
268
    cyg_uint32 r31;
269
#ifdef CYGHWR_HAL_POWERPC_FPU
270
    double     f14;
271
    double     f15;
272
    double     f16;
273
    double     f17;
274
    double     f18;
275
    double     f19;
276
    double     f20;
277
    double     f21;
278
    double     f22;
279
    double     f23;
280
    double     f24;
281
    double     f25;
282
    double     f26;
283
    double     f27;
284
    double     f28;
285
    double     f29;
286
    double     f30;
287
    double     f31;
288
#endif
289
    cyg_uint32 lr;
290
    cyg_uint32 cr;
291
} hal_jmp_buf_t;
292
 
293
#define CYGARC_JMP_BUF_SIZE      (sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32))
294
 
295
typedef cyg_uint32 hal_jmp_buf[ CYGARC_JMP_BUF_SIZE ];
296
 
297
externC int hal_setjmp(hal_jmp_buf env);
298
externC void hal_longjmp(hal_jmp_buf env, int val);
299
 
300
//-----------------------------------------------------------------------------
301
// Idle thread code.
302
// This macro is called in the idle thread loop, and gives the HAL the
303
// chance to insert code. Typical idle thread behaviour might be to halt the
304
// processor.
305
 
306
externC void hal_idle_thread_action(cyg_uint32 loop_count);
307
 
308
#define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_)
309
 
310
//-----------------------------------------------------------------------------
311
// Minimal and sensible stack sizes: the intention is that applications
312
// will use these to provide a stack size in the first instance prior to
313
// proper analysis.  Idle thread stack should be this big.
314
 
315
//    THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES.
316
//           THEY ARE HOWEVER ENOUGH TO START PROGRAMMING.
317
// YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES!
318
 
319
// This is not a config option because it should not be adjusted except
320
// under "enough rope" sort of disclaimers.
321
 
322
// Stack frame overhead per call. The PPC ABI defines regs 13..31 as callee
323
// saved. callee saved variables are irrelevant for us as they would contain
324
// automatic variables, so we only count the caller-saved regs here
325
// So that makes r0..r12 + cr, xer, lr, ctr:
326
#define CYGNUM_HAL_STACK_FRAME_SIZE (4 * 17)
327
 
328
// Stack needed for a context switch
329
#define CYGNUM_HAL_STACK_CONTEXT_SIZE \
330
    (38*4 /* offsetof(HAL_SavedRegisters, context_size) */)
331
 
332
// Interrupt + call to ISR, interrupt_end() and the DSR
333
#define CYGNUM_HAL_STACK_INTERRUPT_SIZE \
334
    ((43*4 /* sizeof(HAL_SavedRegisters) */) + 2 * CYGNUM_HAL_STACK_FRAME_SIZE)
335
 
336
// We have lots of registers so no particular amount is added in for
337
// typical local variable usage.
338
 
339
// We define a minimum stack size as the minimum any thread could ever
340
// legitimately get away with. We can throw asserts if users ask for less
341
// than this. Allow enough for three interrupt sources - clock, serial and
342
// one other
343
 
344
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK 
345
 
346
// An interrupt stack which is large enough for all possible interrupt
347
// conditions (and only used for that purpose) exists.  "User" stacks
348
// can therefore be much smaller
349
 
350
# define CYGNUM_HAL_STACK_SIZE_MINIMUM \
351
         (16*CYGNUM_HAL_STACK_FRAME_SIZE + 2*CYGNUM_HAL_STACK_INTERRUPT_SIZE)
352
 
353
#else
354
 
355
// No separate interrupt stack exists.  Make sure all threads contain
356
// a stack sufficiently large
357
# define CYGNUM_HAL_STACK_SIZE_MINIMUM                  \
358
        (((2+3)*CYGNUM_HAL_STACK_INTERRUPT_SIZE) +      \
359
         (16*CYGNUM_HAL_STACK_FRAME_SIZE))
360
#endif
361
 
362
// Now make a reasonable choice for a typical thread size. Pluck figures
363
// from thin air and say 30 call frames with an average of 16 words of
364
// automatic variables per call frame
365
#define CYGNUM_HAL_STACK_SIZE_TYPICAL                \
366
        (CYGNUM_HAL_STACK_SIZE_MINIMUM +             \
367
         30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4)))
368
 
369
//--------------------------------------------------------------------------
370
// Macros for switching context between two eCos instances (jump from
371
// code in ROM to code in RAM or vice versa).
372
 
373
// Should be defined like for MIPS, saving/restoring R2 - but is it
374
// actually used? I've never seen app code use R2. Something to investigate.
375
#define CYGARC_HAL_SAVE_GP()
376
#define CYGARC_HAL_RESTORE_GP()
377
 
378
//-----------------------------------------------------------------------------
379
#endif // CYGONCE_HAL_ARCH_H
380
// End of hal_arch.h

powered by: WebSVN 2.1.0

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