Mercurial > nand-ecoscentric
annotate packages/hal/powerpc/arch/current/include/hal_arch.h @ 6:d376b777e2ce ecos-sw-1999-05-14
Merge from eCos master repository on 1999-05-14-19:27:43-BST
| author | jlarmour |
|---|---|
| date | Fri, 14 May 1999 12:20:00 +0000 |
| parents | 443894e2e912 |
| children | c38311975d4f |
| rev | line source |
|---|---|
| 0 | 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 //####COPYRIGHTBEGIN#### | |
| 12 // | |
| 13 // ------------------------------------------- | |
| 14 // The contents of this file are subject to the Cygnus eCos Public License | |
| 15 // Version 1.0 (the "License"); you may not use this file except in | |
| 16 // compliance with the License. You may obtain a copy of the License at | |
| 17 // http://sourceware.cygnus.com/ecos | |
| 18 // | |
| 19 // Software distributed under the License is distributed on an "AS IS" | |
| 20 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 21 // License for the specific language governing rights and limitations under | |
| 22 // the License. | |
| 23 // | |
| 24 // The Original Code is eCos - Embedded Cygnus Operating System, released | |
| 25 // September 30, 1998. | |
| 26 // | |
| 27 // The Initial Developer of the Original Code is Cygnus. Portions created | |
| 2 | 28 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
| 0 | 29 // ------------------------------------------- |
| 30 // | |
| 31 //####COPYRIGHTEND#### | |
| 32 //============================================================================= | |
| 33 //#####DESCRIPTIONBEGIN#### | |
| 34 // | |
| 35 // Author(s): nickg | |
| 36 // Contributors: nickg | |
| 37 // Date: 1997-09-08 | |
| 38 // Purpose: Define architecture abstractions | |
| 39 // Usage: #include <cyg/hal/hal_arch.h> | |
| 40 | |
| 41 // | |
| 42 //####DESCRIPTIONEND#### | |
| 43 // | |
| 44 //============================================================================= | |
| 45 | |
| 2 | 46 #include <pkgconf/hal.h> |
| 0 | 47 #include <cyg/infra/cyg_type.h> |
| 48 | |
| 49 //----------------------------------------------------------------------------- | |
| 50 // Processor saved states: | |
| 51 // The layout of this structure is also defined in "ppc.inc", for assembly | |
| 52 // code. Do not change this without changing that (or vice versa). | |
| 53 | |
| 54 typedef struct | |
| 55 { | |
| 56 // These are common to all saved states | |
| 57 cyg_uint32 d[32]; // Data regs | |
| 58 cyg_uint32 cr; // Condition Reg | |
| 59 cyg_uint32 xer; // XER | |
| 60 cyg_uint32 lr; // Link Reg | |
| 61 cyg_uint32 ctr; // Count Reg | |
| 62 | |
| 2 | 63 // These are saved for exceptions and interrupts, but may also |
| 64 // be saved in a context switch if thread-aware debugging is enabled. | |
| 65 cyg_uint32 msr; // Machine State Reg | |
| 66 cyg_uint32 pc; // Program Counter | |
| 67 | |
| 0 | 68 // These are only saved for exceptions and interrupts |
| 69 cyg_uint32 vector; // Vector number | |
| 70 | |
| 71 // These are only saved for exceptions, and are not restored | |
| 72 // when continued. | |
| 73 cyg_uint32 hid0; // Hw Implementation Dependent | |
| 74 cyg_uint32 dar; // Data Address Reg | |
| 75 cyg_uint32 dsisr; // DSISR | |
| 76 cyg_uint32 pvr; // Processor Version | |
| 77 | |
| 2 | 78 // Eventually add BATs, SRs and FP registers too. |
| 0 | 79 } HAL_SavedRegisters; |
| 80 | |
| 81 //----------------------------------------------------------------------------- | |
| 82 // Exception handling function. | |
| 83 // This function is defined by the kernel according to this prototype. It is | |
| 84 // invoked from the HAL to deal with any CPU exceptions that the HAL does | |
| 85 // not want to deal with itself. It usually invokes the kernel's exception | |
| 86 // delivery mechanism. | |
| 87 | |
| 2 | 88 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); |
| 0 | 89 |
| 90 //----------------------------------------------------------------------------- | |
| 91 // Bit manipulation macros | |
| 92 | |
| 93 #define HAL_LSBIT_INDEX(index, mask) \ | |
| 94 asm ( "neg 11,%1;" \ | |
| 95 "and 11,11,%1;" \ | |
| 96 "cntlzw %0,11;" \ | |
| 97 "subfic %0,%0,31;" \ | |
| 98 : "=r" (index) \ | |
| 99 : "r" (mask) \ | |
| 100 : "r11" \ | |
| 101 ); | |
| 102 | |
| 103 #define HAL_MSBIT_INDEX(index, mask) \ | |
| 104 asm ( "cntlzw %1,%0" : "=r" (mask) : "r" (index) ); | |
| 105 | |
| 106 //----------------------------------------------------------------------------- | |
| 2 | 107 // eABI |
| 108 #define CYGARC_PPC_STACK_FRAME_SIZE 56 // size of a stack frame | |
| 109 | |
| 110 //----------------------------------------------------------------------------- | |
| 0 | 111 // Context Initialization |
| 112 // Initialize the context of a thread. | |
| 113 // Arguments: | |
| 2 | 114 // _sparg_ name of variable containing current sp, will be written with new sp |
| 0 | 115 // _thread_ thread object address, passed as argument to entry point |
| 116 // _entry_ entry point address. | |
| 117 // _id_ bit pattern used in initializing registers, for debugging. | |
| 118 | |
| 2 | 119 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \ |
| 120 CYG_MACRO_START \ | |
|
6
d376b777e2ce
Merge from eCos master repository on 1999-05-14-19:27:43-BST
jlarmour
parents:
2
diff
changeset
|
121 register CYG_WORD _sp_ = (((CYG_WORD)_sparg_) &~15) \ |
|
d376b777e2ce
Merge from eCos master repository on 1999-05-14-19:27:43-BST
jlarmour
parents:
2
diff
changeset
|
122 - CYGARC_PPC_STACK_FRAME_SIZE; \ |
| 2 | 123 register HAL_SavedRegisters *_regs_; \ |
| 124 int _i_; \ | |
| 125 _regs_ = (HAL_SavedRegisters *)((_sp_) - sizeof(HAL_SavedRegisters)); \ | |
| 126 for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_; \ | |
| 127 (_regs_)->d[01] = (CYG_WORD)(_sp_); /* SP = top of stack */ \ | |
| 128 (_regs_)->d[03] = (CYG_WORD)(_thread_); /* R3 = arg1 = thread ptr */ \ | |
| 129 (_regs_)->cr = 0; /* CR = 0 */ \ | |
| 130 (_regs_)->xer = 0; /* XER = 0 */ \ | |
| 131 (_regs_)->lr = (CYG_WORD)(_entry_); /* LR = entry point */ \ | |
| 132 (_regs_)->pc = (CYG_WORD)(_entry_); /* set PC for thread dbg */ \ | |
| 133 (_regs_)->ctr = 0; /* CTR = 0 */ \ | |
| 134 _sparg_ = (CYG_ADDRESS)_regs_; \ | |
| 0 | 135 CYG_MACRO_END |
| 136 | |
| 137 //----------------------------------------------------------------------------- | |
| 138 // Context switch macros. | |
| 139 // The arguments are pointers to locations where the stack pointer | |
| 140 // of the current thread is to be stored, and from where the sp of the | |
| 141 // next thread is to be fetched. | |
| 142 | |
| 143 externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from ); | |
| 144 externC void hal_thread_load_context( CYG_ADDRESS to ) | |
| 145 __attribute__ ((noreturn)); | |
| 146 | |
| 147 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \ | |
| 148 hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_); | |
| 149 | |
| 150 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \ | |
| 151 hal_thread_load_context( (CYG_ADDRESS)_tspptr_ ); | |
| 152 | |
| 153 //----------------------------------------------------------------------------- | |
| 154 // Execution reorder barrier. | |
| 155 // When optimizing the compiler can reorder code. In multithreaded systems | |
| 156 // where the order of actions is vital, this can sometimes cause problems. | |
| 157 // This macro may be inserted into places where reordering should not happen. | |
| 158 | |
| 159 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" ) | |
| 160 | |
| 161 //----------------------------------------------------------------------------- | |
| 162 // Breakpoint support | |
| 163 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen | |
| 164 // if executed. | |
| 165 // HAL_BREAKINST is the value of the breakpoint instruction and | |
| 166 // HAL_BREAKINST_SIZE is its size in bytes. | |
| 167 | |
| 168 #define HAL_BREAKPOINT(_label_) \ | |
| 169 asm volatile (" .globl " #_label_ ";" \ | |
| 170 #_label_":" \ | |
| 171 " trap" \ | |
| 172 ); | |
| 173 | |
| 174 #define HAL_BREAKINST 0x7d821008 | |
| 175 | |
| 176 #define HAL_BREAKINST_SIZE 4 | |
| 177 | |
| 178 //----------------------------------------------------------------------------- | |
| 179 // Thread register state manipulation for GDB support. | |
| 180 | |
| 181 // Translate a stack pointer as saved by the thread context macros above into | |
| 182 // a pointer to a HAL_SavedRegisters structure. | |
| 183 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \ | |
| 184 (_regs_) = (HAL_SavedRegisters *)(_sp_) | |
| 185 | |
| 186 // Copy a set of registers from a HAL_SavedRegisters structure into a | |
| 187 // GDB ordered array. | |
| 188 #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \ | |
| 189 CYG_MACRO_START \ | |
| 190 CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ | |
| 191 int _i_; \ | |
| 192 \ | |
| 193 for( _i_ = 0; _i_ < 32; _i_++ ) \ | |
| 194 _regval_[_i_] = (_regs_)->d[_i_]; \ | |
| 195 \ | |
| 196 _regval_[64] = (_regs_)->pc; \ | |
| 197 _regval_[65] = (_regs_)->msr; \ | |
| 198 _regval_[66] = (_regs_)->cr; \ | |
| 199 _regval_[67] = (_regs_)->lr; \ | |
| 200 _regval_[68] = (_regs_)->ctr; \ | |
| 201 _regval_[69] = (_regs_)->xer; \ | |
| 202 CYG_MACRO_END | |
| 203 | |
| 204 // Copy a GDB ordered array into a HAL_SavedRegisters structure. | |
| 205 #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \ | |
| 206 CYG_MACRO_START \ | |
| 207 CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ | |
| 208 int _i_; \ | |
| 209 \ | |
| 210 for( _i_ = 0; _i_ < 32; _i_++ ) \ | |
| 211 (_regs_)->d[_i_] = _regval_[_i_]; \ | |
| 212 \ | |
| 213 (_regs_)->pc = _regval_[64]; \ | |
| 214 (_regs_)->msr = _regval_[65]; \ | |
| 215 (_regs_)->cr = _regval_[66]; \ | |
| 216 (_regs_)->lr = _regval_[67]; \ | |
| 217 (_regs_)->ctr = _regval_[68]; \ | |
| 218 (_regs_)->xer = _regval_[69]; \ | |
| 219 CYG_MACRO_END | |
| 220 | |
| 221 //----------------------------------------------------------------------------- | |
| 222 // HAL setjmp | |
| 2 | 223 // Note: These definitions are repeated in context.S. If changes are required |
| 224 // remember to update both sets. | |
| 0 | 225 |
| 2 | 226 #define CYGARC_JMP_BUF_SP 0 |
| 227 #define CYGARC_JMP_BUF_R2 1 | |
| 228 #define CYGARC_JMP_BUF_R13 2 | |
| 229 #define CYGARC_JMP_BUF_R14 3 | |
| 230 #define CYGARC_JMP_BUF_R15 4 | |
| 231 #define CYGARC_JMP_BUF_R16 5 | |
| 232 #define CYGARC_JMP_BUF_R17 6 | |
| 233 #define CYGARC_JMP_BUF_R18 7 | |
| 234 #define CYGARC_JMP_BUF_R19 8 | |
| 235 #define CYGARC_JMP_BUF_R20 9 | |
| 236 #define CYGARC_JMP_BUF_R21 10 | |
| 237 #define CYGARC_JMP_BUF_R22 11 | |
| 238 #define CYGARC_JMP_BUF_R23 12 | |
| 239 #define CYGARC_JMP_BUF_R24 13 | |
| 240 #define CYGARC_JMP_BUF_R25 14 | |
| 241 #define CYGARC_JMP_BUF_R26 15 | |
| 242 #define CYGARC_JMP_BUF_R27 16 | |
| 243 #define CYGARC_JMP_BUF_R28 17 | |
| 244 #define CYGARC_JMP_BUF_R29 18 | |
| 245 #define CYGARC_JMP_BUF_R30 19 | |
| 246 #define CYGARC_JMP_BUF_R31 20 | |
| 247 #define CYGARC_JMP_BUF_LR 21 | |
| 248 #define CYGARC_JMP_BUF_CR 22 | |
| 0 | 249 |
| 2 | 250 #define CYGARC_JMP_BUF_SIZE 23 |
| 251 | |
| 252 typedef cyg_uint32 hal_jmp_buf[CYGARC_JMP_BUF_SIZE]; | |
| 0 | 253 |
| 254 externC int hal_setjmp(hal_jmp_buf env); | |
| 255 externC void hal_longjmp(hal_jmp_buf env, int val); | |
| 256 | |
| 257 //----------------------------------------------------------------------------- | |
| 258 // Idle thread code. | |
| 259 // This macro is called in the idle thread loop, and gives the HAL the | |
| 260 // chance to insert code. Typical idle thread behaviour might be to halt the | |
| 261 // processor. | |
| 262 | |
| 263 externC void hal_idle_thread_action(cyg_uint32 loop_count); | |
| 264 | |
| 265 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_) | |
| 266 | |
| 267 //----------------------------------------------------------------------------- | |
| 2 | 268 // Minimal and sensible stack sizes: the intention is that applications |
| 269 // will use these to provide a stack size in the first instance prior to | |
| 270 // proper analysis. Idle thread stack should be this big. | |
| 271 | |
| 272 // THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. | |
| 273 // THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. | |
| 274 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! | |
| 275 | |
| 276 // This is not a config option because it should not be adjusted except | |
| 277 // under "enough rope" sort of disclaimers. | |
| 278 | |
| 279 // Stack frame overhead per call. The PPC ABI defines regs 13..31 as callee | |
| 280 // saved. callee saved variables are irrelevant for us as they would contain | |
| 281 // automatic variables, so we only count the caller-saved regs here | |
| 282 // So that makes r0..r12 + cr, xer, lr, ctr: | |
| 283 #define CYGNUM_HAL_STACK_FRAME_SIZE (4 * 17) | |
| 284 | |
| 285 // Stack needed for a context switch (ppcref_context_size from ppc.inc) | |
| 286 #define CYGNUM_HAL_STACK_CONTEXT_SIZE (4 * 38) | |
| 287 | |
| 288 // Interrupt + call to ISR, interrupt_end() and the DSR | |
| 289 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \ | |
| 290 ((43*4 /* sizeof(HAL_SavedRegisters) */) + 2 * CYGNUM_HAL_STACK_FRAME_SIZE) | |
| 291 | |
| 292 // We have lots of registers so no particular amount is added in for | |
| 293 // typical local variable usage. | |
| 294 | |
| 295 // We define a minimum stack size as the minimum any thread could ever | |
| 296 // legitimately get away with. We can throw asserts if users ask for less | |
| 297 // than this. Allow enough for three interrupt sources - clock, serial and | |
| 298 // one other | |
| 299 | |
| 300 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK | |
| 301 | |
| 302 // An interrupt stack which is large enough for all possible interrupt | |
| 303 // conditions (and only used for that purpose) exists. "User" stacks | |
| 304 // can therefore be much smaller | |
| 305 | |
| 306 # define CYGNUM_HAL_STACK_SIZE_MINIMUM \ | |
| 307 (16*CYGNUM_HAL_STACK_FRAME_SIZE + 2*CYGNUM_HAL_STACK_INTERRUPT_SIZE) | |
| 308 | |
| 309 #else | |
| 310 | |
| 311 // No separate interrupt stack exists. Make sure all threads contain | |
| 312 // a stack sufficiently large | |
| 313 # define CYGNUM_HAL_STACK_SIZE_MINIMUM \ | |
| 314 (((2+3)*CYGNUM_HAL_STACK_INTERRUPT_SIZE) + \ | |
| 315 (16*CYGNUM_HAL_STACK_FRAME_SIZE)) | |
| 316 #endif | |
| 317 | |
| 318 // Now make a reasonable choice for a typical thread size. Pluck figures | |
| 319 // from thin air and say 30 call frames with an average of 16 words of | |
| 320 // automatic variables per call frame | |
| 321 #define CYGNUM_HAL_STACK_SIZE_TYPICAL \ | |
| 322 (CYGNUM_HAL_STACK_SIZE_MINIMUM + \ | |
| 323 30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4))) | |
| 324 | |
| 325 //----------------------------------------------------------------------------- | |
| 0 | 326 #endif // CYGONCE_HAL_ARCH_H |
| 327 // End of hal_arch.h |
