source: rtems/cpukit/score/cpu/mips/rtems/score/cpu.h @ d2202ac

4.115
Last change on this file since d2202ac was f1738ed, checked in by Sebastian Huber <sebastian.huber@…>, on 11/04/12 at 20:04:39

score: PR1607: Add and use CPU_SIZEOF_POINTER

Add and use new CPU port define CPU_SIZEOF_POINTER. It must be an
integer literal that can be used by the assembler. This value will be
used to calculate offsets of structure members. These offsets will be
used in assembler code.

The size of a pointer is part of the application binary interface (ABI)
and thus independent of the actual programming language. The compiler
will provide defines to determine the current ABI. We use these defines
to select the appropriate CPU_SIZEOF_POINTER value.

Static assertions in the new file "cpukit/score/src/percpuasm.c" will
ensure that the value of CPU_SIZEOF_POINTER is consistent with the
current compiler settings. Also the offset values used by assembler
code are verfied.

  • Property mode set to 100644
File size: 41.2 KB
Line 
1/**
2 *  @file
3 * 
4 *  Mips CPU Dependent Header File
5 *
6 *  Conversion to MIPS port by Alan Cudmore <alanc@linuxstart.com> and
7 *           Joel Sherrill <joel@OARcorp.com>.
8 *
9 *    These changes made the code conditional on standard cpp predefines,
10 *    merged the mips1 and mips3 code sequences as much as possible,
11 *    and moved some of the assembly code to C.  Alan did much of the
12 *    initial analysis and rework.  Joel took over from there and
13 *    wrote the JMR3904 BSP so this could be tested.  Joel also
14 *    added the new interrupt vectoring support in libcpu and
15 *    tried to better support the various interrupt controllers.
16 *
17 */
18
19/*
20 *  Original MIP64ORION port by Craig Lebakken <craigl@transition.com>
21 *           COPYRIGHT (c) 1996 by Transition Networks Inc.
22 *
23 *    To anyone who acknowledges that this file is provided "AS IS"
24 *    without any express or implied warranty:
25 *      permission to use, copy, modify, and distribute this file
26 *      for any purpose is hereby granted without fee, provided that
27 *      the above copyright notice and this notice appears in all
28 *      copies, and that the name of Transition Networks not be used in
29 *      advertising or publicity pertaining to distribution of the
30 *      software without specific, written prior permission.
31 *      Transition Networks makes no representations about the suitability
32 *      of this software for any purpose.
33 *
34 *  COPYRIGHT (c) 1989-2012.
35 *  On-Line Applications Research Corporation (OAR).
36 *
37 *  The license and distribution terms for this file may be
38 *  found in the file LICENSE in this distribution or at
39 *  http://www.rtems.com/license/LICENSE.
40 */
41
42#ifndef _RTEMS_SCORE_CPU_H
43#define _RTEMS_SCORE_CPU_H
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49#include <rtems/score/types.h>
50#include <rtems/score/mips.h>
51
52/* conditional compilation parameters */
53
54/*
55 *  Should the calls to _Thread_Enable_dispatch be inlined?
56 *
57 *  If TRUE, then they are inlined.
58 *  If FALSE, then a subroutine call is made.
59 *
60 *  Basically this is an example of the classic trade-off of size
61 *  versus speed.  Inlining the call (TRUE) typically increases the
62 *  size of RTEMS while speeding up the enabling of dispatching.
63 *  [NOTE: In general, the _Thread_Dispatch_disable_level will
64 *  only be 0 or 1 unless you are in an interrupt handler and that
65 *  interrupt handler invokes the executive.]  When not inlined
66 *  something calls _Thread_Enable_dispatch which in turns calls
67 *  _Thread_Dispatch.  If the enable dispatch is inlined, then
68 *  one subroutine call is avoided entirely.]
69 */
70
71#define CPU_INLINE_ENABLE_DISPATCH       FALSE
72
73/*
74 *  Should the body of the search loops in _Thread_queue_Enqueue_priority
75 *  be unrolled one time?  In unrolled each iteration of the loop examines
76 *  two "nodes" on the chain being searched.  Otherwise, only one node
77 *  is examined per iteration.
78 *
79 *  If TRUE, then the loops are unrolled.
80 *  If FALSE, then the loops are not unrolled.
81 *
82 *  The primary factor in making this decision is the cost of disabling
83 *  and enabling interrupts (_ISR_Flash) versus the cost of rest of the
84 *  body of the loop.  On some CPUs, the flash is more expensive than
85 *  one iteration of the loop body.  In this case, it might be desirable
86 *  to unroll the loop.  It is important to note that on some CPUs, this
87 *  code is the longest interrupt disable period in RTEMS.  So it is
88 *  necessary to strike a balance when setting this parameter.
89 */
90
91#define CPU_UNROLL_ENQUEUE_PRIORITY      TRUE
92
93/*
94 *  Does RTEMS manage a dedicated interrupt stack in software?
95 *
96 *  If TRUE, then a stack is allocated in _Interrupt_Manager_initialization.
97 *  If FALSE, nothing is done.
98 *
99 *  If the CPU supports a dedicated interrupt stack in hardware,
100 *  then it is generally the responsibility of the BSP to allocate it
101 *  and set it up.
102 *
103 *  If the CPU does not support a dedicated interrupt stack, then
104 *  the porter has two options: (1) execute interrupts on the
105 *  stack of the interrupted task, and (2) have RTEMS manage a dedicated
106 *  interrupt stack.
107 *
108 *  If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
109 *
110 *  Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
111 *  CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE.  It is
112 *  possible that both are FALSE for a particular CPU.  Although it
113 *  is unclear what that would imply about the interrupt processing
114 *  procedure on that CPU.
115 */
116
117#define CPU_HAS_SOFTWARE_INTERRUPT_STACK FALSE
118
119/*
120 *  Does the CPU follow the simple vectored interrupt model?
121 *
122 *  If TRUE, then RTEMS allocates the vector table it internally manages.
123 *  If FALSE, then the BSP is assumed to allocate and manage the vector
124 *  table
125 *
126 *  MIPS Specific Information:
127 *
128 *  Up to and including RTEMS 4.10, the MIPS port used simple vectored
129 *  interrupts. But this was changed to the PIC model after 4.10.
130 */
131#define CPU_SIMPLE_VECTORED_INTERRUPTS FALSE
132
133/*
134 *  Does this CPU have hardware support for a dedicated interrupt stack?
135 *
136 *  If TRUE, then it must be installed during initialization.
137 *  If FALSE, then no installation is performed.
138 *
139 *  If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE.
140 *
141 *  Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and
142 *  CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE.  It is
143 *  possible that both are FALSE for a particular CPU.  Although it
144 *  is unclear what that would imply about the interrupt processing
145 *  procedure on that CPU.
146 */
147
148#define CPU_HAS_HARDWARE_INTERRUPT_STACK FALSE
149
150/*
151 *  Does RTEMS allocate a dedicated interrupt stack in the Interrupt Manager?
152 *
153 *  If TRUE, then the memory is allocated during initialization.
154 *  If FALSE, then the memory is allocated during initialization.
155 *
156 *  This should be TRUE is CPU_HAS_SOFTWARE_INTERRUPT_STACK is TRUE.
157 */
158
159#define CPU_ALLOCATE_INTERRUPT_STACK FALSE
160
161/*
162 *  Does the RTEMS invoke the user's ISR with the vector number and
163 *  a pointer to the saved interrupt frame (1) or just the vector
164 *  number (0)?
165 *
166 */
167
168#define CPU_ISR_PASSES_FRAME_POINTER 1
169
170
171
172/*
173 *  Does the CPU have hardware floating point?
174 *
175 *  If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
176 *  If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
177 *
178 *  If there is a FP coprocessor such as the i387 or mc68881, then
179 *  the answer is TRUE.
180 *
181 *  The macro name "MIPS_HAS_FPU" should be made CPU specific.
182 *  It indicates whether or not this CPU model has FP support.  For
183 *  example, it would be possible to have an i386_nofp CPU model
184 *  which set this to false to indicate that you have an i386 without
185 *  an i387 and wish to leave floating point support out of RTEMS.
186 */
187
188#if ( MIPS_HAS_FPU == 1 )
189#define CPU_HARDWARE_FP     TRUE
190#else
191#define CPU_HARDWARE_FP     FALSE
192#endif
193
194/*
195 *  Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
196 *
197 *  If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
198 *  If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
199 *
200 *  So far, the only CPU in which this option has been used is the
201 *  HP PA-RISC.  The HP C compiler and gcc both implicitly use the
202 *  floating point registers to perform integer multiplies.  If
203 *  a function which you would not think utilize the FP unit DOES,
204 *  then one can not easily predict which tasks will use the FP hardware.
205 *  In this case, this option should be TRUE.
206 *
207 *  If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
208 *
209 *  Mips Note: It appears the GCC can implicitly generate FPU
210 *  and Altivec instructions when you least expect them.  So make
211 *  all tasks floating point.
212 */
213
214#define CPU_ALL_TASKS_ARE_FP CPU_HARDWARE_FP
215
216/*
217 *  Should the IDLE task have a floating point context?
218 *
219 *  If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
220 *  and it has a floating point context which is switched in and out.
221 *  If FALSE, then the IDLE task does not have a floating point context.
222 *
223 *  Setting this to TRUE negatively impacts the time required to preempt
224 *  the IDLE task from an interrupt because the floating point context
225 *  must be saved as part of the preemption.
226 */
227
228#define CPU_IDLE_TASK_IS_FP      FALSE
229
230/*
231 *  Should the saving of the floating point registers be deferred
232 *  until a context switch is made to another different floating point
233 *  task?
234 *
235 *  If TRUE, then the floating point context will not be stored until
236 *  necessary.  It will remain in the floating point registers and not
237 *  disturned until another floating point task is switched to.
238 *
239 *  If FALSE, then the floating point context is saved when a floating
240 *  point task is switched out and restored when the next floating point
241 *  task is restored.  The state of the floating point registers between
242 *  those two operations is not specified.
243 *
244 *  If the floating point context does NOT have to be saved as part of
245 *  interrupt dispatching, then it should be safe to set this to TRUE.
246 *
247 *  Setting this flag to TRUE results in using a different algorithm
248 *  for deciding when to save and restore the floating point context.
249 *  The deferred FP switch algorithm minimizes the number of times
250 *  the FP context is saved and restored.  The FP context is not saved
251 *  until a context switch is made to another, different FP task.
252 *  Thus in a system with only one FP task, the FP context will never
253 *  be saved or restored.
254 */
255
256#define CPU_USE_DEFERRED_FP_SWITCH       TRUE
257
258/*
259 *  Does this port provide a CPU dependent IDLE task implementation?
260 *
261 *  If TRUE, then the routine _CPU_Internal_threads_Idle_thread_body
262 *  must be provided and is the default IDLE thread body instead of
263 *  _Internal_threads_Idle_thread_body.
264 *
265 *  If FALSE, then use the generic IDLE thread body if the BSP does
266 *  not provide one.
267 *
268 *  This is intended to allow for supporting processors which have
269 *  a low power or idle mode.  When the IDLE thread is executed, then
270 *  the CPU can be powered down.
271 *
272 *  The order of precedence for selecting the IDLE thread body is:
273 *
274 *    1.  BSP provided
275 *    2.  CPU dependent (if provided)
276 *    3.  generic (if no BSP and no CPU dependent)
277 */
278
279/* we can use the low power wait instruction for the IDLE thread */
280#define CPU_PROVIDES_IDLE_THREAD_BODY    TRUE
281
282/*
283 *  Does the stack grow up (toward higher addresses) or down
284 *  (toward lower addresses)?
285 *
286 *  If TRUE, then the grows upward.
287 *  If FALSE, then the grows toward smaller addresses.
288 */
289
290/* our stack grows down */
291#define CPU_STACK_GROWS_UP               FALSE
292
293/*
294 *  The following is the variable attribute used to force alignment
295 *  of critical RTEMS structures.  On some processors it may make
296 *  sense to have these aligned on tighter boundaries than
297 *  the minimum requirements of the compiler in order to have as
298 *  much of the critical data area as possible in a cache line.
299 *
300 *  The placement of this macro in the declaration of the variables
301 *  is based on the syntactically requirements of the GNU C
302 *  "__attribute__" extension.  For example with GNU C, use
303 *  the following to force a structures to a 32 byte boundary.
304 *
305 *      __attribute__ ((aligned (32)))
306 *
307 *  NOTE:  Currently only the Priority Bit Map table uses this feature.
308 *         To benefit from using this, the data must be heavily
309 *         used so it will stay in the cache and used frequently enough
310 *         in the executive to justify turning this on.
311 */
312
313/* our cache line size is 16 bytes */
314#if __GNUC__
315#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (16)))
316#else
317#define CPU_STRUCTURE_ALIGNMENT
318#endif
319
320#define CPU_TIMESTAMP_USE_INT64_INLINE TRUE
321
322/*
323 *  Define what is required to specify how the network to host conversion
324 *  routines are handled.
325 */
326
327/* __MIPSEB__ or __MIPSEL__ is defined by GCC based on -EB or -EL command line options */
328#if defined(__MIPSEB__)
329#define CPU_BIG_ENDIAN                           TRUE
330#define CPU_LITTLE_ENDIAN                        FALSE
331#elif defined(__MIPSEL__)
332#define CPU_BIG_ENDIAN                           FALSE
333#define CPU_LITTLE_ENDIAN                        TRUE
334#else
335#error "Unknown endianness"
336#endif
337
338/*
339 *  The following defines the number of bits actually used in the
340 *  interrupt field of the task mode.  How those bits map to the
341 *  CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
342 */
343
344#define CPU_MODES_INTERRUPT_MASK   0x000000ff
345
346#define CPU_SIZEOF_POINTER 4
347
348/*
349 *  Processor defined structures
350 *
351 *  Examples structures include the descriptor tables from the i386
352 *  and the processor control structure on the i960ca.
353 */
354
355/* may need to put some structures here.  */
356
357/*
358 * Contexts
359 *
360 *  Generally there are 2 types of context to save.
361 *     1. Interrupt registers to save
362 *     2. Task level registers to save
363 *
364 *  This means we have the following 3 context items:
365 *     1. task level context stuff::  Context_Control
366 *     2. floating point task stuff:: Context_Control_fp
367 *     3. special interrupt level context :: Context_Control_interrupt
368 *
369 *  On some processors, it is cost-effective to save only the callee
370 *  preserved registers during a task context switch.  This means
371 *  that the ISR code needs to save those registers which do not
372 *  persist across function calls.  It is not mandatory to make this
373 *  distinctions between the caller/callee saves registers for the
374 *  purpose of minimizing context saved during task switch and on interrupts.
375 *  If the cost of saving extra registers is minimal, simplicity is the
376 *  choice.  Save the same context on interrupt entry as for tasks in
377 *  this case.
378 *
379 *  Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
380 *  care should be used in designing the context area.
381 *
382 *  On some CPUs with hardware floating point support, the Context_Control_fp
383 *  structure will not be used or it simply consist of an array of a
384 *  fixed number of bytes.   This is done when the floating point context
385 *  is dumped by a "FP save context" type instruction and the format
386 *  is not really defined by the CPU.  In this case, there is no need
387 *  to figure out the exact format -- only the size.  Of course, although
388 *  this is enough information for RTEMS, it is probably not enough for
389 *  a debugger such as gdb.  But that is another problem.
390 */
391
392#ifndef ASM
393
394/* WARNING: If this structure is modified, the constants in cpu.h must be updated. */
395#if (__mips == 1) || (__mips == 32)
396#define __MIPS_REGISTER_TYPE     uint32_t
397#define __MIPS_FPU_REGISTER_TYPE uint32_t
398#elif __mips == 3
399#define __MIPS_REGISTER_TYPE     uint64_t
400#define __MIPS_FPU_REGISTER_TYPE uint64_t
401#else
402#error "mips register size: unknown architecture level!!"
403#endif
404typedef struct {
405    __MIPS_REGISTER_TYPE s0;
406    __MIPS_REGISTER_TYPE s1;
407    __MIPS_REGISTER_TYPE s2;
408    __MIPS_REGISTER_TYPE s3;
409    __MIPS_REGISTER_TYPE s4;
410    __MIPS_REGISTER_TYPE s5;
411    __MIPS_REGISTER_TYPE s6;
412    __MIPS_REGISTER_TYPE s7;
413    __MIPS_REGISTER_TYPE sp;
414    __MIPS_REGISTER_TYPE fp;
415    __MIPS_REGISTER_TYPE ra;
416    __MIPS_REGISTER_TYPE c0_sr;
417    __MIPS_REGISTER_TYPE c0_epc;
418} Context_Control;
419
420#define _CPU_Context_Get_SP( _context ) \
421  (uintptr_t) (_context)->sp
422
423/* WARNING: If this structure is modified, the constants in cpu.h
424 *          must also be updated.
425 */
426
427typedef struct {
428#if ( CPU_HARDWARE_FP == TRUE )
429    __MIPS_FPU_REGISTER_TYPE fp0;
430    __MIPS_FPU_REGISTER_TYPE fp1;
431    __MIPS_FPU_REGISTER_TYPE fp2;
432    __MIPS_FPU_REGISTER_TYPE fp3;
433    __MIPS_FPU_REGISTER_TYPE fp4;
434    __MIPS_FPU_REGISTER_TYPE fp5;
435    __MIPS_FPU_REGISTER_TYPE fp6;
436    __MIPS_FPU_REGISTER_TYPE fp7;
437    __MIPS_FPU_REGISTER_TYPE fp8;
438    __MIPS_FPU_REGISTER_TYPE fp9;
439    __MIPS_FPU_REGISTER_TYPE fp10;
440    __MIPS_FPU_REGISTER_TYPE fp11;
441    __MIPS_FPU_REGISTER_TYPE fp12;
442    __MIPS_FPU_REGISTER_TYPE fp13;
443    __MIPS_FPU_REGISTER_TYPE fp14;
444    __MIPS_FPU_REGISTER_TYPE fp15;
445    __MIPS_FPU_REGISTER_TYPE fp16;
446    __MIPS_FPU_REGISTER_TYPE fp17;
447    __MIPS_FPU_REGISTER_TYPE fp18;
448    __MIPS_FPU_REGISTER_TYPE fp19;
449    __MIPS_FPU_REGISTER_TYPE fp20;
450    __MIPS_FPU_REGISTER_TYPE fp21;
451    __MIPS_FPU_REGISTER_TYPE fp22;
452    __MIPS_FPU_REGISTER_TYPE fp23;
453    __MIPS_FPU_REGISTER_TYPE fp24;
454    __MIPS_FPU_REGISTER_TYPE fp25;
455    __MIPS_FPU_REGISTER_TYPE fp26;
456    __MIPS_FPU_REGISTER_TYPE fp27;
457    __MIPS_FPU_REGISTER_TYPE fp28;
458    __MIPS_FPU_REGISTER_TYPE fp29;
459    __MIPS_FPU_REGISTER_TYPE fp30;
460    __MIPS_FPU_REGISTER_TYPE fp31;
461    uint32_t fpcs;
462#endif
463} Context_Control_fp;
464
465/*
466 *  This struct reflects the stack frame employed in ISR_Handler.  Note
467 *  that the ISR routine save some of the registers to this frame for
468 *  all interrupts and exceptions.  Other registers are saved only on
469 *  exceptions, while others are not touched at all.  The untouched
470 *  registers are not normally disturbed by high-level language
471 *  programs so they can be accessed when required.
472 *
473 *  The registers and their ordering in this struct must directly
474 *  correspond to the layout and ordering of * shown in iregdef.h,
475 *  as cpu_asm.S uses those definitions to fill the stack frame.
476 *  This struct provides access to the stack frame for C code.
477 *
478 *  Similarly, this structure is used by debugger stubs and exception
479 *  processing routines so be careful when changing the format.
480 *
481 *  NOTE: The comments with this structure and cpu_asm.S should be kept
482 *        in sync.  When in doubt, look in the  code to see if the
483 *        registers you're interested in are actually treated as expected.
484 *        The order of the first portion of this structure follows the
485 *        order of registers expected by gdb.
486 */
487
488typedef struct
489{
490  __MIPS_REGISTER_TYPE  r0;       /*  0 -- NOT FILLED IN */
491  __MIPS_REGISTER_TYPE  at;       /*  1 -- saved always */
492  __MIPS_REGISTER_TYPE  v0;       /*  2 -- saved always */
493  __MIPS_REGISTER_TYPE  v1;       /*  3 -- saved always */
494  __MIPS_REGISTER_TYPE  a0;       /*  4 -- saved always */
495  __MIPS_REGISTER_TYPE  a1;       /*  5 -- saved always */
496  __MIPS_REGISTER_TYPE  a2;       /*  6 -- saved always */
497  __MIPS_REGISTER_TYPE  a3;       /*  7 -- saved always */
498  __MIPS_REGISTER_TYPE  t0;       /*  8 -- saved always */
499  __MIPS_REGISTER_TYPE  t1;       /*  9 -- saved always */
500  __MIPS_REGISTER_TYPE  t2;       /* 10 -- saved always */
501  __MIPS_REGISTER_TYPE  t3;       /* 11 -- saved always */
502  __MIPS_REGISTER_TYPE  t4;       /* 12 -- saved always */
503  __MIPS_REGISTER_TYPE  t5;       /* 13 -- saved always */
504  __MIPS_REGISTER_TYPE  t6;       /* 14 -- saved always */
505  __MIPS_REGISTER_TYPE  t7;       /* 15 -- saved always */
506  __MIPS_REGISTER_TYPE  s0;       /* 16 -- saved on exceptions */
507  __MIPS_REGISTER_TYPE  s1;       /* 17 -- saved on exceptions */
508  __MIPS_REGISTER_TYPE  s2;       /* 18 -- saved on exceptions */
509  __MIPS_REGISTER_TYPE  s3;       /* 19 -- saved on exceptions */
510  __MIPS_REGISTER_TYPE  s4;       /* 20 -- saved on exceptions */
511  __MIPS_REGISTER_TYPE  s5;       /* 21 -- saved on exceptions */
512  __MIPS_REGISTER_TYPE  s6;       /* 22 -- saved on exceptions */
513  __MIPS_REGISTER_TYPE  s7;       /* 23 -- saved on exceptions */
514  __MIPS_REGISTER_TYPE  t8;       /* 24 -- saved always */
515  __MIPS_REGISTER_TYPE  t9;       /* 25 -- saved always */
516  __MIPS_REGISTER_TYPE  k0;       /* 26 -- NOT FILLED IN, kernel tmp reg */
517  __MIPS_REGISTER_TYPE  k1;       /* 27 -- NOT FILLED IN, kernel tmp reg */
518  __MIPS_REGISTER_TYPE  gp;       /* 28 -- saved always */
519  __MIPS_REGISTER_TYPE  sp;       /* 29 -- saved on exceptions NOT RESTORED */
520  __MIPS_REGISTER_TYPE  fp;       /* 30 -- saved always */
521  __MIPS_REGISTER_TYPE  ra;       /* 31 -- saved always */
522  __MIPS_REGISTER_TYPE  c0_sr;    /* 32 -- saved always, some bits are */
523                                  /*    manipulated per-thread          */
524  __MIPS_REGISTER_TYPE  mdlo;     /* 33 -- saved always */
525  __MIPS_REGISTER_TYPE  mdhi;     /* 34 -- saved always */
526  __MIPS_REGISTER_TYPE  badvaddr; /* 35 -- saved on exceptions, read-only */
527  __MIPS_REGISTER_TYPE  cause;    /* 36 -- saved on exceptions NOT restored */
528  __MIPS_REGISTER_TYPE  epc;      /* 37 -- saved always, read-only register */
529                                  /*        but logically restored */
530  __MIPS_FPU_REGISTER_TYPE f0;    /* 38 -- saved if FP enabled */
531  __MIPS_FPU_REGISTER_TYPE f1;    /* 39 -- saved if FP enabled */
532  __MIPS_FPU_REGISTER_TYPE f2;    /* 40 -- saved if FP enabled */
533  __MIPS_FPU_REGISTER_TYPE f3;    /* 41 -- saved if FP enabled */
534  __MIPS_FPU_REGISTER_TYPE f4;    /* 42 -- saved if FP enabled */
535  __MIPS_FPU_REGISTER_TYPE f5;    /* 43 -- saved if FP enabled */
536  __MIPS_FPU_REGISTER_TYPE f6;    /* 44 -- saved if FP enabled */
537  __MIPS_FPU_REGISTER_TYPE f7;    /* 45 -- saved if FP enabled */
538  __MIPS_FPU_REGISTER_TYPE f8;    /* 46 -- saved if FP enabled */
539  __MIPS_FPU_REGISTER_TYPE f9;    /* 47 -- saved if FP enabled */
540  __MIPS_FPU_REGISTER_TYPE f10;   /* 48 -- saved if FP enabled */
541  __MIPS_FPU_REGISTER_TYPE f11;   /* 49 -- saved if FP enabled */
542  __MIPS_FPU_REGISTER_TYPE f12;   /* 50 -- saved if FP enabled */
543  __MIPS_FPU_REGISTER_TYPE f13;   /* 51 -- saved if FP enabled */
544  __MIPS_FPU_REGISTER_TYPE f14;   /* 52 -- saved if FP enabled */
545  __MIPS_FPU_REGISTER_TYPE f15;   /* 53 -- saved if FP enabled */
546  __MIPS_FPU_REGISTER_TYPE f16;   /* 54 -- saved if FP enabled */
547  __MIPS_FPU_REGISTER_TYPE f17;   /* 55 -- saved if FP enabled */
548  __MIPS_FPU_REGISTER_TYPE f18;   /* 56 -- saved if FP enabled */
549  __MIPS_FPU_REGISTER_TYPE f19;   /* 57 -- saved if FP enabled */
550  __MIPS_FPU_REGISTER_TYPE f20;   /* 58 -- saved if FP enabled */
551  __MIPS_FPU_REGISTER_TYPE f21;   /* 59 -- saved if FP enabled */
552  __MIPS_FPU_REGISTER_TYPE f22;   /* 60 -- saved if FP enabled */
553  __MIPS_FPU_REGISTER_TYPE f23;   /* 61 -- saved if FP enabled */
554  __MIPS_FPU_REGISTER_TYPE f24;   /* 62 -- saved if FP enabled */
555  __MIPS_FPU_REGISTER_TYPE f25;   /* 63 -- saved if FP enabled */
556  __MIPS_FPU_REGISTER_TYPE f26;   /* 64 -- saved if FP enabled */
557  __MIPS_FPU_REGISTER_TYPE f27;   /* 65 -- saved if FP enabled */
558  __MIPS_FPU_REGISTER_TYPE f28;   /* 66 -- saved if FP enabled */
559  __MIPS_FPU_REGISTER_TYPE f29;   /* 67 -- saved if FP enabled */
560  __MIPS_FPU_REGISTER_TYPE f30;   /* 68 -- saved if FP enabled */
561  __MIPS_FPU_REGISTER_TYPE f31;   /* 69 -- saved if FP enabled */
562  __MIPS_REGISTER_TYPE     fcsr;  /* 70 -- saved on exceptions */
563                                  /*    (oddly not documented on MGV) */
564  __MIPS_REGISTER_TYPE     feir;  /* 71 -- saved on exceptions */
565                                  /*    (oddly not documented on MGV) */
566
567  /* GDB does not seem to care about anything past this point */
568
569  __MIPS_REGISTER_TYPE  tlbhi;    /* 72 - NOT FILLED IN, doesn't exist on */
570                                  /*         all MIPS CPUs (at least MGV) */
571#if __mips == 1
572  __MIPS_REGISTER_TYPE  tlblo;    /* 73 - NOT FILLED IN, doesn't exist on */
573                                  /*         all MIPS CPUs (at least MGV) */
574#endif
575#if  (__mips == 3) || (__mips == 32)
576  __MIPS_REGISTER_TYPE  tlblo0;   /* 73 - NOT FILLED IN, doesn't exist on */
577                                  /*         all MIPS CPUs (at least MGV) */
578#endif
579
580  __MIPS_REGISTER_TYPE  inx;      /* 74 -- NOT FILLED IN, doesn't exist on */
581                                  /*         all MIPS CPUs (at least MGV) */
582  __MIPS_REGISTER_TYPE  rand;     /* 75 -- NOT FILLED IN, doesn't exist on */
583                                  /*         all MIPS CPUs (at least MGV) */
584  __MIPS_REGISTER_TYPE  ctxt;     /* 76 -- NOT FILLED IN, doesn't exist on */
585                                  /*         all MIPS CPUs (at least MGV) */
586  __MIPS_REGISTER_TYPE  exctype;  /* 77 -- NOT FILLED IN (not enough info) */
587  __MIPS_REGISTER_TYPE  mode;     /* 78 -- NOT FILLED IN (not enough info) */
588  __MIPS_REGISTER_TYPE  prid;     /* 79 -- NOT FILLED IN (not need to do so) */
589  __MIPS_REGISTER_TYPE  tar ;     /* 80 -- target address register, filled on exceptions */
590  /* end of __mips == 1 so NREGS == 81 */
591#if  (__mips == 3) || (__mips == 32)
592  __MIPS_REGISTER_TYPE  tlblo1;   /* 81 -- NOT FILLED IN */
593  __MIPS_REGISTER_TYPE  pagemask; /* 82 -- NOT FILLED IN */
594  __MIPS_REGISTER_TYPE  wired;    /* 83 -- NOT FILLED IN */
595  __MIPS_REGISTER_TYPE  count;    /* 84 -- NOT FILLED IN */
596  __MIPS_REGISTER_TYPE  compare;  /* 85 -- NOT FILLED IN */
597  __MIPS_REGISTER_TYPE  config;   /* 86 -- NOT FILLED IN */
598  __MIPS_REGISTER_TYPE  lladdr;   /* 87 -- NOT FILLED IN */
599  __MIPS_REGISTER_TYPE  watchlo;  /* 88 -- NOT FILLED IN */
600  __MIPS_REGISTER_TYPE  watchhi;  /* 89 -- NOT FILLED IN */
601  __MIPS_REGISTER_TYPE  ecc;      /* 90 -- NOT FILLED IN */
602  __MIPS_REGISTER_TYPE  cacheerr; /* 91 -- NOT FILLED IN */
603  __MIPS_REGISTER_TYPE  taglo;    /* 92 -- NOT FILLED IN */
604  __MIPS_REGISTER_TYPE  taghi;    /* 93 -- NOT FILLED IN */
605  __MIPS_REGISTER_TYPE  errpc;    /* 94 -- NOT FILLED IN */
606  __MIPS_REGISTER_TYPE  xctxt;    /* 95 -- NOT FILLED IN */
607 /* end of __mips == 3 so NREGS == 96 */
608#endif
609
610} CPU_Interrupt_frame;
611
612/*
613 *  This variable is optional.  It is used on CPUs on which it is difficult
614 *  to generate an "uninitialized" FP context.  It is filled in by
615 *  _CPU_Initialize and copied into the task's FP context area during
616 *  _CPU_Context_Initialize.
617 */
618
619SCORE_EXTERN Context_Control_fp  _CPU_Null_fp_context;
620
621/*
622 *  Nothing prevents the porter from declaring more CPU specific variables.
623 */
624
625/* XXX: if needed, put more variables here */
626
627/*
628 *  The size of the floating point context area.  On some CPUs this
629 *  will not be a "sizeof" because the format of the floating point
630 *  area is not defined -- only the size is.  This is usually on
631 *  CPUs with a "floating point save context" instruction.
632 */
633
634#define CPU_CONTEXT_FP_SIZE sizeof( Context_Control_fp )
635
636/*
637 *  Amount of extra stack (above minimum stack size) required by
638 *  system initialization thread.  Remember that in a multiprocessor
639 *  system the system intialization thread becomes the MP server thread.
640 */
641
642#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
643
644/*
645 *  This defines the number of entries in the ISR_Vector_table managed
646 *  by RTEMS.
647 */
648
649extern unsigned int mips_interrupt_number_of_vectors;
650#define CPU_INTERRUPT_NUMBER_OF_VECTORS      (mips_interrupt_number_of_vectors)
651#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER  (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
652
653/*
654 *  Should be large enough to run all RTEMS tests.  This ensures
655 *  that a "reasonable" small application should not have any problems.
656 */
657
658#define CPU_STACK_MINIMUM_SIZE          (8 * 1024)
659
660/*
661 *  CPU's worst alignment requirement for data types on a byte boundary.  This
662 *  alignment does not take into account the requirements for the stack.
663 */
664
665#define CPU_ALIGNMENT              8
666
667/*
668 *  This number corresponds to the byte alignment requirement for the
669 *  heap handler.  This alignment requirement may be stricter than that
670 *  for the data types alignment specified by CPU_ALIGNMENT.  It is
671 *  common for the heap to follow the same alignment requirement as
672 *  CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict enough for the heap,
673 *  then this should be set to CPU_ALIGNMENT.
674 *
675 *  NOTE:  This does not have to be a power of 2.  It does have to
676 *         be greater or equal to than CPU_ALIGNMENT.
677 */
678
679#define CPU_HEAP_ALIGNMENT         CPU_ALIGNMENT
680
681/*
682 *  This number corresponds to the byte alignment requirement for memory
683 *  buffers allocated by the partition manager.  This alignment requirement
684 *  may be stricter than that for the data types alignment specified by
685 *  CPU_ALIGNMENT.  It is common for the partition to follow the same
686 *  alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict
687 *  enough for the partition, then this should be set to CPU_ALIGNMENT.
688 *
689 *  NOTE:  This does not have to be a power of 2.  It does have to
690 *         be greater or equal to than CPU_ALIGNMENT.
691 */
692
693#define CPU_PARTITION_ALIGNMENT    CPU_ALIGNMENT
694
695/*
696 *  This number corresponds to the byte alignment requirement for the
697 *  stack.  This alignment requirement may be stricter than that for the
698 *  data types alignment specified by CPU_ALIGNMENT.  If the CPU_ALIGNMENT
699 *  is strict enough for the stack, then this should be set to 0.
700 *
701 *  NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
702 */
703
704#define CPU_STACK_ALIGNMENT        CPU_ALIGNMENT
705
706/*
707 *  ISR handler macros
708 */
709
710/*
711 *  Declare the function that is present in the shared libcpu directory,
712 *  that returns the processor dependent interrupt mask.
713 */
714
715uint32_t mips_interrupt_mask( void );
716
717/*
718 *  Disable all interrupts for an RTEMS critical section.  The previous
719 *  level is returned in _level.
720 */
721
722#define _CPU_ISR_Disable( _level ) \
723  do { \
724    unsigned int _scratch; \
725    mips_get_sr( _scratch ); \
726    mips_set_sr( _scratch & ~SR_INTERRUPT_ENABLE_BITS ); \
727    _level = _scratch & SR_INTERRUPT_ENABLE_BITS; \
728  } while(0)
729
730/*
731 *  Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
732 *  This indicates the end of an RTEMS critical section.  The parameter
733 *  _level is not modified.
734 */
735
736#define _CPU_ISR_Enable( _level )  \
737  do { \
738    unsigned int _scratch; \
739    mips_get_sr( _scratch ); \
740    mips_set_sr( (_scratch & ~SR_INTERRUPT_ENABLE_BITS) | (_level & SR_INTERRUPT_ENABLE_BITS) ); \
741  } while(0)
742
743/*
744 *  This temporarily restores the interrupt to _level before immediately
745 *  disabling them again.  This is used to divide long RTEMS critical
746 *  sections into two or more parts.  The parameter _level is not
747 *  modified.
748 */
749
750#define _CPU_ISR_Flash( _xlevel ) \
751  do { \
752    unsigned int _scratch2 = _xlevel; \
753    _CPU_ISR_Enable( _scratch2 ); \
754    _CPU_ISR_Disable( _scratch2 ); \
755    _xlevel = _scratch2; \
756  } while(0)
757
758/*
759 *  Map interrupt level in task mode onto the hardware that the CPU
760 *  actually provides.  Currently, interrupt levels which do not
761 *  map onto the CPU in a generic fashion are undefined.  Someday,
762 *  it would be nice if these were "mapped" by the application
763 *  via a callout.  For example, m68k has 8 levels 0 - 7, levels
764 *  8 - 255 would be available for bsp/application specific meaning.
765 *  This could be used to manage a programmable interrupt controller
766 *  via the rtems_task_mode directive.
767 *
768 *  On the MIPS, 0 is all on.  Non-zero is all off.  This only
769 *  manipulates the IEC.
770 */
771
772uint32_t   _CPU_ISR_Get_level( void );  /* in cpu.c */
773
774void _CPU_ISR_Set_level( uint32_t   );  /* in cpu.c */
775
776/* end of ISR handler macros */
777
778/* Context handler macros */
779
780/*
781 *  Initialize the context to a state suitable for starting a
782 *  task after a context restore operation.  Generally, this
783 *  involves:
784 *
785 *     - setting a starting address
786 *     - preparing the stack
787 *     - preparing the stack and frame pointers
788 *     - setting the proper interrupt level in the context
789 *     - initializing the floating point context
790 *
791 *  This routine generally does not set any unnecessary register
792 *  in the context.  The state of the "general data" registers is
793 *  undefined at task start time.
794 *
795 *  NOTE: This is_fp parameter is TRUE if the thread is to be a floating
796 *        point thread.  This is typically only used on CPUs where the
797 *        FPU may be easily disabled by software such as on the SPARC
798 *        where the PSR contains an enable FPU bit.
799 *
800 *  The per-thread status register holds the interrupt enable, FP enable
801 *  and global interrupt enable for that thread.  It means each thread can
802 *  enable its own set of interrupts.  If interrupts are disabled, RTEMS
803 *  can still dispatch via blocking calls.  This is the function of the
804 *  "Interrupt Level", and on the MIPS, it controls the IEC bit and all
805 *  the hardware interrupts as defined in the SR.  Software ints
806 *  are automatically enabled for all threads, as they will only occur under
807 *  program control anyhow.  Besides, the interrupt level parm is only 8 bits,
808 *  and controlling the software ints plus the others would require 9.
809 *
810 *  If the Interrupt Level is 0, all ints are on.  Otherwise, the
811 *  Interrupt Level should supply a bit pattern to impose on the SR
812 *  interrupt bits; bit 0 applies to the mips1 IEC bit/mips3 EXL&IE, bits 1 thru 6
813 *  apply to the SR register Intr bits from bit 10 thru bit 15.  Bit 7 of
814 *  the Interrupt Level parameter is unused at this time.
815 *
816 *  These are the only per-thread SR bits, the others are maintained
817 *  globally & explicitly preserved by the Context Switch code in cpu_asm.s
818 */
819
820
821#if (__mips == 3) || (__mips == 32)
822#define _INTON          SR_IE
823#if __mips_fpr==64
824#define _EXTRABITS      SR_FR
825#else
826#define _EXTRABITS      0
827#endif /* __mips_fpr==64 */
828#endif /* __mips == 3 */
829#if __mips == 1
830#define _INTON          SR_IEC
831#define _EXTRABITS      0  /* make sure we're in user mode on MIPS1 processors */
832#endif /* __mips == 1 */
833
834
835void _CPU_Context_Initialize(
836  Context_Control  *the_context,
837  uintptr_t        *stack_base,
838  uint32_t          size,
839  uint32_t          new_level,
840  void             *entry_point,
841  bool              is_fp
842);
843
844
845/*
846 *  This routine is responsible for somehow restarting the currently
847 *  executing task.  If you are lucky, then all that is necessary
848 *  is restoring the context.  Otherwise, there will need to be
849 *  a special assembly routine which does something special in this
850 *  case.  Context_Restore should work most of the time.  It will
851 *  not work if restarting self conflicts with the stack frame
852 *  assumptions of restoring a context.
853 */
854
855#define _CPU_Context_Restart_self( _the_context ) \
856   _CPU_Context_restore( (_the_context) );
857
858/*
859 *  The purpose of this macro is to allow the initial pointer into
860 *  A floating point context area (used to save the floating point
861 *  context) to be at an arbitrary place in the floating point
862 *  context area.
863 *
864 *  This is necessary because some FP units are designed to have
865 *  their context saved as a stack which grows into lower addresses.
866 *  Other FP units can be saved by simply moving registers into offsets
867 *  from the base of the context area.  Finally some FP units provide
868 *  a "dump context" instruction which could fill in from high to low
869 *  or low to high based on the whim of the CPU designers.
870 */
871
872#define _CPU_Context_Fp_start( _base, _offset ) \
873   ( (void *) _Addresses_Add_offset( (_base), (_offset) ) )
874
875/*
876 *  This routine initializes the FP context area passed to it to.
877 *  There are a few standard ways in which to initialize the
878 *  floating point context.  The code included for this macro assumes
879 *  that this is a CPU in which a "initial" FP context was saved into
880 *  _CPU_Null_fp_context and it simply copies it to the destination
881 *  context passed to it.
882 *
883 *  Other models include (1) not doing anything, and (2) putting
884 *  a "null FP status word" in the correct place in the FP context.
885 */
886
887#if ( CPU_HARDWARE_FP == TRUE )
888#define _CPU_Context_Initialize_fp( _destination ) \
889  { \
890   *(*(_destination)) = _CPU_Null_fp_context; \
891  }
892#endif
893
894/* end of Context handler macros */
895
896/* Fatal Error manager macros */
897
898/*
899 *  This routine copies _error into a known place -- typically a stack
900 *  location or a register, optionally disables interrupts, and
901 *  halts/stops the CPU.
902 */
903
904#define _CPU_Fatal_halt( _error ) \
905  do { \
906    unsigned int _level; \
907    _CPU_ISR_Disable(_level); \
908    loop: goto loop; \
909  } while (0)
910
911
912extern void mips_break( int error );
913
914/* Bitfield handler macros */
915
916/*
917 *  This routine sets _output to the bit number of the first bit
918 *  set in _value.  _value is of CPU dependent type Priority_bit_map_Control.
919 *  This type may be either 16 or 32 bits wide although only the 16
920 *  least significant bits will be used.
921 *
922 *  There are a number of variables in using a "find first bit" type
923 *  instruction.
924 *
925 *    (1) What happens when run on a value of zero?
926 *    (2) Bits may be numbered from MSB to LSB or vice-versa.
927 *    (3) The numbering may be zero or one based.
928 *    (4) The "find first bit" instruction may search from MSB or LSB.
929 *
930 *  RTEMS guarantees that (1) will never happen so it is not a concern.
931 *  (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
932 *  _CPU_Priority_bits_index().  These three form a set of routines
933 *  which must logically operate together.  Bits in the _value are
934 *  set and cleared based on masks built by _CPU_Priority_mask().
935 *  The basic major and minor values calculated by _Priority_Major()
936 *  and _Priority_Minor() are "massaged" by _CPU_Priority_bits_index()
937 *  to properly range between the values returned by the "find first bit"
938 *  instruction.  This makes it possible for _Priority_Get_highest() to
939 *  calculate the major and directly index into the minor table.
940 *  This mapping is necessary to ensure that 0 (a high priority major/minor)
941 *  is the first bit found.
942 *
943 *  This entire "find first bit" and mapping process depends heavily
944 *  on the manner in which a priority is broken into a major and minor
945 *  components with the major being the 4 MSB of a priority and minor
946 *  the 4 LSB.  Thus (0 << 4) + 0 corresponds to priority 0 -- the highest
947 *  priority.  And (15 << 4) + 14 corresponds to priority 254 -- the next
948 *  to the lowest priority.
949 *
950 *  If your CPU does not have a "find first bit" instruction, then
951 *  there are ways to make do without it.  Here are a handful of ways
952 *  to implement this in software:
953 *
954 *    - a series of 16 bit test instructions
955 *    - a "binary search using if's"
956 *    - _number = 0
957 *      if _value > 0x00ff
958 *        _value >>=8
959 *        _number = 8;
960 *
961 *      if _value > 0x0000f
962 *        _value >=8
963 *        _number += 4
964 *
965 *      _number += bit_set_table[ _value ]
966 *
967 *    where bit_set_table[ 16 ] has values which indicate the first
968 *      bit set
969 */
970
971#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
972#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
973
974#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
975
976#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
977  { \
978    (_output) = 0;   /* do something to prevent warnings */ \
979  }
980
981#endif
982
983/* end of Bitfield handler macros */
984
985/*
986 *  This routine builds the mask which corresponds to the bit fields
987 *  as searched by _CPU_Bitfield_Find_first_bit().  See the discussion
988 *  for that routine.
989 */
990
991#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
992
993#define _CPU_Priority_Mask( _bit_number ) \
994  ( 1 << (_bit_number) )
995
996#endif
997
998/*
999 *  This routine translates the bit numbers returned by
1000 *  _CPU_Bitfield_Find_first_bit() into something suitable for use as
1001 *  a major or minor component of a priority.  See the discussion
1002 *  for that routine.
1003 */
1004
1005#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
1006
1007#define _CPU_Priority_bits_index( _priority ) \
1008  (_priority)
1009
1010#endif
1011
1012/* end of Priority handler macros */
1013
1014/* functions */
1015
1016/*
1017 *  _CPU_Initialize
1018 *
1019 *  This routine performs CPU dependent initialization.
1020 */
1021
1022void _CPU_Initialize(void);
1023
1024/*
1025 *  _CPU_ISR_install_raw_handler
1026 *
1027 *  This routine installs a "raw" interrupt handler directly into the
1028 *  processor's vector table.
1029 */
1030
1031void _CPU_ISR_install_raw_handler(
1032  uint32_t    vector,
1033  proc_ptr    new_handler,
1034  proc_ptr   *old_handler
1035);
1036
1037/*
1038 *  _CPU_ISR_install_vector
1039 *
1040 *  This routine installs an interrupt vector.
1041 */
1042
1043void _CPU_ISR_install_vector(
1044  uint32_t    vector,
1045  proc_ptr    new_handler,
1046  proc_ptr   *old_handler
1047);
1048
1049/*
1050 *  _CPU_Install_interrupt_stack
1051 *
1052 *  This routine installs the hardware interrupt stack pointer.
1053 *
1054 *  NOTE:  It need only be provided if CPU_HAS_HARDWARE_INTERRUPT_STACK
1055 *         is TRUE.
1056 */
1057
1058void _CPU_Install_interrupt_stack( void );
1059
1060/*
1061 *  _CPU_Internal_threads_Idle_thread_body
1062 *
1063 *  This routine is the CPU dependent IDLE thread body.
1064 *
1065 *  NOTE:  It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
1066 *         is TRUE.
1067 */
1068
1069void *_CPU_Thread_Idle_body( uintptr_t ignored );
1070
1071/*
1072 *  _CPU_Context_switch
1073 *
1074 *  This routine switches from the run context to the heir context.
1075 */
1076
1077void _CPU_Context_switch(
1078  Context_Control  *run,
1079  Context_Control  *heir
1080);
1081
1082/*
1083 *  _CPU_Context_restore
1084 *
1085 *  This routine is generally used only to restart self in an
1086 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
1087 *
1088 *  NOTE: May be unnecessary to reload some registers.
1089 */
1090
1091void _CPU_Context_restore(
1092  Context_Control *new_context
1093) RTEMS_COMPILER_NO_RETURN_ATTRIBUTE;
1094
1095/*
1096 *  _CPU_Context_save_fp
1097 *
1098 *  This routine saves the floating point context passed to it.
1099 */
1100
1101void _CPU_Context_save_fp(
1102  Context_Control_fp **fp_context_ptr
1103);
1104
1105/*
1106 *  _CPU_Context_restore_fp
1107 *
1108 *  This routine restores the floating point context passed to it.
1109 */
1110
1111void _CPU_Context_restore_fp(
1112  Context_Control_fp **fp_context_ptr
1113);
1114
1115/*  The following routine swaps the endian format of an unsigned int.
1116 *  It must be static because it is referenced indirectly.
1117 *
1118 *  This version will work on any processor, but if there is a better
1119 *  way for your CPU PLEASE use it.  The most common way to do this is to:
1120 *
1121 *     swap least significant two bytes with 16-bit rotate
1122 *     swap upper and lower 16-bits
1123 *     swap most significant two bytes with 16-bit rotate
1124 *
1125 *  Some CPUs have special instructions which swap a 32-bit quantity in
1126 *  a single instruction (e.g. i486).  It is probably best to avoid
1127 *  an "endian swapping control bit" in the CPU.  One good reason is
1128 *  that interrupts would probably have to be disabled to ensure that
1129 *  an interrupt does not try to access the same "chunk" with the wrong
1130 *  endian.  Another good reason is that on some CPUs, the endian bit
1131 *  endianness for ALL fetches -- both code and data -- so the code
1132 *  will be fetched incorrectly.
1133 */
1134
1135static inline uint32_t CPU_swap_u32(
1136  uint32_t value
1137)
1138{
1139  uint32_t   byte1, byte2, byte3, byte4, swapped;
1140
1141  byte4 = (value >> 24) & 0xff;
1142  byte3 = (value >> 16) & 0xff;
1143  byte2 = (value >> 8)  & 0xff;
1144  byte1 =  value        & 0xff;
1145
1146  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
1147  return( swapped );
1148}
1149
1150#define CPU_swap_u16( value ) \
1151  (((value&0xff) << 8) | ((value >> 8)&0xff))
1152
1153
1154#endif
1155
1156
1157
1158#ifdef __cplusplus
1159}
1160#endif
1161
1162#endif
Note: See TracBrowser for help on using the repository browser.