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