source: rtems/cpukit/score/cpu/sparc/rtems/score/cpu.h @ 35a3af7a

4.115
Last change on this file since 35a3af7a was 38b59a6, checked in by Sebastian Huber <sebastian.huber@…>, on 05/02/14 at 08:31:09

score: Implement forced thread migration

The current implementation of task migration in RTEMS has some
implications with respect to the interrupt latency. It is crucial to
preserve the system invariant that a task can execute on at most one
processor in the system at a time. This is accomplished with a boolean
indicator in the task context. The processor architecture specific
low-level task context switch code will mark that a task context is no
longer executing and waits that the heir context stopped execution
before it restores the heir context and resumes execution of the heir
task. So there is one point in time in which a processor is without a
task. This is essential to avoid cyclic dependencies in case multiple
tasks migrate at once. Otherwise some supervising entity is necessary to
prevent life-locks. Such a global supervisor would lead to scalability
problems so this approach is not used. Currently the thread dispatch is
performed with interrupts disabled. So in case the heir task is
currently executing on another processor then this prolongs the time of
disabled interrupts since one processor has to wait for another
processor to make progress.

It is difficult to avoid this issue with the interrupt latency since
interrupts normally store the context of the interrupted task on its
stack. In case a task is marked as not executing we must not use its
task stack to store such an interrupt context. We cannot use the heir
stack before it stopped execution on another processor. So if we enable
interrupts during this transition we have to provide an alternative task
independent stack for this time frame. This issue needs further
investigation.

  • Property mode set to 100644
File size: 46.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief SPARC CPU Department Source
5 *
6 * This include file contains information pertaining to the port of
7 * the executive to the SPARC processor.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2011.
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/types.h>
27#include <rtems/score/sparc.h>
28
29/* conditional compilation parameters */
30
31/**
32 * Should the calls to _Thread_Enable_dispatch be inlined?
33 *
34 * - If TRUE, then they are inlined.
35 * - If FALSE, then a subroutine call is made.
36 *
37 * On this port, it is faster to inline _Thread_Enable_dispatch.
38 */
39#define CPU_INLINE_ENABLE_DISPATCH       TRUE
40
41/**
42 * Should the body of the search loops in _Thread_queue_Enqueue_priority
43 * be unrolled one time?  In unrolled each iteration of the loop examines
44 * two "nodes" on the chain being searched.  Otherwise, only one node
45 * is examined per iteration.
46 *
47 * - If TRUE, then the loops are unrolled.
48 * - If FALSE, then the loops are not unrolled.
49 *
50 * This parameter could go either way on the SPARC.  The interrupt flash
51 * code is relatively lengthy given the requirements for nops following
52 * writes to the psr.  But if the clock speed were high enough, this would
53 * not represent a great deal of time.
54 */
55#define CPU_UNROLL_ENQUEUE_PRIORITY      TRUE
56
57/**
58 * Does the executive manage a dedicated interrupt stack in software?
59 *
60 * If TRUE, then a stack is allocated in _ISR_Handler_initialization.
61 * If FALSE, nothing is done.
62 *
63 * The SPARC does not have a dedicated HW interrupt stack and one has
64 * been implemented in SW.
65 */
66#define CPU_HAS_SOFTWARE_INTERRUPT_STACK   TRUE
67
68/**
69 * Does the CPU follow the simple vectored interrupt model?
70 *
71 * - If TRUE, then RTEMS allocates the vector table it internally manages.
72 * - If FALSE, then the BSP is assumed to allocate and manage the vector
73 *   table
74 *
75 * THe SPARC is a simple vectored architecture.  Usually there is no
76 * PIC and the CPU directly vectors the interrupts.
77 */
78#define CPU_SIMPLE_VECTORED_INTERRUPTS TRUE
79
80/**
81 * Does this CPU have hardware support for a dedicated interrupt stack?
82 *
83 * - If TRUE, then it must be installed during initialization.
84 * - If FALSE, then no installation is performed.
85 *
86 * The SPARC does not have a dedicated HW interrupt stack.
87 */
88#define CPU_HAS_HARDWARE_INTERRUPT_STACK  FALSE
89
90/**
91 * Do we allocate a dedicated interrupt stack in the Interrupt Manager?
92 *
93 * - If TRUE, then the memory is allocated during initialization.
94 * - If FALSE, then the memory is allocated during initialization.
95 *
96 * The SPARC does not have hardware support for switching to a
97 * dedicated interrupt stack.  The port includes support for doing this
98 * in software.
99 *
100 */
101#define CPU_ALLOCATE_INTERRUPT_STACK      TRUE
102
103/**
104 * Does the RTEMS invoke the user's ISR with the vector number and
105 * a pointer to the saved interrupt frame (1) or just the vector
106 * number (0)?
107 *
108 * The SPARC port does not pass an Interrupt Stack Frame pointer to
109 * interrupt handlers.
110 */
111#define CPU_ISR_PASSES_FRAME_POINTER 0
112
113/**
114 * Does the CPU have hardware floating point?
115 *
116 * - If TRUE, then the FLOATING_POINT task attribute is supported.
117 * - If FALSE, then the FLOATING_POINT task attribute is ignored.
118 *
119 * This is set based upon the multilib settings.
120 */
121#if ( SPARC_HAS_FPU == 1 )
122  #define CPU_HARDWARE_FP     TRUE
123#else
124  #define CPU_HARDWARE_FP     FALSE
125#endif
126
127/**
128 * The SPARC GCC port does not have a software floating point library
129 * that requires RTEMS assistance.
130 */
131#define CPU_SOFTWARE_FP     FALSE
132
133/**
134 * Are all tasks FLOATING_POINT tasks implicitly?
135 *
136 * - If TRUE, then the FLOATING_POINT task attribute is assumed.
137 * - If FALSE, then the FLOATING_POINT task attribute is followed.
138 *
139 * The SPARC GCC port does not implicitly use floating point registers.
140 */
141#define CPU_ALL_TASKS_ARE_FP     FALSE
142
143/**
144 * Should the IDLE task have a floating point context?
145 *
146 * - If TRUE, then the IDLE task is created as a FLOATING_POINT task
147 *   and it has a floating point context which is switched in and out.
148 * - If FALSE, then the IDLE task does not have a floating point context.
149 *
150 * The IDLE task does not have to be floating point on the SPARC.
151 */
152#define CPU_IDLE_TASK_IS_FP      FALSE
153
154/**
155 * Should the saving of the floating point registers be deferred
156 * until a context switch is made to another different floating point
157 * task?
158 *
159 * - If TRUE, then the floating point context will not be stored until
160 * necessary.  It will remain in the floating point registers and not
161 * disturned until another floating point task is switched to.
162 *
163 * - If FALSE, then the floating point context is saved when a floating
164 * point task is switched out and restored when the next floating point
165 * task is restored.  The state of the floating point registers between
166 * those two operations is not specified.
167 *
168 * On the SPARC, we can disable the FPU for integer only tasks so
169 * it is safe to defer floating point context switches.
170 */
171#if defined(RTEMS_SMP)
172  #define CPU_USE_DEFERRED_FP_SWITCH FALSE
173#else
174  #define CPU_USE_DEFERRED_FP_SWITCH TRUE
175#endif
176
177/**
178 * Does this port provide a CPU dependent IDLE task implementation?
179 *
180 * - If TRUE, then the routine _CPU_Thread_Idle_body
181 * must be provided and is the default IDLE thread body instead of
182 * _CPU_Thread_Idle_body.
183 *
184 * - If FALSE, then use the generic IDLE thread body if the BSP does
185 * not provide one.
186 *
187 * The SPARC architecture does not have a low power or halt instruction.
188 * It is left to the BSP and/or CPU specific code to provide an IDLE
189 * thread body which is aware of low power modes.
190 */
191#define CPU_PROVIDES_IDLE_THREAD_BODY    FALSE
192
193/**
194 * Does the stack grow up (toward higher addresses) or down
195 * (toward lower addresses)?
196 *
197 * - If TRUE, then the grows upward.
198 * - If FALSE, then the grows toward smaller addresses.
199 *
200 * The stack grows to lower addresses on the SPARC.
201 */
202#define CPU_STACK_GROWS_UP               FALSE
203
204/**
205 * The following is the variable attribute used to force alignment
206 * of critical data structures.  On some processors it may make
207 * sense to have these aligned on tighter boundaries than
208 * the minimum requirements of the compiler in order to have as
209 * much of the critical data area as possible in a cache line.
210 *
211 * The SPARC does not appear to have particularly strict alignment
212 * requirements.  This value was chosen to take advantages of caches.
213 */
214#define CPU_STRUCTURE_ALIGNMENT          __attribute__ ((aligned (32)))
215
216#define CPU_TIMESTAMP_USE_INT64_INLINE TRUE
217
218/**
219 * Define what is required to specify how the network to host conversion
220 * routines are handled.
221 *
222 * The SPARC is big endian.
223 */
224#define CPU_BIG_ENDIAN                           TRUE
225
226/**
227 * Define what is required to specify how the network to host conversion
228 * routines are handled.
229 *
230 * The SPARC is NOT little endian.
231 */
232#define CPU_LITTLE_ENDIAN                        FALSE
233
234/**
235 * The following defines the number of bits actually used in the
236 * interrupt field of the task mode.  How those bits map to the
237 * CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
238 *
239 * The SPARC has 16 interrupt levels in the PIL field of the PSR.
240 */
241#define CPU_MODES_INTERRUPT_MASK   0x0000000F
242
243#ifndef ASM
244/**
245 * This structure represents the organization of the minimum stack frame
246 * for the SPARC.  More framing information is required in certain situaions
247 * such as when there are a large number of out parameters or when the callee
248 * must save floating point registers.
249 */
250typedef struct {
251  /** This is the offset of the l0 register. */
252  uint32_t    l0;
253  /** This is the offset of the l1 register. */
254  uint32_t    l1;
255  /** This is the offset of the l2 register. */
256  uint32_t    l2;
257  /** This is the offset of the l3 register. */
258  uint32_t    l3;
259  /** This is the offset of the l4 register. */
260  uint32_t    l4;
261  /** This is the offset of the l5 register. */
262  uint32_t    l5;
263  /** This is the offset of the l6 register. */
264  uint32_t    l6;
265  /** This is the offset of the l7 register. */
266  uint32_t    l7;
267  /** This is the offset of the l0 register. */
268  uint32_t    i0;
269  /** This is the offset of the i1 register. */
270  uint32_t    i1;
271  /** This is the offset of the i2 register. */
272  uint32_t    i2;
273  /** This is the offset of the i3 register. */
274  uint32_t    i3;
275  /** This is the offset of the i4 register. */
276  uint32_t    i4;
277  /** This is the offset of the i5 register. */
278  uint32_t    i5;
279  /** This is the offset of the i6 register. */
280  uint32_t    i6_fp;
281  /** This is the offset of the i7 register. */
282  uint32_t    i7;
283  /** This is the offset of the register used to return structures. */
284  void       *structure_return_address;
285
286  /*
287   * The following are for the callee to save the register arguments in
288   * should this be necessary.
289   */
290  /** This is the offset of the register for saved argument 0. */
291  uint32_t    saved_arg0;
292  /** This is the offset of the register for saved argument 1. */
293  uint32_t    saved_arg1;
294  /** This is the offset of the register for saved argument 2. */
295  uint32_t    saved_arg2;
296  /** This is the offset of the register for saved argument 3. */
297  uint32_t    saved_arg3;
298  /** This is the offset of the register for saved argument 4. */
299  uint32_t    saved_arg4;
300  /** This is the offset of the register for saved argument 5. */
301  uint32_t    saved_arg5;
302  /** This field pads the structure so ldd and std instructions can be used. */
303  uint32_t    pad0;
304}  CPU_Minimum_stack_frame;
305
306#endif /* ASM */
307
308/** This macro defines an offset into the stack frame for use in assembly. */
309#define CPU_STACK_FRAME_L0_OFFSET             0x00
310/** This macro defines an offset into the stack frame for use in assembly. */
311#define CPU_STACK_FRAME_L1_OFFSET             0x04
312/** This macro defines an offset into the stack frame for use in assembly. */
313#define CPU_STACK_FRAME_L2_OFFSET             0x08
314/** This macro defines an offset into the stack frame for use in assembly. */
315#define CPU_STACK_FRAME_L3_OFFSET             0x0c
316/** This macro defines an offset into the stack frame for use in assembly. */
317#define CPU_STACK_FRAME_L4_OFFSET             0x10
318/** This macro defines an offset into the stack frame for use in assembly. */
319#define CPU_STACK_FRAME_L5_OFFSET             0x14
320/** This macro defines an offset into the stack frame for use in assembly. */
321#define CPU_STACK_FRAME_L6_OFFSET             0x18
322/** This macro defines an offset into the stack frame for use in assembly. */
323#define CPU_STACK_FRAME_L7_OFFSET             0x1c
324/** This macro defines an offset into the stack frame for use in assembly. */
325#define CPU_STACK_FRAME_I0_OFFSET             0x20
326/** This macro defines an offset into the stack frame for use in assembly. */
327#define CPU_STACK_FRAME_I1_OFFSET             0x24
328/** This macro defines an offset into the stack frame for use in assembly. */
329#define CPU_STACK_FRAME_I2_OFFSET             0x28
330/** This macro defines an offset into the stack frame for use in assembly. */
331#define CPU_STACK_FRAME_I3_OFFSET             0x2c
332/** This macro defines an offset into the stack frame for use in assembly. */
333#define CPU_STACK_FRAME_I4_OFFSET             0x30
334/** This macro defines an offset into the stack frame for use in assembly. */
335#define CPU_STACK_FRAME_I5_OFFSET             0x34
336/** This macro defines an offset into the stack frame for use in assembly. */
337#define CPU_STACK_FRAME_I6_FP_OFFSET          0x38
338/** This macro defines an offset into the stack frame for use in assembly. */
339#define CPU_STACK_FRAME_I7_OFFSET             0x3c
340/** This macro defines an offset into the stack frame for use in assembly. */
341#define CPU_STRUCTURE_RETURN_ADDRESS_OFFSET   0x40
342/** This macro defines an offset into the stack frame for use in assembly. */
343#define CPU_STACK_FRAME_SAVED_ARG0_OFFSET     0x44
344/** This macro defines an offset into the stack frame for use in assembly. */
345#define CPU_STACK_FRAME_SAVED_ARG1_OFFSET     0x48
346/** This macro defines an offset into the stack frame for use in assembly. */
347#define CPU_STACK_FRAME_SAVED_ARG2_OFFSET     0x4c
348/** This macro defines an offset into the stack frame for use in assembly. */
349#define CPU_STACK_FRAME_SAVED_ARG3_OFFSET     0x50
350/** This macro defines an offset into the stack frame for use in assembly. */
351#define CPU_STACK_FRAME_SAVED_ARG4_OFFSET     0x54
352/** This macro defines an offset into the stack frame for use in assembly. */
353#define CPU_STACK_FRAME_SAVED_ARG5_OFFSET     0x58
354/** This macro defines an offset into the stack frame for use in assembly. */
355#define CPU_STACK_FRAME_PAD0_OFFSET           0x5c
356
357/** This defines the size of the minimum stack frame. */
358#define CPU_MINIMUM_STACK_FRAME_SIZE          0x60
359
360#define CPU_PER_CPU_CONTROL_SIZE 4
361
362/**
363 * @brief Offset of the CPU_Per_CPU_control::isr_dispatch_disable field
364 * relative to the Per_CPU_Control begin.
365 */
366#define SPARC_PER_CPU_ISR_DISPATCH_DISABLE 0
367
368/**
369 * @defgroup Contexts SPARC Context Structures
370 *
371 * @ingroup Score
372 *
373 * Generally there are 2 types of context to save.
374 *    + Interrupt registers to save
375 *    + Task level registers to save
376 *
377 * This means we have the following 3 context items:
378 *    + task level context stuff::  Context_Control
379 *    + floating point task stuff:: Context_Control_fp
380 *    + special interrupt level context :: Context_Control_interrupt
381 *
382 * On the SPARC, we are relatively conservative in that we save most
383 * of the CPU state in the context area.  The ET (enable trap) bit and
384 * the CWP (current window pointer) fields of the PSR are considered
385 * system wide resources and are not maintained on a per-thread basis.
386 */
387/**@{**/
388
389#ifndef ASM
390
391typedef struct {
392  /**
393   * This flag is context switched with each thread.  It indicates
394   * that THIS thread has an _ISR_Dispatch stack frame on its stack.
395   * By using this flag, we can avoid nesting more interrupt dispatching
396   * attempts on a previously interrupted thread's stack.
397   */
398  uint32_t isr_dispatch_disable;
399} CPU_Per_CPU_control;
400
401/**
402 * @brief SPARC basic context.
403 *
404 * This structure defines the non-volatile integer and processor state context
405 * for the SPARC architecture according to "SYSTEM V APPLICATION BINARY
406 * INTERFACE - SPARC Processor Supplement", Third Edition.
407 *
408 * The registers g2 through g4 are reserved for applications.  GCC uses them as
409 * volatile registers by default.  So they are treated like volatile registers
410 * in RTEMS as well.
411 *
412 * The register g6 contains the per-CPU control of the current processor.  It
413 * is an invariant of the processor context.  This register must not be saved
414 * and restored during context switches or interrupt services.
415 */
416typedef struct {
417  /** This will contain the contents of the g5 register. */
418  uint32_t   g5;
419  /** This will contain the contents of the g7 register. */
420  uint32_t   g7;
421
422  /**
423   * This will contain the contents of the l0 and l1 registers.
424   *
425   * Using a double l0_and_l1 will put everything in this structure on a double
426   * word boundary which allows us to use double word loads and stores safely
427   * in the context switch.
428   */
429  double     l0_and_l1;
430  /** This will contain the contents of the l2 register. */
431  uint32_t   l2;
432  /** This will contain the contents of the l3 register. */
433  uint32_t   l3;
434  /** This will contain the contents of the l4 register. */
435  uint32_t   l4;
436  /** This will contain the contents of the l5 registeer.*/
437  uint32_t   l5;
438  /** This will contain the contents of the l6 register. */
439  uint32_t   l6;
440  /** This will contain the contents of the l7 register. */
441  uint32_t   l7;
442
443  /** This will contain the contents of the i0 register. */
444  uint32_t   i0;
445  /** This will contain the contents of the i1 register. */
446  uint32_t   i1;
447  /** This will contain the contents of the i2 register. */
448  uint32_t   i2;
449  /** This will contain the contents of the i3 register. */
450  uint32_t   i3;
451  /** This will contain the contents of the i4 register. */
452  uint32_t   i4;
453  /** This will contain the contents of the i5 register. */
454  uint32_t   i5;
455  /** This will contain the contents of the i6 (e.g. frame pointer) register. */
456  uint32_t   i6_fp;
457  /** This will contain the contents of the i7 register. */
458  uint32_t   i7;
459
460  /** This will contain the contents of the o6 (e.g. frame pointer) register. */
461  uint32_t   o6_sp;
462  /**
463   * This will contain the contents of the o7 (e.g. address of CALL
464   * instruction) register.
465   */
466  uint32_t   o7;
467
468  /** This will contain the contents of the processor status register. */
469  uint32_t   psr;
470  /**
471   * This field is used to prevent heavy nesting of calls to _Thread_Dispatch
472   * on an interrupted  task's stack.  This is problematic on the slower
473   * SPARC CPU models at high interrupt rates.
474   */
475  uint32_t   isr_dispatch_disable;
476
477#if defined(RTEMS_SMP)
478  volatile bool is_executing;
479#endif
480} Context_Control;
481
482/**
483 * This macro provides a CPU independent way for RTEMS to access the
484 * stack pointer in a context structure. The actual name and offset is
485 * CPU architecture dependent.
486 */
487#define _CPU_Context_Get_SP( _context ) \
488  (_context)->o6_sp
489
490#ifdef RTEMS_SMP
491  #define _CPU_Context_Get_is_executing( _context ) \
492    (_context)->is_executing
493#endif
494
495#endif /* ASM */
496
497/*
498 *  Offsets of fields with Context_Control for assembly routines.
499 */
500
501/** This macro defines an offset into the context for use in assembly. */
502#define G5_OFFSET    0x00
503/** This macro defines an offset into the context for use in assembly. */
504#define G7_OFFSET    0x04
505
506/** This macro defines an offset into the context for use in assembly. */
507#define L0_OFFSET    0x08
508/** This macro defines an offset into the context for use in assembly. */
509#define L1_OFFSET    0x0C
510/** This macro defines an offset into the context for use in assembly. */
511#define L2_OFFSET    0x10
512/** This macro defines an offset into the context for use in assembly. */
513#define L3_OFFSET    0x14
514/** This macro defines an offset into the context for use in assembly. */
515#define L4_OFFSET    0x18
516/** This macro defines an offset into the context for use in assembly. */
517#define L5_OFFSET    0x1C
518/** This macro defines an offset into the context for use in assembly. */
519#define L6_OFFSET    0x20
520/** This macro defines an offset into the context for use in assembly. */
521#define L7_OFFSET    0x24
522
523/** This macro defines an offset into the context for use in assembly. */
524#define I0_OFFSET    0x28
525/** This macro defines an offset into the context for use in assembly. */
526#define I1_OFFSET    0x2C
527/** This macro defines an offset into the context for use in assembly. */
528#define I2_OFFSET    0x30
529/** This macro defines an offset into the context for use in assembly. */
530#define I3_OFFSET    0x34
531/** This macro defines an offset into the context for use in assembly. */
532#define I4_OFFSET    0x38
533/** This macro defines an offset into the context for use in assembly. */
534#define I5_OFFSET    0x3C
535/** This macro defines an offset into the context for use in assembly. */
536#define I6_FP_OFFSET 0x40
537/** This macro defines an offset into the context for use in assembly. */
538#define I7_OFFSET    0x44
539
540/** This macro defines an offset into the context for use in assembly. */
541#define O6_SP_OFFSET 0x48
542/** This macro defines an offset into the context for use in assembly. */
543#define O7_OFFSET    0x4C
544
545/** This macro defines an offset into the context for use in assembly. */
546#define PSR_OFFSET   0x50
547/** This macro defines an offset into the context for use in assembly. */
548#define ISR_DISPATCH_DISABLE_STACK_OFFSET 0x54
549
550#if defined(RTEMS_SMP)
551  #define SPARC_CONTEXT_CONTROL_IS_EXECUTING_OFFSET 0x58
552#endif
553
554/** This defines the size of the context area for use in assembly. */
555#define CONTEXT_CONTROL_SIZE 0x68
556
557#ifndef ASM
558/**
559 * @brief SPARC basic context.
560 *
561 * This structure defines floating point context area.
562 */
563typedef struct {
564  /** This will contain the contents of the f0 and f1 register. */
565  double      f0_f1;
566  /** This will contain the contents of the f2 and f3 register. */
567  double      f2_f3;
568  /** This will contain the contents of the f4 and f5 register. */
569  double      f4_f5;
570  /** This will contain the contents of the f6 and f7 register. */
571  double      f6_f7;
572  /** This will contain the contents of the f8 and f9 register. */
573  double      f8_f9;
574  /** This will contain the contents of the f10 and f11 register. */
575  double      f10_f11;
576  /** This will contain the contents of the f12 and f13 register. */
577  double      f12_f13;
578  /** This will contain the contents of the f14 and f15 register. */
579  double      f14_f15;
580  /** This will contain the contents of the f16 and f17 register. */
581  double      f16_f17;
582  /** This will contain the contents of the f18 and f19 register. */
583  double      f18_f19;
584  /** This will contain the contents of the f20 and f21 register. */
585  double      f20_f21;
586  /** This will contain the contents of the f22 and f23 register. */
587  double      f22_f23;
588  /** This will contain the contents of the f24 and f25 register. */
589  double      f24_f25;
590  /** This will contain the contents of the f26 and f27 register. */
591  double      f26_f27;
592  /** This will contain the contents of the f28 and f29 register. */
593  double      f28_f29;
594  /** This will contain the contents of the f30 and f31 register. */
595  double      f30_f31;
596  /** This will contain the contents of the floating point status register. */
597  uint32_t    fsr;
598} Context_Control_fp;
599
600#endif /* ASM */
601
602/*
603 *  Offsets of fields with Context_Control_fp for assembly routines.
604 */
605
606/** This macro defines an offset into the FPU context for use in assembly. */
607#define FO_F1_OFFSET     0x00
608/** This macro defines an offset into the FPU context for use in assembly. */
609#define F2_F3_OFFSET     0x08
610/** This macro defines an offset into the FPU context for use in assembly. */
611#define F4_F5_OFFSET     0x10
612/** This macro defines an offset into the FPU context for use in assembly. */
613#define F6_F7_OFFSET     0x18
614/** This macro defines an offset into the FPU context for use in assembly. */
615#define F8_F9_OFFSET     0x20
616/** This macro defines an offset into the FPU context for use in assembly. */
617#define F1O_F11_OFFSET   0x28
618/** This macro defines an offset into the FPU context for use in assembly. */
619#define F12_F13_OFFSET   0x30
620/** This macro defines an offset into the FPU context for use in assembly. */
621#define F14_F15_OFFSET   0x38
622/** This macro defines an offset into the FPU context for use in assembly. */
623#define F16_F17_OFFSET   0x40
624/** This macro defines an offset into the FPU context for use in assembly. */
625#define F18_F19_OFFSET   0x48
626/** This macro defines an offset into the FPU context for use in assembly. */
627#define F2O_F21_OFFSET   0x50
628/** This macro defines an offset into the FPU context for use in assembly. */
629#define F22_F23_OFFSET   0x58
630/** This macro defines an offset into the FPU context for use in assembly. */
631#define F24_F25_OFFSET   0x60
632/** This macro defines an offset into the FPU context for use in assembly. */
633#define F26_F27_OFFSET   0x68
634/** This macro defines an offset into the FPU context for use in assembly. */
635#define F28_F29_OFFSET   0x70
636/** This macro defines an offset into the FPU context for use in assembly. */
637#define F3O_F31_OFFSET   0x78
638/** This macro defines an offset into the FPU context for use in assembly. */
639#define FSR_OFFSET       0x80
640
641/** This defines the size of the FPU context area for use in assembly. */
642#define CONTEXT_CONTROL_FP_SIZE 0x84
643
644#ifndef ASM
645
646/** @} */
647
648/**
649 * @brief Interrupt stack frame (ISF).
650 *
651 * Context saved on stack for an interrupt.
652 *
653 * NOTE: The PSR, PC, and NPC are only saved in this structure for the
654 *       benefit of the user's handler.
655 */
656typedef struct {
657  /** On an interrupt, we must save the minimum stack frame. */
658  CPU_Minimum_stack_frame  Stack_frame;
659  /** This is the offset of the PSR on an ISF. */
660  uint32_t                 psr;
661  /** This is the offset of the XXX on an ISF. */
662  uint32_t                 pc;
663  /** This is the offset of the XXX on an ISF. */
664  uint32_t                 npc;
665  /** This is the offset of the g1 register on an ISF. */
666  uint32_t                 g1;
667  /** This is the offset of the g2 register on an ISF. */
668  uint32_t                 g2;
669  /** This is the offset of the g3 register on an ISF. */
670  uint32_t                 g3;
671  /** This is the offset of the g4 register on an ISF. */
672  uint32_t                 g4;
673  /** This is the offset of the g5 register on an ISF. */
674  uint32_t                 g5;
675  /** This is the offset is reserved for alignment on an ISF. */
676  uint32_t                 reserved_for_alignment;
677  /** This is the offset of the g7 register on an ISF. */
678  uint32_t                 g7;
679  /** This is the offset of the i0 register on an ISF. */
680  uint32_t                 i0;
681  /** This is the offset of the i1 register on an ISF. */
682  uint32_t                 i1;
683  /** This is the offset of the i2 register on an ISF. */
684  uint32_t                 i2;
685  /** This is the offset of the i3 register on an ISF. */
686  uint32_t                 i3;
687  /** This is the offset of the i4 register on an ISF. */
688  uint32_t                 i4;
689  /** This is the offset of the i5 register on an ISF. */
690  uint32_t                 i5;
691  /** This is the offset of the i6 register on an ISF. */
692  uint32_t                 i6_fp;
693  /** This is the offset of the i7 register on an ISF. */
694  uint32_t                 i7;
695  /** This is the offset of the y register on an ISF. */
696  uint32_t                 y;
697  /** This is the offset of the tpc register on an ISF. */
698  uint32_t                 tpc;
699} CPU_Interrupt_frame;
700
701#endif /* ASM */
702
703/*
704 *  Offsets of fields with CPU_Interrupt_frame for assembly routines.
705 */
706
707/** This macro defines an offset into the ISF for use in assembly. */
708#define ISF_STACK_FRAME_OFFSET 0x00
709/** This macro defines an offset into the ISF for use in assembly. */
710#define ISF_PSR_OFFSET         CPU_MINIMUM_STACK_FRAME_SIZE + 0x00
711/** This macro defines an offset into the ISF for use in assembly. */
712#define ISF_PC_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x04
713/** This macro defines an offset into the ISF for use in assembly. */
714#define ISF_NPC_OFFSET         CPU_MINIMUM_STACK_FRAME_SIZE + 0x08
715/** This macro defines an offset into the ISF for use in assembly. */
716#define ISF_G1_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x0c
717/** This macro defines an offset into the ISF for use in assembly. */
718#define ISF_G2_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x10
719/** This macro defines an offset into the ISF for use in assembly. */
720#define ISF_G3_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x14
721/** This macro defines an offset into the ISF for use in assembly. */
722#define ISF_G4_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x18
723/** This macro defines an offset into the ISF for use in assembly. */
724#define ISF_G5_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x1c
725/** This macro defines an offset into the ISF for use in assembly. */
726#define ISF_G7_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x24
727/** This macro defines an offset into the ISF for use in assembly. */
728#define ISF_I0_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x28
729/** This macro defines an offset into the ISF for use in assembly. */
730#define ISF_I1_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x2c
731/** This macro defines an offset into the ISF for use in assembly. */
732#define ISF_I2_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x30
733/** This macro defines an offset into the ISF for use in assembly. */
734#define ISF_I3_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x34
735/** This macro defines an offset into the ISF for use in assembly. */
736#define ISF_I4_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x38
737/** This macro defines an offset into the ISF for use in assembly. */
738#define ISF_I5_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x3c
739/** This macro defines an offset into the ISF for use in assembly. */
740#define ISF_I6_FP_OFFSET       CPU_MINIMUM_STACK_FRAME_SIZE + 0x40
741/** This macro defines an offset into the ISF for use in assembly. */
742#define ISF_I7_OFFSET          CPU_MINIMUM_STACK_FRAME_SIZE + 0x44
743/** This macro defines an offset into the ISF for use in assembly. */
744#define ISF_Y_OFFSET           CPU_MINIMUM_STACK_FRAME_SIZE + 0x48
745/** This macro defines an offset into the ISF for use in assembly. */
746#define ISF_TPC_OFFSET         CPU_MINIMUM_STACK_FRAME_SIZE + 0x4c
747
748/** This defines the size of the ISF area for use in assembly. */
749#define CONTEXT_CONTROL_INTERRUPT_FRAME_SIZE \
750        CPU_MINIMUM_STACK_FRAME_SIZE + 0x50
751
752#ifndef ASM
753/**
754 * This variable is contains the initialize context for the FP unit.
755 * It is filled in by _CPU_Initialize and copied into the task's FP
756 * context area during _CPU_Context_Initialize.
757 */
758SCORE_EXTERN Context_Control_fp  _CPU_Null_fp_context CPU_STRUCTURE_ALIGNMENT;
759
760/**
761 * The following type defines an entry in the SPARC's trap table.
762 *
763 * NOTE: The instructions chosen are RTEMS dependent although one is
764 *       obligated to use two of the four instructions to perform a
765 *       long jump.  The other instructions load one register with the
766 *       trap type (a.k.a. vector) and another with the psr.
767 */
768typedef struct {
769  /** This will contain a "mov %psr, %l0" instruction. */
770  uint32_t     mov_psr_l0;
771  /** This will contain a "sethi %hi(_handler), %l4" instruction. */
772  uint32_t     sethi_of_handler_to_l4;
773  /** This will contain a "jmp %l4 + %lo(_handler)" instruction. */
774  uint32_t     jmp_to_low_of_handler_plus_l4;
775  /** This will contain a " mov _vector, %l3" instruction. */
776  uint32_t     mov_vector_l3;
777} CPU_Trap_table_entry;
778
779/**
780 * This is the set of opcodes for the instructions loaded into a trap
781 * table entry.  The routine which installs a handler is responsible
782 * for filling in the fields for the _handler address and the _vector
783 * trap type.
784 *
785 * The constants following this structure are masks for the fields which
786 * must be filled in when the handler is installed.
787 */
788extern const CPU_Trap_table_entry _CPU_Trap_slot_template;
789
790/**
791 * The size of the floating point context area.
792 */
793#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
794
795#endif
796
797/**
798 * Amount of extra stack (above minimum stack size) required by
799 * MPCI receive server thread.  Remember that in a multiprocessor
800 * system this thread must exist and be able to process all directives.
801 */
802#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 1024
803
804/**
805 * This defines the number of entries in the ISR_Vector_table managed
806 * by the executive.
807 *
808 * On the SPARC, there are really only 256 vectors.  However, the executive
809 * has no easy, fast, reliable way to determine which traps are synchronous
810 * and which are asynchronous.  By default, synchronous traps return to the
811 * instruction which caused the interrupt.  So if you install a software
812 * trap handler as an executive interrupt handler (which is desirable since
813 * RTEMS takes care of window and register issues), then the executive needs
814 * to know that the return address is to the trap rather than the instruction
815 * following the trap.
816 *
817 * So vectors 0 through 255 are treated as regular asynchronous traps which
818 * provide the "correct" return address.  Vectors 256 through 512 are assumed
819 * by the executive to be synchronous and to require that the return address
820 * be fudged.
821 *
822 * If you use this mechanism to install a trap handler which must reexecute
823 * the instruction which caused the trap, then it should be installed as
824 * an asynchronous trap.  This will avoid the executive changing the return
825 * address.
826 */
827#define CPU_INTERRUPT_NUMBER_OF_VECTORS     256
828
829/**
830 * The SPARC has 256 vectors but the port treats 256-512 as synchronous
831 * traps.
832 */
833#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER 511
834
835/**
836 * This is the bit step in a vector number to indicate it is being installed
837 * as a synchronous trap.
838 */
839#define SPARC_SYNCHRONOUS_TRAP_BIT_MASK     0x100
840
841/**
842 * This macro indicates that @a _trap as an asynchronous trap.
843 */
844#define SPARC_ASYNCHRONOUS_TRAP( _trap )    (_trap)
845
846/**
847 * This macro indicates that @a _trap as a synchronous trap.
848 */
849#define SPARC_SYNCHRONOUS_TRAP( _trap )     ((_trap) + 256 )
850
851/**
852 * This macro returns the real hardware vector number associated with @a _trap.
853 */
854#define SPARC_REAL_TRAP_NUMBER( _trap )     ((_trap) % 256)
855
856/**
857 * This is defined if the port has a special way to report the ISR nesting
858 * level.  Most ports maintain the variable _ISR_Nest_level.
859 */
860#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
861
862/**
863 * Should be large enough to run all tests.  This ensures
864 * that a "reasonable" small application should not have any problems.
865 *
866 * This appears to be a fairly generous number for the SPARC since
867 * represents a call depth of about 20 routines based on the minimum
868 * stack frame.
869 */
870#define CPU_STACK_MINIMUM_SIZE  (1024*4)
871
872/**
873 * What is the size of a pointer on this architecture?
874 */
875#define CPU_SIZEOF_POINTER 4
876
877/**
878 * CPU's worst alignment requirement for data types on a byte boundary.  This
879 * alignment does not take into account the requirements for the stack.
880 *
881 * On the SPARC, this is required for double word loads and stores.
882 */
883#define CPU_ALIGNMENT      8
884
885/**
886 * This number corresponds to the byte alignment requirement for the
887 * heap handler.  This alignment requirement may be stricter than that
888 * for the data types alignment specified by CPU_ALIGNMENT.  It is
889 * common for the heap to follow the same alignment requirement as
890 * CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict enough for the heap,
891 * then this should be set to CPU_ALIGNMENT.
892 *
893 * NOTE:  This does not have to be a power of 2.  It does have to
894 *        be greater or equal to than CPU_ALIGNMENT.
895 */
896#define CPU_HEAP_ALIGNMENT         CPU_ALIGNMENT
897
898/**
899 * This number corresponds to the byte alignment requirement for memory
900 * buffers allocated by the partition manager.  This alignment requirement
901 * may be stricter than that for the data types alignment specified by
902 * CPU_ALIGNMENT.  It is common for the partition to follow the same
903 * alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict
904 * enough for the partition, then this should be set to CPU_ALIGNMENT.
905 *
906 * NOTE:  This does not have to be a power of 2.  It does have to
907 *        be greater or equal to than CPU_ALIGNMENT.
908 */
909#define CPU_PARTITION_ALIGNMENT    CPU_ALIGNMENT
910
911/**
912 * This number corresponds to the byte alignment requirement for the
913 * stack.  This alignment requirement may be stricter than that for the
914 * data types alignment specified by CPU_ALIGNMENT.  If the CPU_ALIGNMENT
915 * is strict enough for the stack, then this should be set to 0.
916 *
917 * NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
918 *
919 * The alignment restrictions for the SPARC are not that strict but this
920 * should unsure that the stack is always sufficiently alignment that the
921 * window overflow, underflow, and flush routines can use double word loads
922 * and stores.
923 */
924#define CPU_STACK_ALIGNMENT        16
925
926#ifndef ASM
927
928/*
929 *  ISR handler macros
930 */
931
932/**
933 * Support routine to initialize the RTEMS vector table after it is allocated.
934 */
935#define _CPU_Initialize_vectors()
936
937/**
938 * Disable all interrupts for a critical section.  The previous
939 * level is returned in _level.
940 */
941#define _CPU_ISR_Disable( _level ) \
942  (_level) = sparc_disable_interrupts()
943
944/**
945 * Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
946 * This indicates the end of a critical section.  The parameter
947 * _level is not modified.
948 */
949#define _CPU_ISR_Enable( _level ) \
950  sparc_enable_interrupts( _level )
951
952/**
953 * This temporarily restores the interrupt to _level before immediately
954 * disabling them again.  This is used to divide long critical
955 * sections into two or more parts.  The parameter _level is not
956 * modified.
957 */
958#define _CPU_ISR_Flash( _level ) \
959  sparc_flash_interrupts( _level )
960
961/**
962 * Map interrupt level in task mode onto the hardware that the CPU
963 * actually provides.  Currently, interrupt levels which do not
964 * map onto the CPU in a straight fashion are undefined.
965 */
966#define _CPU_ISR_Set_level( _newlevel ) \
967   sparc_enable_interrupts( _newlevel << 8)
968
969/**
970 * @brief Obtain the current interrupt disable level.
971 *
972 * This method is invoked to return the current interrupt disable level.
973 *
974 * @return This method returns the current interrupt disable level.
975 */
976uint32_t   _CPU_ISR_Get_level( void );
977
978/* end of ISR handler macros */
979
980/* Context handler macros */
981
982/**
983 * Initialize the context to a state suitable for starting a
984 * task after a context restore operation.  Generally, this
985 * involves:
986 *
987 * - setting a starting address
988 * - preparing the stack
989 * - preparing the stack and frame pointers
990 * - setting the proper interrupt level in the context
991 * - initializing the floating point context
992 *
993 * @param[in] the_context points to the context area
994 * @param[in] stack_base is the low address of the allocated stack area
995 * @param[in] size is the size of the stack area in bytes
996 * @param[in] new_level is the interrupt level for the task
997 * @param[in] entry_point is the task's entry point
998 * @param[in] is_fp is set to TRUE if the task is a floating point task
999 * @param[in] tls_area is the thread-local storage (TLS) area
1000 *
1001 * NOTE:  Implemented as a subroutine for the SPARC port.
1002 */
1003void _CPU_Context_Initialize(
1004  Context_Control  *the_context,
1005  uint32_t         *stack_base,
1006  uint32_t          size,
1007  uint32_t          new_level,
1008  void             *entry_point,
1009  bool              is_fp,
1010  void             *tls_area
1011);
1012
1013/**
1014 * This macro is invoked from _Thread_Handler to do whatever CPU
1015 * specific magic is required that must be done in the context of
1016 * the thread when it starts.
1017 *
1018 * On the SPARC, this is setting the frame pointer so GDB is happy.
1019 * Make GDB stop unwinding at _Thread_Handler, previous register window
1020 * Frame pointer is 0 and calling address must be a function with starting
1021 * with a SAVE instruction. If return address is leaf-function (no SAVE)
1022 * GDB will not look at prev reg window fp.
1023 *
1024 * _Thread_Handler is known to start with SAVE.
1025 */
1026#define _CPU_Context_Initialization_at_thread_begin() \
1027  do { \
1028    __asm__ volatile ("set _Thread_Handler,%%i7\n"::); \
1029  } while (0)
1030
1031/**
1032 * This routine is responsible for somehow restarting the currently
1033 * executing task.
1034 *
1035 * On the SPARC, this is is relatively painless but requires a small
1036 * amount of wrapper code before using the regular restore code in
1037 * of the context switch.
1038 */
1039#define _CPU_Context_Restart_self( _the_context ) \
1040   _CPU_Context_restore( (_the_context) );
1041
1042/**
1043 * The FP context area for the SPARC is a simple structure and nothing
1044 * special is required to find the "starting load point"
1045 */
1046#define _CPU_Context_Fp_start( _base, _offset ) \
1047   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
1048
1049/**
1050 * This routine initializes the FP context area passed to it to.
1051 *
1052 * The SPARC allows us to use the simple initialization model
1053 * in which an "initial" FP context was saved into _CPU_Null_fp_context
1054 * at CPU initialization and it is simply copied into the destination
1055 * context.
1056 */
1057#define _CPU_Context_Initialize_fp( _destination ) \
1058  do { \
1059   *(*(_destination)) = _CPU_Null_fp_context; \
1060  } while (0)
1061
1062/* end of Context handler macros */
1063
1064/* Fatal Error manager macros */
1065
1066/**
1067 * This routine copies _error into a known place -- typically a stack
1068 * location or a register, optionally disables interrupts, and
1069 * halts/stops the CPU.
1070 */
1071#define _CPU_Fatal_halt( _error ) \
1072  do { \
1073    uint32_t   level; \
1074    \
1075    level = sparc_disable_interrupts(); \
1076    __asm__ volatile ( "mov  %0, %%g1 " : "=r" (level) : "0" (level) ); \
1077    while (1); /* loop forever */ \
1078  } while (0)
1079
1080/* end of Fatal Error manager macros */
1081
1082/* Bitfield handler macros */
1083
1084#if ( SPARC_HAS_BITSCAN == 0 )
1085  /**
1086   * The SPARC port uses the generic C algorithm for bitfield scan if the
1087   * CPU model does not have a scan instruction.
1088   */
1089  #define CPU_USE_GENERIC_BITFIELD_CODE TRUE
1090  /**
1091   * The SPARC port uses the generic C algorithm for bitfield scan if the
1092   * CPU model does not have a scan instruction.  Thus is needs the generic
1093   * data table used by that algorithm.
1094   */
1095  #define CPU_USE_GENERIC_BITFIELD_DATA TRUE
1096#else
1097  #error "scan instruction not currently supported by RTEMS!!"
1098#endif
1099
1100/* end of Bitfield handler macros */
1101
1102/* functions */
1103
1104/**
1105 * @brief SPARC specific initialization.
1106 *
1107 * This routine performs CPU dependent initialization.
1108 */
1109void _CPU_Initialize(void);
1110
1111/**
1112 * @brief SPARC specific raw ISR installer.
1113 *
1114 * This routine installs @a new_handler to be directly called from the trap
1115 * table.
1116 *
1117 * @param[in] vector is the vector number
1118 * @param[in] new_handler is the new ISR handler
1119 * @param[in] old_handler will contain the old ISR handler
1120 */
1121void _CPU_ISR_install_raw_handler(
1122  uint32_t    vector,
1123  proc_ptr    new_handler,
1124  proc_ptr   *old_handler
1125);
1126
1127/**
1128 * @brief SPARC specific RTEMS ISR installer.
1129 *
1130 * This routine installs an interrupt vector.
1131 *
1132 * @param[in] vector is the vector number
1133 * @param[in] new_handler is the new ISR handler
1134 * @param[in] old_handler will contain the old ISR handler
1135 */
1136
1137void _CPU_ISR_install_vector(
1138  uint32_t    vector,
1139  proc_ptr    new_handler,
1140  proc_ptr   *old_handler
1141);
1142
1143/**
1144 * @brief SPARC specific context switch.
1145 *
1146 * This routine switches from the run context to the heir context.
1147 *
1148 * @param[in] run is the currently executing thread
1149 * @param[in] heir will become the currently executing thread
1150 */
1151void _CPU_Context_switch(
1152  Context_Control  *run,
1153  Context_Control  *heir
1154);
1155
1156/**
1157 * @brief SPARC specific context restore.
1158 *
1159 * This routine is generally used only to restart self in an
1160 * efficient manner.
1161 *
1162 * @param[in] new_context is the context to restore
1163 */
1164void _CPU_Context_restore(
1165  Context_Control *new_context
1166) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
1167
1168/**
1169 * @brief The pointer to the current per-CPU control is available via register
1170 * g6.
1171 */
1172register struct Per_CPU_Control *_SPARC_Per_CPU_current asm( "g6" );
1173
1174#define _CPU_Get_current_per_CPU_control() ( _SPARC_Per_CPU_current )
1175
1176#if defined(RTEMS_SMP)
1177  uint32_t _CPU_SMP_Initialize( void );
1178
1179  bool _CPU_SMP_Start_processor( uint32_t cpu_index );
1180
1181  void _CPU_SMP_Finalize_initialization( uint32_t cpu_count );
1182
1183  #if defined(__leon__)
1184    static inline uint32_t _CPU_SMP_Get_current_processor( void )
1185    {
1186      return _LEON3_Get_current_processor();
1187    }
1188  #else
1189    uint32_t _CPU_SMP_Get_current_processor( void );
1190  #endif
1191
1192  void _CPU_SMP_Send_interrupt( uint32_t target_processor_index );
1193
1194  static inline void _CPU_SMP_Processor_event_broadcast( void )
1195  {
1196    __asm__ volatile ( "" : : : "memory" );
1197  }
1198
1199  static inline void _CPU_SMP_Processor_event_receive( void )
1200  {
1201    __asm__ volatile ( "" : : : "memory" );
1202  }
1203#endif
1204
1205/**
1206 * @brief SPARC specific save FPU method.
1207 *
1208 * This routine saves the floating point context passed to it.
1209 *
1210 * @param[in] fp_context_ptr is the area to save into
1211 */
1212void _CPU_Context_save_fp(
1213  Context_Control_fp **fp_context_ptr
1214);
1215
1216/**
1217 * @brief SPARC specific restore FPU method.
1218 *
1219 * This routine restores the floating point context passed to it.
1220 *
1221 * @param[in] fp_context_ptr is the area to restore from
1222 */
1223void _CPU_Context_restore_fp(
1224  Context_Control_fp **fp_context_ptr
1225);
1226
1227static inline void _CPU_Context_volatile_clobber( uintptr_t pattern )
1228{
1229  /* TODO */
1230}
1231
1232static inline void _CPU_Context_validate( uintptr_t pattern )
1233{
1234  while (1) {
1235    /* TODO */
1236  }
1237}
1238
1239typedef struct {
1240  uint32_t trap;
1241  CPU_Interrupt_frame *isf;
1242} CPU_Exception_frame;
1243
1244void _BSP_Exception_frame_print( const CPU_Exception_frame *frame );
1245
1246static inline void _CPU_Exception_frame_print(
1247  const CPU_Exception_frame *frame
1248)
1249{
1250  _BSP_Exception_frame_print( frame );
1251}
1252
1253/**
1254 * @brief SPARC specific method to endian swap an uint32_t.
1255 *
1256 * The following routine swaps the endian format of an unsigned int.
1257 * It must be static because it is referenced indirectly.
1258 *
1259 * @param[in] value is the value to endian swap
1260 *
1261 * This version will work on any processor, but if you come across a better
1262 * way for the SPARC PLEASE use it.  The most common way to swap a 32-bit
1263 * entity as shown below is not any more efficient on the SPARC.
1264 *
1265 *    - swap least significant two bytes with 16-bit rotate
1266 *    - swap upper and lower 16-bits
1267 *    - swap most significant two bytes with 16-bit rotate
1268 *
1269 * It is not obvious how the SPARC can do significantly better than the
1270 * generic code.  gcc 2.7.0 only generates about 12 instructions for the
1271 * following code at optimization level four (i.e. -O4).
1272 */
1273static inline uint32_t CPU_swap_u32(
1274  uint32_t value
1275)
1276{
1277  uint32_t   byte1, byte2, byte3, byte4, swapped;
1278
1279  byte4 = (value >> 24) & 0xff;
1280  byte3 = (value >> 16) & 0xff;
1281  byte2 = (value >> 8)  & 0xff;
1282  byte1 =  value        & 0xff;
1283
1284  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
1285  return( swapped );
1286}
1287
1288/**
1289 * @brief SPARC specific method to endian swap an uint16_t.
1290 *
1291 * The following routine swaps the endian format of a uint16_t.
1292 *
1293 * @param[in] value is the value to endian swap
1294 */
1295#define CPU_swap_u16( value ) \
1296  (((value&0xff) << 8) | ((value >> 8)&0xff))
1297
1298typedef uint32_t CPU_Counter_ticks;
1299
1300typedef CPU_Counter_ticks (*SPARC_Counter_difference)(
1301  CPU_Counter_ticks second,
1302  CPU_Counter_ticks first
1303);
1304
1305/*
1306 * The SPARC processors supported by RTEMS have no built-in CPU counter
1307 * support.  We have to use some hardware counter module for this purpose.  The
1308 * BSP must provide a 32-bit register which contains the current CPU counter
1309 * value and a function for the difference calculation.  It can use for example
1310 * the GPTIMER instance used for the clock driver.
1311 */
1312typedef struct {
1313  volatile const CPU_Counter_ticks *counter_register;
1314  SPARC_Counter_difference counter_difference;
1315} SPARC_Counter;
1316
1317extern SPARC_Counter _SPARC_Counter;
1318
1319/*
1320 * Returns always a value of one regardless of the parameters.  This prevents
1321 * an infinite loop in rtems_counter_delay_ticks().  Its only a reasonably safe
1322 * default.
1323 */
1324CPU_Counter_ticks _SPARC_Counter_difference_default(
1325  CPU_Counter_ticks second,
1326  CPU_Counter_ticks first
1327);
1328
1329static inline bool _SPARC_Counter_is_default( void )
1330{
1331  return _SPARC_Counter.counter_difference
1332    == _SPARC_Counter_difference_default;
1333}
1334
1335static inline void _SPARC_Counter_initialize(
1336  volatile const CPU_Counter_ticks *counter_register,
1337  SPARC_Counter_difference counter_difference
1338)
1339{
1340  _SPARC_Counter.counter_register = counter_register;
1341  _SPARC_Counter.counter_difference = counter_difference;
1342}
1343
1344static inline CPU_Counter_ticks _CPU_Counter_read( void )
1345{
1346  return *_SPARC_Counter.counter_register;
1347}
1348
1349static inline CPU_Counter_ticks _CPU_Counter_difference(
1350  CPU_Counter_ticks second,
1351  CPU_Counter_ticks first
1352)
1353{
1354  return (*_SPARC_Counter.counter_difference)( second, first );
1355}
1356
1357#endif /* ASM */
1358
1359#ifdef __cplusplus
1360}
1361#endif
1362
1363#endif
Note: See TracBrowser for help on using the repository browser.