source: rtems/cpukit/score/cpu/v850/include/rtems/score/cpu.h @ 48dd7b8c

Last change on this file since 48dd7b8c was 48dd7b8c, checked in by Kinsey Moore <kinsey.moore@…>, on 06/29/20 at 19:35:08

score: Add CPU_USE_LIBC_INIT_FINI_ARRAY

This introduces the CPU_USE_LIBC_INIT_FINI_ARRAY define for use by CPU
ports to determine which global constructor and destructor methods are
used instead of placing architecture defines where they shouldn't be.

Close #4018

  • Property mode set to 100644
File size: 20.2 KB
Line 
1/**
2 * @file
3 *
4 * @brief V850 CPU Department Source
5 *
6 * This include file contains information pertaining to the v850
7 * processor.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2012.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#ifndef _RTEMS_SCORE_CPU_H
20#define _RTEMS_SCORE_CPU_H
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26#include <rtems/score/basedefs.h>
27#include <rtems/score/v850.h>
28
29/* conditional compilation parameters */
30
31/**
32 * Does the CPU follow the simple vectored interrupt model?
33 *
34 * If TRUE, then RTEMS allocates the vector table it internally manages.
35 * If FALSE, then the BSP is assumed to allocate and manage the vector
36 * table
37 *
38 * Port Specific Information:
39 *
40 * This port uses the Progammable Interrupt Controller interrupt model.
41 */
42#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE
43
44#define CPU_HARDWARE_FP FALSE
45
46#define CPU_SOFTWARE_FP FALSE
47
48#define CPU_ALL_TASKS_ARE_FP FALSE
49
50#define CPU_IDLE_TASK_IS_FP FALSE
51
52#define CPU_USE_DEFERRED_FP_SWITCH FALSE
53
54#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
55
56/**
57 * Does the stack grow up (toward higher addresses) or down
58 * (toward lower addresses)?
59 *
60 * If TRUE, then the grows upward.
61 * If FALSE, then the grows toward smaller addresses.
62 *
63 * Port Specific Information:
64 *
65 * The v850 stack grows from high addresses to low addresses.
66 */
67#define CPU_STACK_GROWS_UP               FALSE
68
69/* FIXME: Is this the right value? */
70#define CPU_CACHE_LINE_BYTES 32
71
72#define CPU_STRUCTURE_ALIGNMENT
73
74/**
75 * @addtogroup RTEMSScoreCPUV850CPUInterrupt
76 * The following defines the number of bits actually used in the
77 * interrupt field of the task mode.  How those bits map to the
78 * CPU interrupt levels is defined by the routine @ref _CPU_ISR_Set_level.
79 *
80 * Port Specific Information:
81 *
82 * The v850 only has a single bit in the CPU for interrupt disable/enable.
83 */
84#define CPU_MODES_INTERRUPT_MASK   0x00000001
85
86#define CPU_MAXIMUM_PROCESSORS 32
87
88/**
89 * @defgroup RTEMSScoreCPUV850CPUContext Processor Dependent Context Management
90 *
91 * @ingroup RTEMSScoreCPUV850
92 *
93 * From the highest level viewpoint, there are 2 types of context to save.
94 *
95 *    -# Interrupt registers to save
96 *    -# Task level registers to save
97 *
98 * Since RTEMS handles integer and floating point contexts separately, this
99 * means we have the following 3 context items:
100 *
101 *    -# task level context stuff::  Context_Control
102 *    -# floating point task stuff:: Context_Control_fp
103 *    -# special interrupt level context :: CPU_Interrupt_frame
104 *
105 * On some processors, it is cost-effective to save only the callee
106 * preserved registers during a task context switch.  This means
107 * that the ISR code needs to save those registers which do not
108 * persist across function calls.  It is not mandatory to make this
109 * distinctions between the caller/callee saves registers for the
110 * purpose of minimizing context saved during task switch and on interrupts.
111 * If the cost of saving extra registers is minimal, simplicity is the
112 * choice.  Save the same context on interrupt entry as for tasks in
113 * this case.
114 *
115 * Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
116 * care should be used in designing the context area.
117 *
118 * On some CPUs with hardware floating point support, the Context_Control_fp
119 * structure will not be used or it simply consist of an array of a
120 * fixed number of bytes.   This is done when the floating point context
121 * is dumped by a "FP save context" type instruction and the format
122 * is not really defined by the CPU.  In this case, there is no need
123 * to figure out the exact format -- only the size.  Of course, although
124 * this is enough information for RTEMS, it is probably not enough for
125 * a debugger such as gdb.  But that is another problem.
126 *
127 * Port Specific Information:
128 *
129 * On the v850, this port saves special registers and those that are
130 * callee saved.
131 */
132/** @{ **/
133
134/**
135 * This defines the minimal set of integer and processor state registers
136 * that must be saved during a voluntary context switch from one thread
137 * to another.
138 */
139typedef struct {
140    uint32_t   r1;
141    /** This field is the stack pointer (e.g. r3).  */
142    uint32_t   r3_stack_pointer;
143    uint32_t   r20;
144    uint32_t   r21;
145    uint32_t   r22;
146    uint32_t   r23;
147    uint32_t   r24;
148    uint32_t   r25;
149    uint32_t   r26;
150    uint32_t   r27;
151    uint32_t   r28;
152    uint32_t   r29;
153    uint32_t   r31;
154    uint32_t   psw;
155} Context_Control;
156
157/**
158 * This macro returns the stack pointer associated with @a _context.
159 *
160 * @param[in] _context is the thread context area to access
161 *
162 * @return This method returns the stack pointer.
163 */
164#define _CPU_Context_Get_SP( _context ) \
165  (_context)->r3_stack_pointer
166
167/**
168 * This defines the set of integer and processor state registers that must
169 * be saved during an interrupt.  This set does not include any which are
170 * in @ref Context_Control.
171 */
172typedef struct {
173    /** This field is a hint that a port will have a number of integer
174     * registers that need to be saved when an interrupt occurs or
175     * when a context switch occurs at the end of an ISR.
176     */
177    uint32_t   special_interrupt_register;
178} CPU_Interrupt_frame;
179
180/** @} */
181
182/**
183 * @defgroup RTEMSScoreCPUV850CPUInterrupt Processor Dependent Interrupt Management
184 *
185 * @ingroup RTEMSScoreCPUV850
186 */
187/** @{ **/
188
189/**
190 * Amount of extra stack (above minimum stack size) required by
191 * MPCI receive server thread.  Remember that in a multiprocessor
192 * system this thread must exist and be able to process all directives.
193 *
194 * Port Specific Information:
195 *
196 * There is no reason to think the v850 needs extra MPCI receive
197 * server stack.
198 */
199#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
200
201/**
202 * This is defined if the port has a special way to report the ISR nesting
203 * level.  Most ports maintain the variable @a _ISR_Nest_level.
204 */
205#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
206
207/** @} */
208
209/**
210 * @addtogroup RTEMSScoreCPUV850CPUContext
211 * Should be large enough to run all RTEMS tests.  This ensures
212 * that a "reasonable" small application should not have any problems.
213 *
214 * Port Specific Information:
215 *
216 * This should be very conservative on the v850.
217 */
218#define CPU_STACK_MINIMUM_SIZE          (1024*4)
219
220#define CPU_SIZEOF_POINTER 4
221
222/**
223 * CPU's worst alignment requirement for data types on a byte boundary.  This
224 * alignment does not take into account the requirements for the stack.
225 *
226 * Port Specific Information:
227 *
228 * There is no apparent reason why this should be larger than 8.
229 */
230#define CPU_ALIGNMENT              8
231
232/**
233 * This number corresponds to the byte alignment requirement for the
234 * heap handler.  This alignment requirement may be stricter than that
235 * for the data types alignment specified by @ref CPU_ALIGNMENT.  It is
236 * common for the heap to follow the same alignment requirement as
237 * @ref CPU_ALIGNMENT.  If the @ref CPU_ALIGNMENT is strict enough for
238 * the heap, then this should be set to @ref CPU_ALIGNMENT.
239 *
240 * @note  This does not have to be a power of 2 although it should be
241 *        a multiple of 2 greater than or equal to 2.  The requirement
242 *        to be a multiple of 2 is because the heap uses the least
243 *        significant field of the front and back flags to indicate
244 *        that a block is in use or free.  So you do not want any odd
245 *        length blocks really putting length data in that bit.
246 *
247 *        On byte oriented architectures, @ref CPU_HEAP_ALIGNMENT normally will
248 *        have to be greater or equal to than @ref CPU_ALIGNMENT to ensure that
249 *        elements allocated from the heap meet all restrictions.
250 *
251 * Port Specific Information:
252 *
253 * There is no apparent reason why this should be larger than CPU_ALIGNMENT.
254 */
255#define CPU_HEAP_ALIGNMENT         CPU_ALIGNMENT
256
257/**
258 * This number corresponds to the byte alignment requirement for the
259 * stack.  This alignment requirement may be stricter than that for the
260 * data types alignment specified by @ref CPU_ALIGNMENT.  If the
261 * @ref CPU_ALIGNMENT is strict enough for the stack, then this should be
262 * set to 0.
263 *
264 * @note This must be a power of 2 either 0 or greater than @ref CPU_ALIGNMENT.
265 *
266 * Port Specific Information:
267 *
268 * The v850 has enough RAM where alignment to 16 may be desirable depending
269 * on the cache properties. But this remains to be demonstrated.
270 */
271#define CPU_STACK_ALIGNMENT        4
272
273#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
274
275/*
276 *  ISR handler macros
277 */
278
279/**
280 * @addtogroup RTEMSScoreCPUV850CPUInterrupt
281 */
282/** @{ **/
283
284/**
285 * Disable all interrupts for an RTEMS critical section.  The previous
286 * level is returned in @a _isr_cookie.
287 *
288 * @param[out] _isr_cookie will contain the previous level cookie
289 *
290 * Port Specific Information:
291 *
292 * On the v850, we need to save the PSW and use "di" to disable interrupts.
293 */
294#define _CPU_ISR_Disable( _isr_cookie ) \
295  do { \
296    unsigned int _psw; \
297    \
298    v850_get_psw( _psw ); \
299    __asm__ __volatile__( "di" ); \
300    _isr_cookie = _psw; \
301  } while (0)
302
303/**
304 * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
305 * This indicates the end of an RTEMS critical section.  The parameter
306 * @a _isr_cookie is not modified.
307 *
308 * @param[in] _isr_cookie contain the previous level cookie
309 *
310 * Port Specific Information:
311 *
312 * On the v850, we simply need to restore the PSW.
313 */
314#define _CPU_ISR_Enable( _isr_cookie )  \
315  do { \
316    unsigned int _psw = (_isr_cookie); \
317    \
318    v850_set_psw( _psw ); \
319  } while (0)
320
321/**
322 * This temporarily restores the interrupt to @a _isr_cookie before immediately
323 * disabling them again.  This is used to divide long RTEMS critical
324 * sections into two or more parts.  The parameter @a _isr_cookie is not
325 * modified.
326 *
327 * @param[in] _isr_cookie contain the previous level cookie
328 *
329 * Port Specific Information:
330 *
331 * This saves at least one instruction over using enable/disable back to back.
332 */
333#define _CPU_ISR_Flash( _isr_cookie ) \
334  do { \
335    unsigned int _psw = (_isr_cookie); \
336    v850_set_psw( _psw ); \
337    __asm__ __volatile__( "di" ); \
338  } while (0)
339
340RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( uint32_t level )
341{
342  return ( level & V850_PSW_INTERRUPT_DISABLE_MASK )
343    != V850_PSW_INTERRUPT_DISABLE;
344}
345
346/**
347 * This routine and @ref _CPU_ISR_Get_level
348 * Map the interrupt level in task mode onto the hardware that the CPU
349 * actually provides.  Currently, interrupt levels which do not
350 * map onto the CPU in a generic fashion are undefined.  Someday,
351 * it would be nice if these were "mapped" by the application
352 * via a callout.  For example, m68k has 8 levels 0 - 7, levels
353 * 8 - 255 would be available for bsp/application specific meaning.
354 * This could be used to manage a programmable interrupt controller
355 * via the rtems_task_mode directive.
356 *
357 * Port Specific Information:
358 *
359 * On the v850, level 0 is enabled. Non-zero is disabled.
360 */
361#define _CPU_ISR_Set_level( new_level ) \
362  do { \
363    if ( new_level ) \
364      __asm__ __volatile__( "di" ); \
365    else \
366      __asm__ __volatile__( "ei" ); \
367  } while (0)
368
369/**
370 * Return the current interrupt disable level for this task in
371 * the format used by the interrupt level portion of the task mode.
372 *
373 * @note This routine usually must be implemented as a subroutine.
374 *
375 * Port Specific Information:
376 *
377 * This method is implemented in C on the v850.
378 */
379uint32_t   _CPU_ISR_Get_level( void );
380
381/* end of ISR handler macros */
382
383/** @} */
384
385/* Context handler macros */
386
387/**
388 * @addtogroup RTEMSScoreCPUV850CPUContext
389 * Initialize the context to a state suitable for starting a
390 * task after a context restore operation.  Generally, this
391 * involves:
392 *
393 *    - setting a starting address
394 *    - preparing the stack
395 *    - preparing the stack and frame pointers
396 *    - setting the proper interrupt level in the context
397 *    - initializing the floating point context
398 *
399 * This routine generally does not set any unnecessary register
400 * in the context.  The state of the "general data" registers is
401 * undefined at task start time.
402 *
403 * @param[in] _the_context is the context structure to be initialized
404 * @param[in] _stack_base is the lowest physical address of this task's stack
405 * @param[in] _size is the size of this task's stack
406 * @param[in] _isr is the interrupt disable level
407 * @param[in] _entry_point is the thread's entry point.  This is
408 *        always @a _Thread_Handler
409 * @param[in] _is_fp is TRUE if the thread is to be a floating
410 *       point thread.  This is typically only used on CPUs where the
411 *       FPU may be easily disabled by software such as on the SPARC
412 *       where the PSR contains an enable FPU bit.
413 * @param[in] tls_area is the thread-local storage (TLS) area
414 *
415 * Port Specific Information:
416 *
417 * This method is implemented in C on the v850.
418 */
419void _CPU_Context_Initialize(
420  Context_Control  *the_context,
421  uint32_t         *stack_base,
422  uint32_t          size,
423  uint32_t          new_level,
424  void             *entry_point,
425  bool              is_fp,
426  void             *tls_area
427);
428
429/**
430 * This routine is responsible for somehow restarting the currently
431 * executing task.  If you are lucky, then all that is necessary
432 * is restoring the context.  Otherwise, there will need to be
433 * a special assembly routine which does something special in this
434 * case.  For many ports, simply adding a label to the restore path
435 * of @ref _CPU_Context_switch will work.  On other ports, it may be
436 * possibly to load a few arguments and jump to the restore path. It will
437 * not work if restarting self conflicts with the stack frame
438 * assumptions of restoring a context.
439 *
440 * Port Specific Information:
441 *
442 * On the v850, we require a special entry point to restart a task.
443 */
444#define _CPU_Context_Restart_self( _the_context ) \
445   _CPU_Context_restore( (_the_context) );
446
447/* XXX this should be possible to remove */
448#if 0
449/**
450 * This routine initializes the FP context area passed to it to.
451 * There are a few standard ways in which to initialize the
452 * floating point context.  The code included for this macro assumes
453 * that this is a CPU in which a "initial" FP context was saved into
454 * @a _CPU_Null_fp_context and it simply copies it to the destination
455 * context passed to it.
456 *
457 * Other floating point context save/restore models include:
458 *   -# not doing anything, and
459 *   -# putting a "null FP status word" in the correct place in the FP context.
460 *
461 * @param[in] _destination is the floating point context area
462 *
463 * Port Specific Information:
464 *
465 * XXX document implementation including references if appropriate
466 */
467#define _CPU_Context_Initialize_fp( _destination ) \
468  { \
469  }
470#endif
471
472/* end of Context handler macros */
473
474/* Fatal Error manager macros */
475
476/**
477 * This routine copies _error into a known place -- typically a stack
478 * location or a register, optionally disables interrupts, and
479 * halts/stops the CPU.
480 *
481 * Port Specific Information:
482 *
483 * Move the error code into r10, disable interrupts and halt.
484 */
485#define _CPU_Fatal_halt( _source, _error ) \
486  do { \
487    __asm__ __volatile__ ( "di" ); \
488    __asm__ __volatile__ ( "mov %0, r10; " : "=r" ((_error)) ); \
489    __asm__ __volatile__ ( "halt" ); \
490  } while (0)
491
492/* end of Fatal Error manager macros */
493
494#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
495
496#define CPU_USE_LIBC_INIT_FINI_ARRAY FALSE
497
498/* functions */
499
500/**
501 * @brief CPU initialize.
502 * This routine performs CPU dependent initialization.
503 *
504 * Port Specific Information:
505 *
506 * This is implemented in C.
507 *
508 * v850 CPU Dependent Source
509 */
510void _CPU_Initialize(void);
511
512void *_CPU_Thread_Idle_body( uintptr_t ignored );
513
514/**
515 * @addtogroup RTEMSScoreCPUV850CPUContext
516 */
517/**@{**/
518
519/**
520 * This routine switches from the run context to the heir context.
521 *
522 * @param[in] run points to the context of the currently executing task
523 * @param[in] heir points to the context of the heir task
524 *
525 * Port Specific Information:
526 *
527 * This is implemented in assembly on the v850.
528 */
529void _CPU_Context_switch(
530  Context_Control  *run,
531  Context_Control  *heir
532);
533
534/**
535 * This routine is generally used only to restart self in an
536 * efficient manner.  It may simply be a label in @ref _CPU_Context_switch.
537 *
538 * @param[in] new_context points to the context to be restored.
539 *
540 * @note May be unnecessary to reload some registers.
541 *
542 * Port Specific Information:
543 *
544 * This is implemented in assembly on the v850.
545 */
546void _CPU_Context_restore(
547  Context_Control *new_context
548) RTEMS_NO_RETURN;
549
550/* XXX this should be possible to remove */
551#if 0
552/**
553 * This routine saves the floating point context passed to it.
554 *
555 * @param[in] fp_context_ptr is a pointer to a pointer to a floating
556 * point context area
557 *
558 * @return on output @a *fp_context_ptr will contain the address that
559 * should be used with @ref _CPU_Context_restore_fp to restore this context.
560 *
561 * Port Specific Information:
562 *
563 * XXX document implementation including references if appropriate
564 */
565void _CPU_Context_save_fp(
566  Context_Control_fp **fp_context_ptr
567);
568#endif
569
570/* XXX this should be possible to remove */
571#if 0
572/**
573 * This routine restores the floating point context passed to it.
574 *
575 * @param[in] fp_context_ptr is a pointer to a pointer to a floating
576 * point context area to restore
577 *
578 * @return on output @a *fp_context_ptr will contain the address that
579 * should be used with @ref _CPU_Context_save_fp to save this context.
580 *
581 * Port Specific Information:
582 *
583 * XXX document implementation including references if appropriate
584 */
585void _CPU_Context_restore_fp(
586  Context_Control_fp **fp_context_ptr
587);
588#endif
589
590/** @} */
591
592/* FIXME */
593typedef CPU_Interrupt_frame CPU_Exception_frame;
594
595void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
596
597/**
598 * @defgroup RTEMSScoreCPUV850CPUEndian CPUEndian
599 *
600 * @ingroup RTEMSScoreCPUV850
601 *
602 * @brief CPUEndian
603 */
604/** @{ */
605
606/**
607 * The following routine swaps the endian format of an unsigned int.
608 * It must be static because it is referenced indirectly.
609 *
610 * This version will work on any processor, but if there is a better
611 * way for your CPU PLEASE use it.  The most common way to do this is to:
612 *
613 *    swap least significant two bytes with 16-bit rotate
614 *    swap upper and lower 16-bits
615 *    swap most significant two bytes with 16-bit rotate
616 *
617 * Some CPUs have special instructions which swap a 32-bit quantity in
618 * a single instruction (e.g. i486).  It is probably best to avoid
619 * an "endian swapping control bit" in the CPU.  One good reason is
620 * that interrupts would probably have to be disabled to ensure that
621 * an interrupt does not try to access the same "chunk" with the wrong
622 * endian.  Another good reason is that on some CPUs, the endian bit
623 * endianness for ALL fetches -- both code and data -- so the code
624 * will be fetched incorrectly.
625 *
626 * @param[in] value is the value to be swapped
627 * @return the value after being endian swapped
628 *
629 * Port Specific Information:
630 *
631 * The v850 has a single instruction to swap endianness on a 32 bit quantity.
632 */
633static inline uint32_t CPU_swap_u32(
634  uint32_t value
635)
636{
637  unsigned int swapped;
638
639  #if (V850_HAS_BYTE_SWAP_INSTRUCTION == 1)
640    unsigned int v;
641
642    v = value;
643    __asm__ __volatile__ ("bsw %0, %1" : "=r" (v), "=&r" (swapped) );
644  #else
645    uint32_t byte1, byte2, byte3, byte4;
646
647    byte4 = (value >> 24) & 0xff;
648    byte3 = (value >> 16) & 0xff;
649    byte2 = (value >> 8)  & 0xff;
650    byte1 =  value        & 0xff;
651
652    swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
653  #endif
654  return swapped;
655}
656
657/**
658 * This routine swaps a 16 bir quantity.
659 *
660 * @param[in] value is the value to be swapped
661 * @return the value after being endian swapped
662 *
663 * Port Specific Information:
664 *
665 * The v850 has a single instruction to swap endianness on a 16 bit quantity.
666 */
667static inline uint16_t CPU_swap_u16( uint16_t value )
668{
669  unsigned int swapped;
670
671  #if (V850_HAS_BYTE_SWAP_INSTRUCTION == 1)
672    unsigned int v;
673
674    v = value;
675    __asm__ __volatile__ ("bsh %0, %1" : "=r" (v), "=&r" (swapped) );
676  #else
677    swapped = ((value & 0xff) << 8) | ((value >> 8) & 0xff);
678  #endif
679  return swapped;
680}
681
682/** @} */
683
684typedef uint32_t CPU_Counter_ticks;
685
686uint32_t _CPU_Counter_frequency( void );
687
688CPU_Counter_ticks _CPU_Counter_read( void );
689
690static inline CPU_Counter_ticks _CPU_Counter_difference(
691  CPU_Counter_ticks second,
692  CPU_Counter_ticks first
693)
694{
695  return second - first;
696}
697
698/** Type that can store a 32-bit integer or a pointer. */
699typedef uintptr_t CPU_Uint32ptr;
700
701#ifdef __cplusplus
702}
703#endif
704
705#endif
Note: See TracBrowser for help on using the repository browser.