1 #ifndef CYGONCE_HAL_HAL_ARCH_H
2 #define CYGONCE_HAL_HAL_ARCH_H
4 //=============================================================================
8 // Architecture specific abstractions
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.
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.
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
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.
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.
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.
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####
47 // Contributors:proven, pjo, nickg
49 // Purpose: Define architecture abstractions
50 // Usage: #include <cyg/hal/hal_arch.h>
52 //####DESCRIPTIONEND####
54 //=============================================================================
56 #include <pkgconf/hal.h>
57 #include <cyg/infra/cyg_type.h>
59 #include <cyg/hal/var_arch.h>
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).
65 #ifdef CYGHWR_HAL_I386_FPU
69 cyg_uint32 fpstate_valid;
70 cyg_uint32 fpstate[108/sizeof(cyg_uint32)];
71 #ifdef CYGHWR_HAL_I386_PENTIUM_SSE
88 #ifdef CYGHWR_HAL_I386_FPU
89 #ifdef CYGHWR_HAL_I386_FPU_SWITCH_LAZY
90 HAL_FPU_Context *fpucontext;
92 HAL_FPU_Context fpucontext;
103 cyg_uint32 vector; // if saved on interrupt contains intr vector
107 } HAL_SavedRegisters;
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 );
118 //-----------------------------------------------------------------------------
119 // Bit manipulation routines
121 #define HAL_LSBIT_INDEX(index, mask) \
123 asm volatile( "bsfl %1,%0\n" \
129 #define HAL_MSBIT_INDEX(index, mask) \
131 asm volatile( "bsrl %1,%0\n" \
137 //-----------------------------------------------------------------------------
138 // Context Initialization
139 // Initialize the context of a thread.
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.
146 #ifndef CYG_HAL_DEFAULT_CS
147 #define CYG_HAL_DEFAULT_CS 0x0008
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); \
155 # define HAL_THREAD_INIT_FPU_CONTEXT( __regs, __fpspace ) \
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; \
165 # define HAL_THREAD_INIT_FPU_CONTEXT_SPACE( __sp, __fpspace ) \
166 (__fpspace) = (__fpspace);
167 # define HAL_THREAD_INIT_FPU_CONTEXT( __regs, __fpspace ) \
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; \
177 # define HAL_THREAD_INIT_FPU_CONTEXT_SPACE( __sp, __fpspace ) \
178 (__fpspace) = (__fpspace);
179 # define HAL_THREAD_INIT_FPU_CONTEXT( __regs, __fpspace )
183 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \
185 register CYG_WORD* _sp_ = ((CYG_WORD*)((_sparg_) &~15)); \
186 register CYG_WORD *_fpspace_ = NULL; \
187 register HAL_SavedRegisters *_regs_; \
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); \
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_; \
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.
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));
223 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \
224 hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_);
226 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \
227 hal_thread_load_context( (CYG_ADDRESS)_tspptr_ );
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.
235 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" )
237 //-----------------------------------------------------------------------------
238 // Breakpoint support
239 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen
241 // HAL_BREAKINST is the value of the breakpoint instruction and
242 // HAL_BREAKINST_SIZE is its size in bytes.
244 #define HAL_BREAKPOINT(_label_) \
246 asm volatile (" .globl " #_label_ ";" \
252 #define HAL_BREAKINST 0xCC
253 #define HAL_BREAKINST_SIZE 1
255 //-----------------------------------------------------------------------------
256 // Thread register state manipulation for GDB support.
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_)
263 // Copy a set of registers from a HAL_SavedRegisters structure into a
264 // GDB ordered array.
266 externC void hal_get_gdb_registers(CYG_ADDRWORD *, HAL_SavedRegisters *);
267 externC void hal_set_gdb_registers(HAL_SavedRegisters *, CYG_ADDRWORD *);
269 #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \
270 hal_get_gdb_registers((CYG_ADDRWORD *)(_aregval_), (_regs_))
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_))
276 //-----------------------------------------------------------------------------
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
286 #define CYGARC_JMP_BUF_SIZE 6
288 typedef cyg_uint32 hal_jmp_buf[CYGARC_JMP_BUF_SIZE];
290 externC int hal_setjmp(hal_jmp_buf env);
291 externC void hal_longjmp(hal_jmp_buf env, int val);
293 //-----------------------------------------------------------------------------
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
299 externC void hal_idle_thread_action(cyg_uint32 loop_count);
301 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_)
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.
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!
312 // This is not a config option because it should not be adjusted except
313 // under "enough rope" sort of disclaimers.
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)
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)
323 # define CYGNUM_HAL_STACK_CONTEXT_SIZE (4 * 12)
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)
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
335 #if defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK)
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
341 # define CYGNUM_HAL_STACK_SIZE_MINIMUM \
342 (2*CYGNUM_HAL_STACK_FRAME_SIZE + 2*CYGNUM_HAL_STACK_INTERRUPT_SIZE)
346 // No separate interrupt stack exists. Make sure all threads contain
347 // a stack sufficiently large
349 # define CYGNUM_HAL_STACK_SIZE_MINIMUM \
350 (((2+3+10)*CYGNUM_HAL_STACK_INTERRUPT_SIZE) + \
351 (2*CYGNUM_HAL_STACK_FRAME_SIZE))
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
359 #define CYGNUM_HAL_STACK_SIZE_TYPICAL \
360 (CYGNUM_HAL_STACK_SIZE_MINIMUM + \
361 15 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4)))
363 //--------------------------------------------------------------------------
364 // Memory access macros
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)
371 //--------------------------------------------------------------------------
372 // Region size finder
374 #if CYGINT_HAL_I386_MEM_REAL_REGION_TOP
376 externC cyg_uint8 *hal_i386_mem_real_region_top( cyg_uint8 *_regionend_ );
378 # define HAL_MEM_REAL_REGION_TOP( _regionend_ ) \
379 hal_i386_mem_real_region_top( _regionend_ )
382 //--------------------------------------------------------------------------
383 // Macros for switching context between two eCos instances (jump from
384 // code in ROM to code in RAM or vice versa).
386 #define CYGARC_HAL_SAVE_GP()
387 #define CYGARC_HAL_RESTORE_GP()
389 //--------------------------------------------------------------------------
390 #endif // CYGONCE_HAL_HAL_ARCH_H