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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [m68k/] [arch/] [current/] [include/] [hal_arch.h] - Blame information for rev 856

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

Line No. Rev Author Line
1 786 skrzyp
#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) 2003, 2006, 2008 Free Software Foundation, 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      
19
// version.                                                                 
20
//
21
// eCos is distributed in the hope that it will be useful, but WITHOUT      
22
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
24
// for more details.                                                        
25
//
26
// You should have received a copy of the GNU General Public License        
27
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
28
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
29
//
30
// As a special exception, if other files instantiate templates or use      
31
// macros or inline functions from this file, or you compile this file      
32
// and link it with other works to produce a work based on this file,       
33
// this file does not by itself cause the resulting work to be covered by   
34
// the GNU General Public License. However the source code for this file    
35
// must still be made available in accordance with section (3) of the GNU   
36
// General Public License v2.                                               
37
//
38
// This exception does not invalidate any other reasons why a work based    
39
// on this file might be covered by the GNU General Public License.         
40
// -------------------------------------------                              
41
// ####ECOSGPLCOPYRIGHTEND####                                              
42
//=============================================================================
43
//####DESCRIPTIONBEGIN####
44
//
45
// Author(s):   bartv
46
// Date:        2003-06-04
47
//####DESCRIPTIONEND####
48
//=============================================================================
49
 
50
#include <pkgconf/system.h>
51
#include <pkgconf/hal.h>
52
#include <pkgconf/hal_m68k.h>
53
 
54
#include <cyg/infra/cyg_type.h>
55
#include <cyg/hal/var_arch.h>
56
 
57
// ----------------------------------------------------------------------------
58
// The default IPL level for when interrupts are enabled. Usually this will
59
// be set to 0, but on some platforms it may be appropriate to run with
60
// a higher IPL level and effectively leave some interrupts disabled.
61
 
62
#ifndef CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL
63
# define CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL    0
64
#endif
65
 
66
// ----------------------------------------------------------------------------
67
// setjmp/longjmp support. These only deal with the integer and fpu units.
68
// If there are other hardware units then they are unlikely to be used
69
// directly by the compiler, only by application code. Hence it is
70
// application code that should decide whether or not each unit's state
71
// should be preserved across setjmp/longjmp boundaries.
72
//
73
// Floating point registers have to be saved/restored here even if they
74
// are not saved during a context switch, because we are concerned
75
// about state within a single thread. The control and status registers
76
// are saved as well, but fpiar can be ignored - setjmp() is not going
77
// to happen while handling a floating point exception.
78
//
79
// The default implementation is in assembler and uses weak aliases. That
80
// code has to be kept in step with this structure definition.
81
 
82
#ifndef HAL_SETJMP
83
#define HAL_SETJMP
84
 
85
typedef struct {
86
    CYG_ADDRESS pc;
87
    CYG_ADDRESS sp;
88
    cyg_uint32  d[6];   // d2 to d7, d0 and d1 are caller-save
89
    CYG_ADDRESS a[5];   // a2 to a6, a0 and a1 are caller-save, a7 (sp) is separate
90
#ifdef CYGINT_HAL_M68K_VARIANT_FPU
91
    long double f[6];   // f2 to f7, f0 and f1 are caller-save
92
#endif
93
} hal_jmp_buf_t;
94
 
95
// This type is used by normal routines to pass the address of the
96
// structure into our routines without having to explicitly take the
97
// address of the structure.
98
typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)];
99
 
100
externC int                         hal_m68k_setjmp(hal_jmp_buf);
101
externC void                        hal_m68k_longjmp(hal_jmp_buf, int);
102
#define hal_setjmp(_env)            hal_m68k_setjmp(_env)
103
#define hal_longjmp(_env, _val)     hal_m68k_longjmp(_env, _val)
104
 
105
#endif // HAL_SETJMP
106
 
107
// ----------------------------------------------------------------------------
108
// Thread context support. The implementation is in assembler functions
109
// rather than inline macros. That makes it easier to cope with
110
// hardware-specific units which have their own context.
111
//
112
// A thread context consists of an integer part, a floating point part
113
// (iff the hardware has a standard FPU and if the configuration makes
114
// FPU context part of the save state), and OTHER for extra hardware
115
// units.
116
 
117
#define HAL_M68K_SR_C           (0x01 << 0)
118
#define HAL_M68K_SR_V           (0x01 << 1)
119
#define HAL_M68K_SR_Z           (0x01 << 2)
120
#define HAL_M68K_SR_N           (0x01 << 3)
121
#define HAL_M68K_SR_X           (0x01 << 4)
122
#define HAL_M68K_SR_S           (0x01 << 13)
123
#define HAL_M68K_SR_T           (0x01 << 15)
124
#define HAL_M68K_SR_IPL_MASK    (0x07 << 8)
125
#define HAL_M68K_SR_IPL_SHIFT   8
126
 
127
typedef struct {
128
    // The integer context, d0-d7,a0-a6
129
    cyg_uint32  da[15];
130
 
131
    // FPU context. This is only relevant if the hardware has an FPU,
132
    // and then only if the configuration makes the FPU context part
133
    // of the save state.
134
#ifdef CYGIMP_HAL_M68K_FPU_SAVE
135
    cyg_uint32  fpsr;
136
    CYG_ADDRESS fpiar;
137
    long double f[8];
138
#endif
139
 
140
    // Some m68k variants may have additional state that should be part
141
    // of a thread context.
142
#ifdef HAL_CONTEXT_OTHER
143
    HAL_CONTEXT_OTHER
144
#endif
145
 
146
    // Program counter, status register, etc. The exact layout is
147
    // determined by the variant. The intention is that the structure
148
    // matches the state pushed onto the stack by the hardware when an
149
    // interrupt occurs, so the context can overlap this part of the
150
    // stack. That avoids having to copy the saved PC and SR registers
151
    // from the stack into the context structure. The final step of
152
    // a context switch is an rte instruction.
153
    HAL_CONTEXT_PCSR
154
 
155
} HAL_SavedRegisters;
156
 
157
#define HAL_CONTEXT_INTEGER_SIZE    (15 * 4)
158
#ifdef CYGIMP_HAL_M68K_FPU_SAVE
159
# define HAL_CONTEXT_FPU_SIZE       ((2 * 4) + (8 * 12))
160
#else
161
# define HAL_CONTEXT_FPU_SIZE       0
162
#endif
163
#ifndef HAL_CONTEXT_OTHER_SIZE
164
# define HAL_CONTEXT_OTHER_SIZE     0
165
#endif
166
#ifndef HAL_CONTEXT_PCSR_SIZE
167
# define HAL_CONTEXT_PCSR_SIZE      8
168
#endif
169
 
170
#define HAL_CONTEXT_FULL_SIZE       (HAL_CONTEXT_INTEGER_SIZE + HAL_CONTEXT_FPU_SIZE + HAL_CONTEXT_OTHER_SIZE + HAL_CONTEXT_PCSR_SIZE)
171
 
172
// Load and switch are handled by functions in hal_arch.S. One level
173
// of indirection is removed here for the destination thread, so that
174
// the actual stack pointer gets passed to assembler.
175
externC void    hal_thread_load_context(CYG_ADDRESS) CYGBLD_ATTRIB_NORET;
176
externC void    hal_thread_switch_context(CYG_ADDRESS, CYG_ADDRESS);
177
 
178
#define HAL_THREAD_LOAD_CONTEXT(_to_)                                       \
179
    CYG_MACRO_START                                                         \
180
    hal_thread_load_context((CYG_ADDRESS) *(_to_));                         \
181
    CYG_MACRO_END
182
 
183
#define HAL_THREAD_SWITCH_CONTEXT(_from_, _to_)                             \
184
    CYG_MACRO_START                                                         \
185
    hal_thread_switch_context((CYG_ADDRESS)(_from_), (CYG_ADDRESS)*(_to_)); \
186
    CYG_MACRO_END
187
 
188
// Init context can be done easily in C.
189
//
190
// LOAD_CONTEXT and SWITCH_CONTEXT will end up doing an rte, so at the top
191
// of the stack we want the SR, return PC, a dummy PC for the entry point's
192
// stack frame, and the argument to the function.
193
//
194
//             +----------------+
195
//             | _thread_ arg   |
196
//             +----------------+
197
//             | return PC      |
198
//             +----------------+
199
//             | _entry_ PC     |
200
//             +- - - - - - - - +
201
//             |     SR         |
202
//   SP ---->  +- - - - - - - - +
203
//             |     HAL        |
204
//             | SavedRegisters |
205
//             |                |
206
//
207
// FPU and OTHER contexts are handled by macros which may or may not expand.
208
//
209
// The PC/SR fields are handled by variant-specific code.
210
 
211
#ifdef CYGIMP_HAL_M68K_FPU_SAVE
212
# define HAL_CONTEXT_FPU_INIT(_regs_)                                       \
213
    CYG_MACRO_START                                                         \
214
    int _j_;                                                                \
215
    (_regs_)->fpsr  = 0;                                                    \
216
    (_regs_)->fpiar = 0;                                                    \
217
    for (_j_ = 0; _j_ < 8; _j_++) {                                         \
218
        (_regs_)->f[_j_] = 0.0;                                             \
219
    }                                                                       \
220
    CYG_MACRO_END
221
#else
222
# define HAL_CONTEXT_FPU_INIT(_regs_)
223
#endif
224
#ifndef HAL_CONTEXT_OTHER_INIT
225
# define HAL_CONTEXT_OTHER_INIT(_regs_)
226
#endif
227
 
228
// Only initialize with ints enabled if CYGPKG_KERNEL. RedBoot does a
229
// LoadContext, causing interrupts to be enabled prematurely.
230
#ifdef CYGPKG_KERNEL
231
# define _HAL_M68K_INIT_CONTEXT_SR_ (0x2000 | (CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL<<8))
232
#else
233
# define _HAL_M68K_INIT_CONTEXT_SR_ (0x2700)
234
#endif
235
 
236
#define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_)                          \
237
    CYG_MACRO_START                                                                         \
238
    cyg_uint32* _sp_ = ((cyg_uint32*) ((cyg_uint32)(_sparg_) & ~(CYGARC_ALIGNMENT - 1)));   \
239
    HAL_SavedRegisters* _regs_;                                                             \
240
    int         _i_;                                                                        \
241
    *(--_sp_)   = (cyg_uint32)(_thread_);                                                   \
242
    *(--_sp_)   = 0xDEADC0DE;                                                               \
243
    _regs_      = (HAL_SavedRegisters*) ((cyg_uint32)_sp_ - sizeof(HAL_SavedRegisters));    \
244
    for (_i_ = 0; _i_ < 14; _i_++) {                                                        \
245
        _regs_->da[_i_] = _id_;                                                             \
246
    }                                                                                       \
247
    _regs_->da[14] = 0;                                                                     \
248
    HAL_CONTEXT_FPU_INIT(_regs_)                                                            \
249
    HAL_CONTEXT_OTHER_INIT(_regs_)                                                          \
250
    HAL_CONTEXT_PCSR_INIT(_regs_, _entry_, _HAL_M68K_INIT_CONTEXT_SR_);                     \
251
    (_sparg_) = (CYG_ADDRESS) (_regs_);                                                     \
252
    CYG_MACRO_END
253
 
254
// ----------------------------------------------------------------------------
255
// Minimal and sensible stack sizes: the intention is that applications
256
// will use these to provide a stack size in the first instance prior to
257
// proper analysis.  Idle thread stack should be this big.
258
//
259
//    THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES.
260
//           THEY ARE HOWEVER ENOUGH TO START PROGRAMMING.
261
// YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES!
262
//
263
// This is not a config option because it should not be adjusted except
264
// under "enough rope" sort of disclaimers.
265
 
266
// Stack frame overhead per call. 6 data registers, 5 address
267
// registers, frame pointer, and return address. We can't guess the
268
// local variables so just assume that using all of the registers
269
// averages out.
270
# define CYGNUM_HAL_STACK_FRAME_SIZE ((6 + 5 + 1 + 1) * 4)
271
 
272
// Stack needed for a context switch. Allow for sr and vector as well.
273
#ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE
274
# define CYGNUM_HAL_STACK_CONTEXT_SIZE HAL_CONTEXT_FULL_SIZE
275
#endif
276
 
277
// Interrupt handling. These need to allow for nesting and a
278
// separate interrupt stack.
279
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
280
# ifndef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
281
 
282
// No interrupt stack, no nesting. Worst case: a saved context, a
283
// frame for the interrupt_end() call, six frames for DSR processing,
284
// another saved context for an interrupt during the DSRs, and
285
// six frames for the ISR.
286
#  define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((2 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (13 * CYGNUM_HAL_STACK_FRAME_SIZE))
287
 
288
# else
289
// No interrupt stack but nesting. Worst case: a saved context,
290
// a frame for interrupt_end(), six frames for DSR processing, then
291
// up to five higher priority interrupts each requiring a context
292
// and six frames.
293
#  define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((6 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (37 * CYGNUM_HAL_STACK_FRAME_SIZE))
294
# endif
295
 
296
#else
297
 
298
# ifndef CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING
299
// An interrupt stack but no nesting. Worst case: a saved context,
300
// a frame for interrupt_end(), and another saved context. There
301
// is no need to worry about ISR or DSR frames since those will
302
// be on the interrupt stack. We also need to allow for nested
303
// interrupts before these are disabled, which will involve only
304
// 2 words rather than a full stack.
305
# define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((2 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (1 * CYGNUM_HAL_STACK_FRAME_SIZE) + (5 * 2 * 4))
306
 
307
# else
308
// An interrupt stack and nesting. We need to allow for another five
309
// nested contexts because nested interrupts may happen after pushing
310
// the current context but before switching to the interrupt stack.
311
# define CYGNUM_HAL_STACK_INTERRUPT_SIZE ((7 * CYGNUM_HAL_STACK_CONTEXT_SIZE) + (1 * CYGNUM_HAL_STACK_FRAME_SIZE))
312
 
313
# endif
314
#endif
315
 
316
// We define a minimum stack size as the minimum any thread could ever
317
// legitimately get away with. We can throw asserts if users ask for
318
// less than this. This allows for a saved context for context switching
319
// plus eight stack frames for cals, in addition to the interrupt overhead.
320
#define CYGNUM_HAL_STACK_SIZE_MINIMUM (CYGNUM_HAL_STACK_INTERRUPT_SIZE + CYGNUM_HAL_STACK_CONTEXT_SIZE + (8 * CYGNUM_HAL_STACK_FRAME_SIZE))
321
 
322
// Now make a reasonable choice for a typical thread size. Allow for
323
// another 8 call frames and a K for on-stack buffers, printf(),
324
// and debugging overheads.
325
#define CYGNUM_HAL_STACK_SIZE_TYPICAL (CYGNUM_HAL_STACK_SIZE_MINIMUM + (8 * CYGNUM_HAL_STACK_FRAME_SIZE) + 1024)
326
 
327
// -----------------------------------------------------------------------------
328
// Bit manipulation routines. The vanilla 68000 has no special
329
// instructions for this so assembler implementations are used
330
// instead. Newer ColdFires do have suitable instructions so will
331
// define their own versions of these macro.
332
 
333
#ifndef HAL_LSBIT_INDEX
334
externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask);
335
#define HAL_LSBIT_INDEX(index, mask) (index) = hal_lsbit_index(mask);
336
#endif
337
#ifndef HAL_MSBIT_INDEX
338
externC cyg_uint32 hal_msbit_index(cyg_uint32 mask);
339
#define HAL_MSBIT_INDEX(index, mask) (index) = hal_msbit_index(mask);
340
#endif
341
 
342
// There are some useful bit-set and bit-clear instructions which allow
343
// for atomic updates of a single byte of memory.
344
#define HAL_M68K_BSET(_address_, _bit_)                                                 \
345
    CYG_MACRO_START                                                                     \
346
    asm volatile("bset %0,(%1)\n" : : "i" (_bit_), "a" (_address_) : "cc", "memory");   \
347
    CYG_MACRO_END
348
 
349
#define HAL_M68K_BCLR(_address_, _bit_)                                                 \
350
    CYG_MACRO_START                                                                     \
351
    asm volatile("bclr %0,(%1)\n" : : "i" (_bit_), "a" (_address_) : "cc", "memory");   \
352
    CYG_MACRO_END
353
 
354
//-----------------------------------------------------------------------------
355
// Idle thread code. A plain 68000 has no special support, so a no-op
356
// function is used. Variants may use this to go into sleep mode.
357
 
358
#ifndef HAL_IDLE_THREAD_ACTION
359
# define HAL_IDLE_THREAD_ACTION(_count_) CYG_EMPTY_STATEMENT
360
#endif
361
 
362
//-----------------------------------------------------------------------------
363
// Execution reorder barrier.
364
// When optimizing the compiler can reorder code. In multithreaded systems
365
// where the order of actions is vital, this can sometimes cause problems.
366
// This macro may be inserted into places where reordering should not happen.
367
 
368
#define HAL_REORDER_BARRIER() __asm__ volatile ( "" : : : "memory" )
369
 
370
//--------------------------------------------------------------------------
371
// Macros for switching context between two eCos instances (jump from
372
// code in ROM to code in RAM or vice versa). The 68000 does not have any
373
// relevant global state so these macros are no-ops.
374
 
375
#define CYGARC_HAL_SAVE_GP()
376
#define CYGARC_HAL_RESTORE_GP()
377
 
378
//-----------------------------------------------------------------------------
379
// gdb support
380
 
381
// Translate a stack pointer as saved by the thread context macros
382
// into a pointer to a HAL_SavedRegisters structure. On the 68K
383
// these are equivalent.
384
#define HAL_THREAD_GET_SAVED_REGISTERS(_stack_, _regs_) \
385
    CYG_MACRO_START                                     \
386
    (_regs_)    = (HAL_SavedRegisters*)(_stack_);       \
387
    CYG_MACRO_END
388
 
389
// Translate between an eCos context and a gdb register set.
390
externC void hal_get_gdb_registers(CYG_ADDRWORD*, HAL_SavedRegisters*);
391
externC void hal_set_gdb_registers(HAL_SavedRegisters*, CYG_ADDRWORD*);
392
 
393
#define HAL_GET_GDB_REGISTERS(_regval_, _regs_)                                         \
394
    CYG_MACRO_START                                                                     \
395
    hal_get_gdb_registers((CYG_ADDRWORD*)(_regval_), (HAL_SavedRegisters*)(_regs_));    \
396
    CYG_MACRO_END
397
 
398
#define HAL_SET_GDB_REGISTERS(_regs_,_regval_)                                          \
399
    CYG_MACRO_START                                                                     \
400
    hal_set_gdb_registers((HAL_SavedRegisters*)(_regs_), (CYG_ADDRWORD*)(_regval_));    \
401
    CYG_MACRO_END
402
 
403
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
404
 
405
// HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen
406
// if executed.
407
// HAL_BREAKINST is the value of the breakpoint instruction and
408
// HAL_BREAKINST_SIZE is its size in bytes.
409
 
410
#define HAL_BREAKPOINT(_label_)                     \
411
__asm__ volatile (" .globl  " #_label_ ";"          \
412
              #_label_":"                           \
413
              " trap #15"                           \
414
    );
415
 
416
#define HAL_BREAKINST           0x4E4F
417
 
418
#define HAL_BREAKINST_SIZE      2
419
 
420
// The GDB register definitions. as per gdb/m68k-stub.c
421
// FIXME: more work is needed for floating point support.
422
enum regnames {
423
    D0, D1, D2, D3, D4, D5, D6, D7,
424
    A0, A1, A2, A3, A4, A5, FP, SP,
425
    PS, PC,
426
#ifdef CYGINT_HAL_M68K_VARIANT_FPU
427
    FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7,
428
    FPCONTROL, FPSTATUS, FPIADDR
429
#endif
430
};
431
 
432
#ifdef CYGINT_HAL_M68K_VARIANT_FPU
433
# define NUMREGS    29
434
#else
435
# define NUMREGS    18
436
#endif
437
 
438
#define REGSIZE(_x_)    (4)
439
 
440
typedef enum regnames regnames_t;
441
typedef CYG_ADDRWORD  target_register_t;
442
 
443
externC int     __computeSignal(unsigned int trap_number);
444
externC int     __get_trap_number(void);
445
externC void    __install_breakpoints(void);
446
externC void    __clear_breakpoints(void);
447
externC void    __single_step(void);
448
externC void    __clear_single_step(void);
449
externC void    __skipinst(void);
450
externC int     __is_breakpoint_function(void);
451
externC void    set_pc(target_register_t);
452
 
453
#define HAL_STUB_PLATFORM_STUBS_FIXUP()                         \
454
    CYG_MACRO_START                                             \
455
    if (CYGNUM_HAL_VECTOR_TRAP15 == __get_trap_number())        \
456
        put_register(PC, get_register(PC) - 2);                 \
457
    CYG_MACRO_END
458
 
459
#endif  // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
460
 
461
//-----------------------------------------------------------------------------
462
// Exception handling function.
463
// This function is defined by the kernel according to this prototype. It is
464
// invoked from the HAL to deal with any CPU exceptions that the HAL does
465
// not want to deal with itself. It usually invokes the kernel's exception
466
// delivery mechanism.
467
#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && defined(CYGPKG_HAL_EXCEPTIONS)
468
externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data );
469
#endif
470
 
471
//-----------------------------------------------------------------------------
472
#endif // CYGONCE_HAL_ARCH_H
473
// End of hal_arch.h
474
 

powered by: WebSVN 2.1.0

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