RTEMS 5.2
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
cpu.h
Go to the documentation of this file.
1
12/*
13 * COPYRIGHT (c) 1989-2011.
14 * On-Line Applications Research Corporation (OAR).
15 *
16 * The license and distribution terms for this file may be
17 * found in the file LICENSE in this distribution or at
18 * http://www.rtems.org/license/LICENSE.
19 */
20
21#ifndef _RTEMS_SCORE_CPU_H
22#define _RTEMS_SCORE_CPU_H
23
24#ifdef __cplusplus
25extern "C" {
26#endif
27
29#include <rtems/score/m68k.h>
30
31/* conditional compilation parameters */
32
33/*
34 * Does the CPU follow the simple vectored interrupt model?
35 *
36 * If TRUE, then RTEMS allocates the vector table it internally manages.
37 * If FALSE, then the BSP is assumed to allocate and manage the vector
38 * table
39 *
40 * M68K Specific Information:
41 *
42 * XXX document implementation including references if appropriate
43 */
44#define CPU_SIMPLE_VECTORED_INTERRUPTS TRUE
45
46/*
47 * Does the RTEMS invoke the user's ISR with the vector number and
48 * a pointer to the saved interrupt frame (1) or just the vector
49 * number (0)?
50 */
51
52#define CPU_ISR_PASSES_FRAME_POINTER FALSE
53
54/*
55 * Some family members have no FP, some have an FPU such as the
56 * MC68881/MC68882 for the MC68020, others have it built in (MC68030, 040).
57 *
58 * NOTE: If on a CPU without hardware FP, then one can use software
59 * emulation. The gcc software FP emulation code has data which
60 * must be contexted switched on a per task basis.
61 */
62
63#if ( M68K_HAS_FPU == 1 ) || ( M68K_HAS_EMAC == 1 )
64 #define CPU_HARDWARE_FP TRUE
65 #define CPU_SOFTWARE_FP FALSE
66#else
67 #define CPU_HARDWARE_FP FALSE
68 #if defined( __GNUC__ )
69 #define CPU_SOFTWARE_FP TRUE
70 #else
71 #define CPU_SOFTWARE_FP FALSE
72 #endif
73#endif
74
75/*
76 * All tasks are not by default floating point tasks on this CPU.
77 * The IDLE task does not have a floating point context on this CPU.
78 * It is safe to use the deferred floating point context switch
79 * algorithm on this CPU.
80 */
81
82#define CPU_ALL_TASKS_ARE_FP FALSE
83#define CPU_IDLE_TASK_IS_FP FALSE
84#define CPU_USE_DEFERRED_FP_SWITCH TRUE
85#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
86
87#define CPU_STACK_GROWS_UP FALSE
88
89/* FIXME: Is this the right value? */
90#define CPU_CACHE_LINE_BYTES 16
91
92#define CPU_STRUCTURE_ALIGNMENT RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )
93
94#define CPU_MAXIMUM_PROCESSORS 32
95
96#if ( CPU_HARDWARE_FP == TRUE ) && !defined( __mcoldfire__ )
97 #if defined( __mc68060__ )
98 #define M68K_FP_STATE_SIZE 16
99 #else
100 #define M68K_FP_STATE_SIZE 216
101 #endif
102#endif
103
104#ifndef ASM
105
106/* structures */
107
108/*
109 * Basic integer context for the m68k family.
110 */
111
112typedef struct {
113 uint32_t sr; /* (sr) status register */
114 uint32_t d2; /* (d2) data register 2 */
115 uint32_t d3; /* (d3) data register 3 */
116 uint32_t d4; /* (d4) data register 4 */
117 uint32_t d5; /* (d5) data register 5 */
118 uint32_t d6; /* (d6) data register 6 */
119 uint32_t d7; /* (d7) data register 7 */
120 void *a2; /* (a2) address register 2 */
121 void *a3; /* (a3) address register 3 */
122 void *a4; /* (a4) address register 4 */
123 void *a5; /* (a5) address register 5 */
124 void *a6; /* (a6) address register 6 */
125 void *a7_msp; /* (a7) master stack pointer */
126 #if defined( __mcoldfire__ ) && ( M68K_HAS_FPU == 1 )
127 uint8_t fpu_dis;
128 #endif
130
131#define _CPU_Context_Get_SP( _context ) \
132 (_context)->a7_msp
133
134/*
135 * Floating point context areas and support routines
136 */
137
138#if ( CPU_SOFTWARE_FP == TRUE )
139 /*
140 * This is the same as gcc's view of the software FP condition code
141 * register _fpCCR. The implementation of the emulation code is
142 * in the gcc-VERSION/config/m68k directory. This structure is
143 * correct as of gcc 2.7.2.2.
144 */
145 typedef struct {
146 uint16_t _exception_bits;
147 uint16_t _trap_enable_bits;
148 uint16_t _sticky_bits;
149 uint16_t _rounding_mode;
150 uint16_t _format;
151 uint16_t _last_operation;
152 union {
153 float sf;
154 double df;
155 } _operand1;
156 union {
157 float sf;
158 double df;
159 } _operand2;
161
162 #define _CPU_Context_Initialize_fp( _fp_area ) \
163 { \
164 Context_Control_fp *_fp; \
165 _fp = *(Context_Control_fp **)_fp_area; \
166 _fp->_exception_bits = 0; \
167 _fp->_trap_enable_bits = 0; \
168 _fp->_sticky_bits = 0; \
169 _fp->_rounding_mode = 0; /* ROUND_TO_NEAREST */ \
170 _fp->_format = 0; /* NIL */ \
171 _fp->_last_operation = 0; /* NOOP */ \
172 _fp->_operand1.df = 0; \
173 _fp->_operand2.df = 0; \
174 }
175#endif
176
177#if ( CPU_HARDWARE_FP == TRUE )
178 #if defined( __mcoldfire__ )
179 /* We need memset() to initialize the FP context */
180 #include <string.h>
181
182 #if ( M68K_HAS_FPU == 1 )
183 /*
184 * The Cache Control Register (CACR) has write-only access. It is also
185 * used to enable and disable the FPU. We need to maintain a copy of
186 * this register to allow per thread values.
187 */
188 extern uint32_t _CPU_cacr_shadow;
189 #endif
190
191 /* We assume that each ColdFire core with a FPU has also an EMAC unit */
192 typedef struct {
193 uint32_t emac_macsr;
194 uint32_t emac_acc0;
195 uint32_t emac_acc1;
196 uint32_t emac_acc2;
197 uint32_t emac_acc3;
198 uint32_t emac_accext01;
199 uint32_t emac_accext23;
200 uint32_t emac_mask;
201 #if ( M68K_HAS_FPU == 1 )
202 uint16_t fp_state_format;
203 uint16_t fp_state_fpcr;
204 double fp_state_op;
205 uint32_t fp_state_fpsr;
206
207 /*
208 * We need to save the FP Instruction Address Register (FPIAR), because
209 * a context switch can occur within a FP exception before the handler
210 * was able to save this register.
211 */
212 uint32_t fp_fpiar;
213
214 double fp_data [8];
215 #endif
217
218 /*
219 * The reset value for all context relevant registers except the FP data
220 * registers is zero. The reset value of the FP data register is NAN. The
221 * restore of the reset FP state will reset the FP data registers, so the
222 * initial value of them can be arbitrary here.
223 */
224 #define _CPU_Context_Initialize_fp( _fp_area ) \
225 memset( *(_fp_area), 0, sizeof( Context_Control_fp ) )
226 #else
227 /*
228 * FP context save area for the M68881/M68882 and 68060 numeric
229 * coprocessors.
230 */
231 typedef struct {
232 /*
233 * M68K_FP_STATE_SIZE bytes for FSAVE/FRESTORE
234 * 96 bytes for FMOVEM FP0-7
235 * 12 bytes for FMOVEM CREGS
236 * 4 bytes for non-null flag
237 */
238 uint8_t fp_save_area [M68K_FP_STATE_SIZE + 112];
240
241 /*
242 * The floating-point context is saved/restored via FSAVE/FRESTORE which
243 * use a growing down stack. Initialize the stack and adjust the FP area
244 * pointer accordingly.
245 */
246 #define _CPU_Context_Initialize_fp( _fp_area ) \
247 { \
248 uint32_t *_fp_context = (uint32_t *) \
249 ( (uintptr_t) *( _fp_area ) + CPU_CONTEXT_FP_SIZE - 4 ); \
250 *(--(_fp_context)) = 0; \
251 *(_fp_area) = (void *)(_fp_context); \
252 }
253 #endif
254#endif
255
256/*
257 * The following structures define the set of information saved
258 * on the current stack by RTEMS upon receipt of each exc/interrupt.
259 * These are not used by m68k handlers.
260 * The exception frame is for rdbg.
261 */
262
263typedef struct {
264 uint32_t vecnum; /* vector number */
266
267typedef struct {
268 uint32_t vecnum; /* vector number */
269 uint32_t sr; /* status register */
270 uint32_t pc; /* program counter */
271 uint32_t d0, d1, d2, d3, d4, d5, d6, d7;
272 uint32_t a0, a1, a2, a3, a4, a5, a6, a7;
274
275/* variables */
276
277extern void* _VBR;
278
279#endif /* ASM */
280
281/* constants */
282
283/*
284 * This defines the number of levels and the mask used to pick those
285 * bits out of a thread mode.
286 */
287
288#define CPU_MODES_INTERRUPT_MASK 0x00000007 /* interrupt level in mode */
289
290/*
291 * context size area for floating point
292 */
293
294#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
295
296/*
297 * extra stack required by the MPCI receive server thread
298 */
299
300#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
301
302/*
303 * m68k family supports 256 distinct vectors.
304 */
305
306#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
307#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
308
309/*
310 * This is defined if the port has a special way to report the ISR nesting
311 * level. Most ports maintain the variable _ISR_Nest_level.
312 */
313
314#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
315
316/*
317 * Minimum size of a thread's stack.
318 */
319
320#define CPU_STACK_MINIMUM_SIZE M68K_CPU_STACK_MINIMUM_SIZE
321
322/*
323 * Maximum priority of a thread. Note based from 0 which is the idle task.
324 */
325#define CPU_PRIORITY_MAXIMUM M68K_CPU_PRIORITY_MAXIMUM
326
327#define CPU_SIZEOF_POINTER 4
328
329/*
330 * m68k is pretty tolerant of alignment. Just put things on 4 byte boundaries.
331 */
332
333#define CPU_ALIGNMENT 4
334#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
335
336/*
337 * On m68k thread stacks require no further alignment after allocation
338 * from the Workspace.
339 */
340
341#define CPU_STACK_ALIGNMENT 0
342
343#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
344
345#ifndef ASM
346
347/* macros */
348
349/*
350 * ISR handler macros
351 *
352 * These macros perform the following functions:
353 * + initialize the RTEMS vector table
354 * + disable all maskable CPU interrupts
355 * + restore previous interrupt level (enable)
356 * + temporarily restore interrupts (flash)
357 * + set a particular level
358 */
359
360#define _CPU_Initialize_vectors()
361
362#define _CPU_ISR_Disable( _level ) \
363 m68k_disable_interrupts( _level )
364
365#define _CPU_ISR_Enable( _level ) \
366 m68k_enable_interrupts( _level )
367
368#define _CPU_ISR_Flash( _level ) \
369 m68k_flash_interrupts( _level )
370
371RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( uint32_t level )
372{
373 return ( level & 0x0700 ) == 0;
374}
375
376#define _CPU_ISR_Set_level( _newlevel ) \
377 m68k_set_interrupt_level( _newlevel )
378
379uint32_t _CPU_ISR_Get_level( void );
380
381/* end of ISR handler macros */
382
383/*
384 * Context handler macros
385 *
386 * These macros perform the following functions:
387 * + initialize a context area
388 * + restart the current thread
389 * + calculate the initial pointer into a FP context area
390 * + initialize an FP context area
391 */
392
394 Context_Control *the_context,
395 void *stack_area_begin,
396 size_t stack_area_size,
397 uint32_t new_level,
398 void (*entry_point)( void ),
399 bool is_fp,
400 void *tls_area
401);
402
403/* end of Context handler macros */
404
405void *_CPU_Thread_Idle_body( uintptr_t ignored );
406
407/*
408 * Fatal Error manager macros
409 *
410 * These macros perform the following functions:
411 * + disable interrupts and halt the CPU
412 */
413
414#if ( defined(__mcoldfire__) )
415#define _CPU_Fatal_halt( _source, _error ) \
416 { __asm__ volatile( "move.w %%sr,%%d0\n\t" \
417 "or.l %2,%%d0\n\t" \
418 "move.w %%d0,%%sr\n\t" \
419 "move.l %1,%%d0\n\t" \
420 "move.l #0xDEADBEEF,%%d1\n\t" \
421 "halt" \
422 : "=g" (_error) \
423 : "0" (_error), "d"(0x0700) \
424 : "d0", "d1" ); \
425 }
426#else
427#define _CPU_Fatal_halt( _source, _error ) \
428 { __asm__ volatile( "movl %0,%%d0; " \
429 "orw #0x0700,%%sr; " \
430 "stop #0x2700" : "=d" ((_error)) : "0" ((_error)) ); \
431 }
432#endif
433
434/* end of Fatal Error manager macros */
435
436/*
437 * Bitfield handler macros
438 *
439 * These macros perform the following functions:
440 * + scan for the highest numbered (MSB) set in a 16 bit bitfield
441 *
442 * NOTE:
443 *
444 * It appears that on the M68020 bitfield are always 32 bits wide
445 * when in a register. This code forces the bitfield to be in
446 * memory (it really always is anyway). This allows us to
447 * have a real 16 bit wide bitfield which operates "correctly."
448 */
449
450#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
451
452#if ( M68K_HAS_BFFFO != 1 )
453/*
454 * Lookup table for BFFFO simulation
455 */
456extern const unsigned char _CPU_m68k_BFFFO_table[256];
457#endif
458
459#if ( M68K_HAS_BFFFO == 1 )
460
461#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
462 __asm__ volatile( "bfffo (%1),#0,#16,%0" : "=d" (_output) : "a" (&_value));
463
464#elif ( __mcfisaaplus__ )
465 /* This is simplified by the fact that RTEMS never calls it with _value=0 */
466#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
467 __asm__ volatile ( \
468 " swap %0\n" \
469 " ff1.l %0\n" \
470 : "=d" ((_output)) \
471 : "0" ((_value)) \
472 : "cc" ) ;
473
474#else
475/* duplicates BFFFO results for 16 bits (i.e., 15-(_priority) in
476 _CPU_Priority_bits_index is not needed), handles the 0 case, and
477 does not molest _value -- jsg */
478#if ( defined(__mcoldfire__) )
479
480#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
481 { \
482 int dumby; \
483 \
484 __asm__ volatile ( \
485 " clr.l %1\n" \
486 " move.w %2,%1\n" \
487 " lsr.l #8,%1\n" \
488 " beq.s 1f\n" \
489 " move.b (%3,%1),%0\n" \
490 " bra.s 0f\n" \
491 "1: move.w %2,%1\n" \
492 " move.b (%3,%1),%0\n" \
493 " addq.l #8,%0\n" \
494 "0: and.l #0xff,%0\n" \
495 : "=&d" ((_output)), "=&d" ((dumby)) \
496 : "d" ((_value)), "ao" ((_CPU_m68k_BFFFO_table)) \
497 : "cc" ) ; \
498 }
499#elif ( M68K_HAS_EXTB_L == 1 )
500#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
501 { \
502 int dumby; \
503 \
504 __asm__ volatile ( " move.w %2,%1\n" \
505 " lsr.w #8,%1\n" \
506 " beq.s 1f\n" \
507 " move.b (%3,%1.w),%0\n" \
508 " extb.l %0\n" \
509 " bra.s 0f\n" \
510 "1: moveq.l #8,%0\n" \
511 " add.b (%3,%2.w),%0\n" \
512 "0:\n" \
513 : "=&d" ((_output)), "=&d" ((dumby)) \
514 : "d" ((_value)), "ao" ((_CPU_m68k_BFFFO_table)) \
515 : "cc" ) ; \
516 }
517#else
518#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
519 { \
520 int dumby; \
521 \
522 __asm__ volatile ( " move.w %2,%1\n" \
523 " lsr.w #8,%1\n" \
524 " beq.s 1f\n" \
525 " move.b (%3,%1.w),%0\n" \
526 " and.l #0x000000ff,%0\n"\
527 " bra.s 0f\n" \
528 "1: moveq.l #8,%0\n" \
529 " add.b (%3,%2.w),%0\n" \
530 "0:\n" \
531 : "=&d" ((_output)), "=&d" ((dumby)) \
532 : "d" ((_value)), "ao" ((_CPU_m68k_BFFFO_table)) \
533 : "cc" ) ; \
534 }
535#endif
536
537#endif
538
539/* end of Bitfield handler macros */
540
541/*
542 * Priority handler macros
543 *
544 * These macros perform the following functions:
545 * + return a mask with the bit for this major/minor portion of
546 * of thread priority set.
547 * + translate the bit number returned by "Bitfield_find_first_bit"
548 * into an index into the thread ready chain bit maps
549 */
550
551#define _CPU_Priority_Mask( _bit_number ) \
552 ( 0x8000 >> (_bit_number) )
553
554#define _CPU_Priority_bits_index( _priority ) \
555 (_priority)
556
557/* end of Priority handler macros */
558
559/* functions */
560
561/*
562 * _CPU_Initialize
563 *
564 * This routine performs CPU dependent initialization.
565 */
566
567void _CPU_Initialize(void);
568
569typedef void ( *CPU_ISR_raw_handler )( void );
570
572 uint32_t vector,
573 CPU_ISR_raw_handler new_handler,
574 CPU_ISR_raw_handler *old_handler
575);
576
577typedef void ( *CPU_ISR_handler )( uint32_t );
578
580 uint32_t vector,
581 CPU_ISR_handler new_handler,
582 CPU_ISR_handler *old_handler
583);
584
585/*
586 * _CPU_Context_switch
587 *
588 * This routine switches from the run context to the heir context.
589 */
590
592 Context_Control *run,
593 Context_Control *heir
594);
595
597 Context_Control *the_context
599
600/*
601 * _CPU_Context_save_fp
602 *
603 * This routine saves the floating point context passed to it.
604 */
605
607 Context_Control_fp **fp_context_ptr
608);
609
610/*
611 * _CPU_Context_restore_fp
612 *
613 * This routine restores the floating point context passed to it.
614 */
615
617 Context_Control_fp **fp_context_ptr
618);
619
626 const CPU_Exception_frame *frame
627);
628
629typedef uint32_t CPU_Counter_ticks;
630
631uint32_t _CPU_Counter_frequency( void );
632
633CPU_Counter_ticks _CPU_Counter_read( void );
634
635static inline CPU_Counter_ticks _CPU_Counter_difference(
636 CPU_Counter_ticks second,
637 CPU_Counter_ticks first
638)
639{
640 return second - first;
641}
642
643#if (M68K_HAS_FPSP_PACKAGE == 1)
644/*
645 * Hooks for the Floating Point Support Package (FPSP) provided by Motorola
646 *
647 * NOTES:
648 *
649 * Motorola 68k family CPU's before the 68040 used a coprocessor
650 * (68881 or 68882) to handle floating point. The 68040 has internal
651 * floating point support -- but *not* the complete support provided by
652 * the 68881 or 68882. The leftover functions are taken care of by the
653 * M68040 Floating Point Support Package. Quoting from the MC68040
654 * Microprocessors User's Manual, Section 9, Floating-Point Unit (MC68040):
655 *
656 * "When used with the M68040FPSP, the MC68040 FPU is fully
657 * compliant with IEEE floating-point standards."
658 *
659 * M68KFPSPInstallExceptionHandlers is in libcpu/m68k/MODEL/fpsp and
660 * is invoked early in the application code to ensure that proper FP
661 * behavior is installed. This is not left to the BSP to call, since
662 * this would force all applications using that BSP to use FPSP which
663 * is not necessarily desirable.
664 *
665 * There is a similar package for the 68060 but RTEMS does not yet
666 * support the 68060.
667 */
668
669void M68KFPSPInstallExceptionHandlers (void);
670
671extern int (*_FPSP_install_raw_handler)(
672 uint32_t vector,
673 CPU_ISR_raw_handler new_handler,
674 CPU_ISR_raw_handler *old_handler
675);
676
677#endif
678
680typedef uintptr_t CPU_Uint32ptr;
681
682#endif
683
684#ifdef __cplusplus
685}
686#endif
687
688#endif
Basic Definitions.
#define _CPU_Context_Restart_self(_the_context)
Definition: cpu.h:480
#define RTEMS_NO_RETURN
Definition: basedefs.h:102
#define RTEMS_INLINE_ROUTINE
Definition: basedefs.h:66
bool _CPU_ISR_Is_enabled(uint32_t level)
Returns true if interrupts are enabled in the specified ISR level, otherwise returns false.
Definition: cpu.h:375
void * _CPU_Thread_Idle_body(uintptr_t ignored)
Definition: idle-mcf5272.c:20
void _CPU_Initialize(void)
CPU initialization.
Definition: cpu.c:45
uintptr_t CPU_Uint32ptr
Definition: cpu.h:662
RTEMS_INLINE_ROUTINE void _CPU_ISR_install_vector(uint32_t vector, CPU_ISR_handler new_handler, CPU_ISR_handler *old_handler)
SPARC specific RTEMS ISR installer.
Definition: cpu.h:493
uint32_t _CPU_Counter_frequency(void)
Returns the current CPU counter frequency in Hz.
Definition: system-clocks.c:112
void _CPU_Context_switch(Context_Control *run, Context_Control *heir)
CPU switch context.
Definition: cpu_asm.c:91
CPU_Counter_ticks _CPU_Counter_read(void)
Returns the current CPU counter value.
Definition: system-clocks.c:117
uint32_t _CPU_ISR_Get_level(void)
Definition: cpu.c:88
void _CPU_Context_Initialize(Context_Control *context, void *stack_area_begin, size_t stack_area_size, uint32_t new_level, void(*entry_point)(void), bool is_fp, void *tls_area)
Initializes the CPU context.
Definition: epiphany-context-initialize.c:40
void _CPU_Exception_frame_print(const CPU_Exception_frame *frame)
Prints the exception frame via printk().
Definition: vectorexceptions.c:45
RTEMS_INLINE_ROUTINE void _CPU_ISR_install_raw_handler(uint32_t vector, CPU_ISR_raw_handler new_handler, CPU_ISR_raw_handler *old_handler)
SPARC specific raw ISR installer.
Definition: cpu.h:649
#define pc
pc, used on mips16 *‍/
Definition: regs.h:67
Motorola M68K CPU Dependent Source.
uint32_t CPU_Counter_ticks
Unsigned integer type for CPU counter values.
Definition: cpu.h:1210
#define _CPU_Context_restore_fp(_fp_context_ptr)
Nothing to do due to the synchronous or lazy floating point switch.
Definition: cpu.h:904
#define _CPU_Context_save_fp(_fp_context_ptr)
Nothing to do due to the synchronous or lazy floating point switch.
Definition: cpu.h:898
The set of registers that specifies the complete processor state.
Definition: cpu.h:629
Interrupt stack frame (ISF).
Definition: cpu.h:191
SPARC basic context.
Definition: cpu.h:194
Thread register context.
Definition: cpu.h:194