]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/i386/arch/v2_0/include/hal_arch.h
Initial revision
[karo-tx-redboot.git] / packages / hal / i386 / arch / v2_0 / include / hal_arch.h
1 #ifndef CYGONCE_HAL_HAL_ARCH_H
2 #define CYGONCE_HAL_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):   proven
47 // Contributors:proven, pjo, nickg
48 // Date:        1998-10-05
49 // Purpose:     Define architecture abstractions
50 // Usage:       #include <cyg/hal/hal_arch.h>
51 //
52 //####DESCRIPTIONEND####
53 //
54 //=============================================================================
55
56 #include <pkgconf/hal.h>
57 #include <cyg/infra/cyg_type.h>
58
59 #include <cyg/hal/var_arch.h>
60
61 //-----------------------------------------------------------------------------
62 // Processor saved states. This structure is also defined in i386.inc for
63 // assembly code. Do not change this without changing that (or vice versa).
64
65 #ifdef CYGHWR_HAL_I386_FPU
66
67 typedef struct
68 {
69     cyg_uint32  fpstate_valid;
70     cyg_uint32  fpstate[108/sizeof(cyg_uint32)];
71 #ifdef CYGHWR_HAL_I386_PENTIUM_SSE
72     cyg_uint32  xmm0[4];
73     cyg_uint32  xmm1[4];
74     cyg_uint32  xmm2[4];
75     cyg_uint32  xmm3[4];
76     cyg_uint32  xmm4[4];
77     cyg_uint32  xmm5[4];
78     cyg_uint32  xmm6[4];
79     cyg_uint32  xmm7[4];
80     cyg_uint32  mxcsr;
81 #endif
82 } HAL_FPU_Context;
83
84 #endif
85
86 typedef struct 
87 {
88 #ifdef CYGHWR_HAL_I386_FPU
89 #ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY
90     HAL_FPU_Context     *fpucontext;
91 #else
92     HAL_FPU_Context     fpucontext;    
93 #endif    
94 #endif    
95     cyg_uint32  edi;
96     cyg_uint32  esi;
97     cyg_uint32  ebp;
98     cyg_uint32  esp;
99     cyg_uint32  ebx;
100     cyg_uint32  edx;
101     cyg_uint32  ecx;
102     cyg_uint32  eax;    
103     cyg_uint32  vector; // if saved on interrupt contains intr vector
104     cyg_uint32  pc;
105     cyg_uint32  cs;
106     cyg_uint32  eflags;
107 } HAL_SavedRegisters;
108
109
110 //-----------------------------------------------------------------------------
111 // Exception handling function.
112 // This function is defined by the kernel according to this prototype. It is
113 // invoked from the HAL to deal with any CPU exceptions that the HAL does
114 // not want to deal with itself. It usually invokes the kernel's exception
115 // delivery mechanism.
116 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data );
117
118 //-----------------------------------------------------------------------------
119 // Bit manipulation routines
120
121 #define HAL_LSBIT_INDEX(index, mask)            \
122 CYG_MACRO_START                                 \
123     asm volatile( "bsfl %1,%0\n"                \
124                   : "=r" (index)                \
125                   : "r" (mask)                  \
126                 );                              \
127 CYG_MACRO_END
128
129 #define HAL_MSBIT_INDEX(index, mask)            \
130 CYG_MACRO_START                                 \
131     asm volatile( "bsrl %1,%0\n"                \
132                   : "=r" (index)                \
133                   : "r" (mask)                  \
134                 );                              \
135 CYG_MACRO_END
136
137 //-----------------------------------------------------------------------------
138 // Context Initialization
139 // Initialize the context of a thread.
140 // Arguments:
141 // _sp_ name of variable containing current sp, will be written with new sp
142 // _thread_ thread object address, passed as argument to entry point
143 // _entry_ entry point address.
144 // _id_ bit pattern used in initializing registers, for debugging.
145
146 #ifndef CYG_HAL_DEFAULT_CS
147 #define CYG_HAL_DEFAULT_CS 0x0008
148 #endif
149
150 #ifdef CYGHWR_HAL_I386_FPU
151 # ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY
152 # define HAL_THREAD_INIT_FPU_CONTEXT_SPACE( __sp, __fpspace )   \
153          __sp -= sizeof(HAL_FPU_Context);                       \
154          __fpspace = __sp;
155 # define HAL_THREAD_INIT_FPU_CONTEXT( __regs, __fpspace )                               \
156 CYG_MACRO_START                                                                         \
157     cyg_ucount8 __i;                                                                    \
158     HAL_FPU_Context *__fpspace_ = (HAL_FPU_Context *)(__fpspace);                       \
159     (__regs)->fpucontext = __fpspace_;                                                  \
160     __fpspace_->fpstate_valid = 0;                                                      \
161     for( __i = 0; __i < (sizeof(__fpspace_->fpstate)/sizeof(cyg_uint32)); __i++ )       \
162         __fpspace_->fpstate[__i] = 0;                                                   \
163 CYG_MACRO_END
164 # else
165 # define HAL_THREAD_INIT_FPU_CONTEXT_SPACE( __sp, __fpspace )                   \
166          (__fpspace) = (__fpspace);
167 # define HAL_THREAD_INIT_FPU_CONTEXT( __regs, __fpspace )                               \
168 CYG_MACRO_START                                                                         \
169     cyg_ucount8 __i;                                                                    \
170     HAL_FPU_Context *__fpspace_ = &((__regs)->fpucontext);                              \
171     __fpspace_->fpstate_valid = 0;                                                      \
172     for( __i = 0; __i < (sizeof(__fpspace_->fpstate)/sizeof(cyg_uint32)); __i++ )       \
173         __fpspace_->fpstate[__i] = 0;                                                   \
174 CYG_MACRO_END
175 # endif
176 #else
177 # define HAL_THREAD_INIT_FPU_CONTEXT_SPACE( __sp, __fpspace )                   \
178          (__fpspace) = (__fpspace);
179 # define HAL_THREAD_INIT_FPU_CONTEXT( __regs, __fpspace )
180 #endif
181
182
183 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ )     \
184 CYG_MACRO_START                                                         \
185     register CYG_WORD* _sp_ = ((CYG_WORD*)((_sparg_) &~15));            \
186     register CYG_WORD *_fpspace_ = NULL;                                \
187     register HAL_SavedRegisters *_regs_;                                \
188                                                                         \
189     HAL_THREAD_INIT_FPU_CONTEXT_SPACE( _sp_, _fpspace_ );               \
190     *(--_sp_) = (CYG_WORD)(0);                                          \
191     *(--_sp_) = (CYG_WORD)(0);                                          \
192     *(--_sp_) = (CYG_WORD)(_thread_);                                   \
193     *(--_sp_) = (CYG_WORD)(0);                                          \
194                                                                         \
195     _regs_ = (HAL_SavedRegisters *)                                     \
196                ((unsigned long)_sp_ - sizeof(HAL_SavedRegisters));      \
197     HAL_THREAD_INIT_FPU_CONTEXT( _regs_, _fpspace_ );                   \
198     _regs_->eflags = (CYG_WORD)(0x00000200);                            \
199     _regs_->cs     = (CYG_WORD)(CYG_HAL_DEFAULT_CS);                    \
200     _regs_->pc     = (CYG_WORD)(_entry_);                               \
201     _regs_->vector = (CYG_WORD)(_id_);                                  \
202     _regs_->esp    = (CYG_WORD) _sp_-4;                                 \
203     _regs_->ebp    = (CYG_WORD)(_id_);                                  \
204     _regs_->esi    = (CYG_WORD)(_id_);                                  \
205     _regs_->edi    = (CYG_WORD)(_id_);                                  \
206     _regs_->eax    = (CYG_WORD)(_id_);                                  \
207     _regs_->ebx    = (CYG_WORD)(_id_);                                  \
208     _regs_->ecx    = (CYG_WORD)(_id_);                                  \
209     _regs_->edx    = (CYG_WORD)(_id_);                                  \
210     (_sparg_)      = (CYG_ADDRESS) _regs_;                              \
211 CYG_MACRO_END
212
213 //-----------------------------------------------------------------------------
214 // Context switch macros.
215 // The arguments are pointers to locations where the stack pointer
216 // of the current thread is to be stored, and from where the sp of the
217 // next thread is to be fetched.
218
219 externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from );
220 externC void hal_thread_load_context( CYG_ADDRESS to )
221     __attribute__ ((noreturn));
222
223 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_)                    \
224         hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_);
225
226 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_)                               \
227         hal_thread_load_context( (CYG_ADDRESS)_tspptr_ );
228
229 //-----------------------------------------------------------------------------
230 // Execution reorder barrier.
231 // When optimizing the compiler can reorder code. In multithreaded systems
232 // where the order of actions is vital, this can sometimes cause problems.
233 // This macro may be inserted into places where reordering should not happen.
234
235 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" )
236
237 //-----------------------------------------------------------------------------
238 // Breakpoint support
239 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen 
240 // if executed.
241 // HAL_BREAKINST is the value of the breakpoint instruction and 
242 // HAL_BREAKINST_SIZE is its size in bytes.
243
244 #define HAL_BREAKPOINT(_label_)                 \
245 CYG_MACRO_START                                 \
246     asm volatile (" .globl  " #_label_ ";"      \
247                   #_label_":"                   \
248                   "int $3"                      \
249         );                                      \
250 CYG_MACRO_END
251
252 #define HAL_BREAKINST                    0xCC
253 #define HAL_BREAKINST_SIZE               1
254
255 //-----------------------------------------------------------------------------
256 // Thread register state manipulation for GDB support.
257
258 // Translate a stack pointer as saved by the thread context macros above into
259 // a pointer to a HAL_SavedRegisters structure.
260 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ )  \
261         (_regs_) = (HAL_SavedRegisters *)(_sp_)
262
263 // Copy a set of registers from a HAL_SavedRegisters structure into a
264 // GDB ordered array.    
265
266 externC void hal_get_gdb_registers(CYG_ADDRWORD *, HAL_SavedRegisters *);
267 externC void hal_set_gdb_registers(HAL_SavedRegisters *, CYG_ADDRWORD *);
268
269 #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \
270                 hal_get_gdb_registers((CYG_ADDRWORD *)(_aregval_), (_regs_))
271
272 // Copy a GDB ordered array into a HAL_SavedRegisters structure.
273 #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \
274                 hal_set_gdb_registers((_regs_), (CYG_ADDRWORD *)(_aregval_))
275
276 //-----------------------------------------------------------------------------
277 // HAL setjmp
278
279 #define CYGARC_JMP_BUF_SP        0
280 #define CYGARC_JMP_BUF_EBP       1
281 #define CYGARC_JMP_BUF_EBX       2
282 #define CYGARC_JMP_BUF_ESI       3
283 #define CYGARC_JMP_BUF_EDI       4
284 #define CYGARC_JMP_BUF_PC        5
285
286 #define CYGARC_JMP_BUF_SIZE      6
287
288 typedef cyg_uint32 hal_jmp_buf[CYGARC_JMP_BUF_SIZE];
289
290 externC int hal_setjmp(hal_jmp_buf env);
291 externC void hal_longjmp(hal_jmp_buf env, int val);
292
293 //-----------------------------------------------------------------------------
294 // Idle thread code.
295 // This macro is called in the idle thread loop, and gives the HAL the
296 // chance to insert code. Typical idle thread behaviour might be to halt the
297 // processor.
298
299 externC void hal_idle_thread_action(cyg_uint32 loop_count);
300
301 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_)
302
303 //-----------------------------------------------------------------------------
304 // Minimal and sensible stack sizes: the intention is that applications
305 // will use these to provide a stack size in the first instance prior to
306 // proper analysis.  Idle thread stack should be this big.
307
308 //    THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES.
309 //           THEY ARE HOWEVER ENOUGH TO START PROGRAMMING.
310 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES!
311  
312 // This is not a config option because it should not be adjusted except
313 // under "enough rope" sort of disclaimers.
314  
315 // Stack frame overhead per call. Four arguments, 3 local registers
316 // (edi, esi, ebx), four local variables and return address.
317 #define CYGNUM_HAL_STACK_FRAME_SIZE (12 * 4)
318
319 // Stack needed for a context switch ( sizeof(HAL_SavedRegisters) ).
320 #ifdef CYGHWR_HAL_I386_FPU
321 # define CYGNUM_HAL_STACK_CONTEXT_SIZE ((4 * 12) + 108)
322 #else
323 # define CYGNUM_HAL_STACK_CONTEXT_SIZE (4 * 12)
324 #endif
325
326 // Interrupt + call to ISR, interrupt_end() and the DSR
327 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \
328     ((4*CYGNUM_HAL_STACK_CONTEXT_SIZE) + 4 * CYGNUM_HAL_STACK_FRAME_SIZE)
329
330 // We define a minimum stack size as the minimum any thread could ever
331 // legitimately get away with. We can throw asserts if users ask for less
332 // than this. Allow enough for three interrupt sources - clock, serial and
333 // one other
334
335 #if defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK)
336
337 // An interrupt stack which is large enough for all possible interrupt
338 // conditions (and only used for that purpose) exists.  "User" stacks
339 // can therefore be much smaller
340
341 # define CYGNUM_HAL_STACK_SIZE_MINIMUM \
342          (2*CYGNUM_HAL_STACK_FRAME_SIZE + 2*CYGNUM_HAL_STACK_INTERRUPT_SIZE)
343
344 #else
345
346 // No separate interrupt stack exists.  Make sure all threads contain
347 // a stack sufficiently large
348
349 # define CYGNUM_HAL_STACK_SIZE_MINIMUM                  \
350         (((2+3+10)*CYGNUM_HAL_STACK_INTERRUPT_SIZE) +   \
351          (2*CYGNUM_HAL_STACK_FRAME_SIZE))
352
353 #endif
354
355 // Now make a reasonable choice for a typical thread size. Pluck figures
356 // from thin air and say 15 call frames with an average of 16 words of
357 // automatic variables per call frame
358
359 #define CYGNUM_HAL_STACK_SIZE_TYPICAL                \
360         (CYGNUM_HAL_STACK_SIZE_MINIMUM +             \
361          15 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4)))
362
363 //--------------------------------------------------------------------------
364 // Memory access macros
365
366 #define CYGARC_CACHED_ADDRESS(x)                       (x)
367 #define CYGARC_UNCACHED_ADDRESS(x)                     (x)
368 #define CYGARC_PHYSICAL_ADDRESS(x)                     (x)
369 #define CYGARC_VIRTUAL_ADDRESS(x)                      (x)
370
371 //--------------------------------------------------------------------------
372 // Region size finder
373
374 #if CYGINT_HAL_I386_MEM_REAL_REGION_TOP
375
376 externC cyg_uint8 *hal_i386_mem_real_region_top( cyg_uint8 *_regionend_ );
377                                                 
378 # define HAL_MEM_REAL_REGION_TOP( _regionend_ ) \
379     hal_i386_mem_real_region_top( _regionend_ )
380 #endif
381
382 //--------------------------------------------------------------------------
383 // Macros for switching context between two eCos instances (jump from
384 // code in ROM to code in RAM or vice versa).
385
386 #define CYGARC_HAL_SAVE_GP()
387 #define CYGARC_HAL_RESTORE_GP()
388
389 //--------------------------------------------------------------------------
390 #endif // CYGONCE_HAL_HAL_ARCH_H
391 // End of hal_arch.h