RTEMS 7.0-rc1
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 (uintptr_t)(_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#endif /* ASM */
296
297/* constants */
298
299/*
300 * This defines the number of levels and the mask used to pick those
301 * bits out of a thread mode.
302 */
303
304#define CPU_MODES_INTERRUPT_MASK 0x00000007 /* interrupt level in mode */
305
306/*
307 * context size area for floating point
308 */
309
310#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
311
312/*
313 * extra stack required by the MPCI receive server thread
314 */
315
316#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
317
318/*
319 * m68k family supports 256 distinct vectors.
320 */
321
322#define CPU_INTERRUPT_NUMBER_OF_VECTORS 256
323#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
324
325/*
326 * This is defined if the port has a special way to report the ISR nesting
327 * level. Most ports maintain the variable _ISR_Nest_level.
328 */
329
330#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
331
332/*
333 * Minimum size of a thread's stack.
334 */
335
336#define CPU_STACK_MINIMUM_SIZE M68K_CPU_STACK_MINIMUM_SIZE
337
338/*
339 * Maximum priority of a thread. Note based from 0 which is the idle task.
340 */
341#define CPU_PRIORITY_MAXIMUM M68K_CPU_PRIORITY_MAXIMUM
342
343#define CPU_SIZEOF_POINTER 4
344
345/*
346 * m68k is pretty tolerant of alignment. Just put things on 4 byte boundaries.
347 */
348
349#define CPU_ALIGNMENT 4
350#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
351
352/*
353 * On m68k thread stacks require no further alignment after allocation
354 * from the Workspace.
355 */
356
357#define CPU_STACK_ALIGNMENT CPU_ALIGNMENT
358
359#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
360
361#ifndef ASM
362
363/* macros */
364
365/*
366 * ISR handler macros
367 *
368 * These macros perform the following functions:
369 * + disable all maskable CPU interrupts
370 * + restore previous interrupt level (enable)
371 * + temporarily restore interrupts (flash)
372 * + set a particular level
373 */
374
375#define _CPU_ISR_Disable( _level ) \
376 m68k_disable_interrupts( _level )
377
378#define _CPU_ISR_Enable( _level ) \
379 m68k_enable_interrupts( _level )
380
381#define _CPU_ISR_Flash( _level ) \
382 m68k_flash_interrupts( _level )
383
384static inline bool _CPU_ISR_Is_enabled( uint32_t level )
385{
386 return ( level & 0x0700 ) == 0;
387}
388
389#define _CPU_ISR_Set_level( _newlevel ) \
390 m68k_set_interrupt_level( _newlevel )
391
392uint32_t _CPU_ISR_Get_level( void );
393
394/* end of ISR handler macros */
395
396/*
397 * Context handler macros
398 *
399 * These macros perform the following functions:
400 * + initialize a context area
401 * + restart the current thread
402 * + calculate the initial pointer into a FP context area
403 * + initialize an FP context area
404 */
405
406void _CPU_Context_Initialize(
407 Context_Control *the_context,
408 void *stack_area_begin,
409 size_t stack_area_size,
410 uint32_t new_level,
411 void (*entry_point)( void ),
412 bool is_fp,
413 void *tls_area
414);
415
416/* end of Context handler macros */
417
418RTEMS_NO_RETURN void *_CPU_Thread_Idle_body( uintptr_t ignored );
419
420#define CPU_USE_LIBC_INIT_FINI_ARRAY FALSE
421
422/*
423 * Bitfield handler macros
424 *
425 * These macros perform the following functions:
426 * + scan for the highest numbered (MSB) set in a 16 bit bitfield
427 *
428 * NOTE:
429 *
430 * It appears that on the M68020 bitfield are always 32 bits wide
431 * when in a register. This code forces the bitfield to be in
432 * memory (it really always is anyway). This allows us to
433 * have a real 16 bit wide bitfield which operates "correctly."
434 */
435
436#define CPU_USE_GENERIC_BITFIELD_CODE FALSE
437
438#if ( M68K_HAS_BFFFO != 1 )
439/*
440 * Lookup table for BFFFO simulation
441 */
442extern const unsigned char _CPU_m68k_BFFFO_table[256];
443#endif
444
445#if ( M68K_HAS_BFFFO == 1 )
446
447#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
448 __asm__ volatile( "bfffo (%1),#0,#16,%0" : "=d" (_output) : "a" (&_value));
449
450#elif ( __mcfisaaplus__ )
451 /* This is simplified by the fact that RTEMS never calls it with _value=0 */
452#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
453 __asm__ volatile ( \
454 " swap %0\n" \
455 " ff1.l %0\n" \
456 : "=d" ((_output)) \
457 : "0" ((_value)) \
458 : "cc" ) ;
459
460#else
461/* duplicates BFFFO results for 16 bits (i.e., 15-(_priority) in
462 _CPU_Priority_bits_index is not needed), handles the 0 case, and
463 does not molest _value -- jsg */
464#if ( defined(__mcoldfire__) )
465
466#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
467 { \
468 int dumby; \
469 \
470 __asm__ volatile ( \
471 " clr.l %1\n" \
472 " move.w %2,%1\n" \
473 " lsr.l #8,%1\n" \
474 " beq.s 1f\n" \
475 " move.b (%3,%1),%0\n" \
476 " bra.s 0f\n" \
477 "1: move.w %2,%1\n" \
478 " move.b (%3,%1),%0\n" \
479 " addq.l #8,%0\n" \
480 "0: and.l #0xff,%0\n" \
481 : "=&d" ((_output)), "=&d" ((dumby)) \
482 : "d" ((_value)), "ao" ((_CPU_m68k_BFFFO_table)) \
483 : "cc" ) ; \
484 }
485#elif ( M68K_HAS_EXTB_L == 1 )
486#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
487 { \
488 int dumby; \
489 \
490 __asm__ volatile ( " move.w %2,%1\n" \
491 " lsr.w #8,%1\n" \
492 " beq.s 1f\n" \
493 " move.b (%3,%1.w),%0\n" \
494 " extb.l %0\n" \
495 " bra.s 0f\n" \
496 "1: moveq.l #8,%0\n" \
497 " add.b (%3,%2.w),%0\n" \
498 "0:\n" \
499 : "=&d" ((_output)), "=&d" ((dumby)) \
500 : "d" ((_value)), "ao" ((_CPU_m68k_BFFFO_table)) \
501 : "cc" ) ; \
502 }
503#else
504#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
505 { \
506 int dumby; \
507 \
508 __asm__ volatile ( " move.w %2,%1\n" \
509 " lsr.w #8,%1\n" \
510 " beq.s 1f\n" \
511 " move.b (%3,%1.w),%0\n" \
512 " and.l #0x000000ff,%0\n"\
513 " bra.s 0f\n" \
514 "1: moveq.l #8,%0\n" \
515 " add.b (%3,%2.w),%0\n" \
516 "0:\n" \
517 : "=&d" ((_output)), "=&d" ((dumby)) \
518 : "d" ((_value)), "ao" ((_CPU_m68k_BFFFO_table)) \
519 : "cc" ) ; \
520 }
521#endif
522
523#endif
524
525/* end of Bitfield handler macros */
526
527/*
528 * Priority handler macros
529 *
530 * These macros perform the following functions:
531 * + return a mask with the bit for this major/minor portion of
532 * of thread priority set.
533 * + translate the bit number returned by "Bitfield_find_first_bit"
534 * into an index into the thread ready chain bit maps
535 */
536
537#define _CPU_Priority_Mask( _bit_number ) \
538 ( 0x8000 >> (_bit_number) )
539
540#define _CPU_Priority_bits_index( _priority ) \
541 (_priority)
542
543/* end of Priority handler macros */
544
545/* functions */
546
547/*
548 * _CPU_Initialize
549 *
550 * This routine performs CPU dependent initialization.
551 */
552
553void _CPU_Initialize(void);
554
555typedef void ( *CPU_ISR_raw_handler )( void );
556
558 uint32_t vector,
559 CPU_ISR_raw_handler new_handler,
560 CPU_ISR_raw_handler *old_handler
561);
562
563typedef void ( *CPU_ISR_handler )( uint32_t );
564
566 uint32_t vector,
567 CPU_ISR_handler new_handler,
568 CPU_ISR_handler *old_handler
569);
570
571/*
572 * _CPU_Context_switch
573 *
574 * This routine switches from the run context to the heir context.
575 */
576
578 Context_Control *run,
579 Context_Control *heir
580);
581
582RTEMS_NO_RETURN void _CPU_Context_Restart_self(
583 Context_Control *the_context
584);
585
586/*
587 * _CPU_Context_save_fp
588 *
589 * This routine saves the floating point context passed to it.
590 */
591
593 Context_Control_fp **fp_context_ptr
594);
595
596/*
597 * _CPU_Context_restore_fp
598 *
599 * This routine restores the floating point context passed to it.
600 */
601
603 Context_Control_fp **fp_context_ptr
604);
605
612 const CPU_Exception_frame *frame
613);
614
615typedef uint32_t CPU_Counter_ticks;
616
617uint32_t _CPU_Counter_frequency( void );
618
619CPU_Counter_ticks _CPU_Counter_read( void );
620
621#if (M68K_HAS_FPSP_PACKAGE == 1)
622/*
623 * Hooks for the Floating Point Support Package (FPSP) provided by Motorola
624 *
625 * NOTES:
626 *
627 * Motorola 68k family CPU's before the 68040 used a coprocessor
628 * (68881 or 68882) to handle floating point. The 68040 has internal
629 * floating point support -- but *not* the complete support provided by
630 * the 68881 or 68882. The leftover functions are taken care of by the
631 * M68040 Floating Point Support Package. Quoting from the MC68040
632 * Microprocessors User's Manual, Section 9, Floating-Point Unit (MC68040):
633 *
634 * "When used with the M68040FPSP, the MC68040 FPU is fully
635 * compliant with IEEE floating-point standards."
636 *
637 * M68KFPSPInstallExceptionHandlers is in libcpu/m68k/MODEL/fpsp and
638 * is invoked early in the application code to ensure that proper FP
639 * behavior is installed. This is not left to the BSP to call, since
640 * this would force all applications using that BSP to use FPSP which
641 * is not necessarily desirable.
642 *
643 * There is a similar package for the 68060 but RTEMS does not yet
644 * support the 68060.
645 */
646
647void M68KFPSPInstallExceptionHandlers (void);
648
649extern int (*_FPSP_install_raw_handler)(
650 uint32_t vector,
651 CPU_ISR_raw_handler new_handler,
652 CPU_ISR_raw_handler *old_handler
653);
654
655#endif
656
658typedef uintptr_t CPU_Uint32ptr;
659
660#endif
661
662#ifdef __cplusplus
663}
664#endif
665
666#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:120
#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:167
void * _CPU_Thread_Idle_body(uintptr_t ignored)
Definition: m68kidle.c:39
void _CPU_Initialize(void)
CPU initialization.
Definition: cpu.c:47
uintptr_t CPU_Uint32ptr
Definition: cpu.h:611
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:108
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:500
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