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