source: rtems/cpukit/score/cpu/or1k/include/rtems/score/cpu.h @ 141d502

5
Last change on this file since 141d502 was 42f2fdfd, checked in by Sebastian Huber <sebastian.huber@…>, on 07/20/18 at 05:56:43

score: Move context validation declarations

The context validation support functions _CPU_Context_validate() and
_CPU_Context_volatile_clobber() are used only by one test program
(spcontext01). Move the function declarations to the CPU port
implementation header file.

  • Property mode set to 100644
File size: 22.2 KB
Line 
1/**
2 * @file rtems/score/cpu.h
3 */
4
5/*
6 *  This include file contains macros pertaining to the Opencores
7 *  or1k processor family.
8 *
9 *  COPYRIGHT (c) 2014 Hesham ALMatary <heshamelmatary@gmail.com>
10 *  COPYRIGHT (c) 1989-1999.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 *
17 *  This file adapted from no_cpu example of the RTEMS distribution.
18 *  The body has been modified for the Opencores OR1k implementation by
19 *  Chris Ziomkowski. <chris@asics.ws>
20 *
21 */
22
23#ifndef _OR1K_CPU_H
24#define _OR1K_CPU_H
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30
31#include <rtems/score/or1k.h>            /* pick up machine definitions */
32#include <rtems/score/or1k-utility.h>
33#include <rtems/score/basedefs.h>
34#ifndef ASM
35#include <rtems/bspIo.h>
36#include <stdint.h>
37#include <stdio.h> /* for printk */
38#endif
39
40/* conditional compilation parameters */
41
42/*
43 *  Does the RTEMS invoke the user's ISR with the vector number and
44 *  a pointer to the saved interrupt frame (1) or just the vector
45 *  number (0)?
46 *
47 */
48
49#define CPU_ISR_PASSES_FRAME_POINTER TRUE
50
51/*
52 *  Does the CPU have hardware floating point?
53 *
54 *  If TRUE, then the RTEMS_FLOATING_POINT task attribute is supported.
55 *  If FALSE, then the RTEMS_FLOATING_POINT task attribute is ignored.
56 *
57 *  If there is a FP coprocessor such as the i387 or mc68881, then
58 *  the answer is TRUE.
59 *
60 *  The macro name "OR1K_HAS_FPU" should be made CPU specific.
61 *  It indicates whether or not this CPU model has FP support.  For
62 *  example, it would be possible to have an i386_nofp CPU model
63 *  which set this to false to indicate that you have an i386 without
64 *  an i387 and wish to leave floating point support out of RTEMS.
65 *
66 *  The CPU_SOFTWARE_FP is used to indicate whether or not there
67 *  is software implemented floating point that must be context
68 *  switched.  The determination of whether or not this applies
69 *  is very tool specific and the state saved/restored is also
70 *  compiler specific.
71 *
72 *  Or1k Specific Information:
73 *
74 *  At this time there are no implementations of Or1k that are
75 *  expected to implement floating point. More importantly, the
76 *  floating point architecture is expected to change significantly
77 *  before such chips are fabricated.
78 */
79
80#define CPU_HARDWARE_FP     FALSE
81#define CPU_SOFTWARE_FP     FALSE
82
83/*
84 *  Are all tasks RTEMS_FLOATING_POINT tasks implicitly?
85 *
86 *  If TRUE, then the RTEMS_FLOATING_POINT task attribute is assumed.
87 *  If FALSE, then the RTEMS_FLOATING_POINT task attribute is followed.
88 *
89 *  If CPU_HARDWARE_FP is FALSE, then this should be FALSE as well.
90 *
91 */
92
93#define CPU_ALL_TASKS_ARE_FP     FALSE
94
95/*
96 *  Should the IDLE task have a floating point context?
97 *
98 *  If TRUE, then the IDLE task is created as a RTEMS_FLOATING_POINT task
99 *  and it has a floating point context which is switched in and out.
100 *  If FALSE, then the IDLE task does not have a floating point context.
101 *
102 *  Setting this to TRUE negatively impacts the time required to preempt
103 *  the IDLE task from an interrupt because the floating point context
104 *  must be saved as part of the preemption.
105 *
106 */
107
108#define CPU_IDLE_TASK_IS_FP      FALSE
109
110/*
111 *  Should the saving of the floating point registers be deferred
112 *  until a context switch is made to another different floating point
113 *  task?
114 *
115 *  If TRUE, then the floating point context will not be stored until
116 *  necessary.  It will remain in the floating point registers and not
117 *  disturned until another floating point task is switched to.
118 *
119 *  If FALSE, then the floating point context is saved when a floating
120 *  point task is switched out and restored when the next floating point
121 *  task is restored.  The state of the floating point registers between
122 *  those two operations is not specified.
123 *
124 *  If the floating point context does NOT have to be saved as part of
125 *  interrupt dispatching, then it should be safe to set this to TRUE.
126 *
127 *  Setting this flag to TRUE results in using a different algorithm
128 *  for deciding when to save and restore the floating point context.
129 *  The deferred FP switch algorithm minimizes the number of times
130 *  the FP context is saved and restored.  The FP context is not saved
131 *  until a context switch is made to another, different FP task.
132 *  Thus in a system with only one FP task, the FP context will never
133 *  be saved or restored.
134 *
135 */
136
137#define CPU_USE_DEFERRED_FP_SWITCH       TRUE
138
139#define CPU_ENABLE_ROBUST_THREAD_DISPATCH FALSE
140
141/*
142 *  Does this port provide a CPU dependent IDLE task implementation?
143 *
144 *  If TRUE, then the routine _CPU_Thread_Idle_body
145 *  must be provided and is the default IDLE thread body instead of
146 *  _CPU_Thread_Idle_body.
147 *
148 *  If FALSE, then use the generic IDLE thread body if the BSP does
149 *  not provide one.
150 *
151 *  This is intended to allow for supporting processors which have
152 *  a low power or idle mode.  When the IDLE thread is executed, then
153 *  the CPU can be powered down.
154 *
155 *  The order of precedence for selecting the IDLE thread body is:
156 *
157 *    1.  BSP provided
158 *    2.  CPU dependent (if provided)
159 *    3.  generic (if no BSP and no CPU dependent)
160 *
161 */
162
163#define CPU_PROVIDES_IDLE_THREAD_BODY    TRUE
164
165/*
166 *  Does the stack grow up (toward higher addresses) or down
167 *  (toward lower addresses)?
168 *
169 *  If TRUE, then the grows upward.
170 *  If FALSE, then the grows toward smaller addresses.
171 *
172 */
173
174#define CPU_STACK_GROWS_UP               FALSE
175
176/* FIXME: Is this the right value? */
177#define CPU_CACHE_LINE_BYTES 32
178
179#define CPU_STRUCTURE_ALIGNMENT RTEMS_ALIGNED( CPU_CACHE_LINE_BYTES )
180
181/*
182 *  The following defines the number of bits actually used in the
183 *  interrupt field of the task mode.  How those bits map to the
184 *  CPU interrupt levels is defined by the routine _CPU_ISR_Set_level().
185 *
186 */
187
188#define CPU_MODES_INTERRUPT_MASK   0x00000001
189
190/*
191 *  Processor defined structures required for cpukit/score.
192 */
193
194
195/*
196 * Contexts
197 *
198 *  Generally there are 2 types of context to save.
199 *     1. Interrupt registers to save
200 *     2. Task level registers to save
201 *
202 *  This means we have the following 3 context items:
203 *     1. task level context stuff::  Context_Control
204 *     2. floating point task stuff:: Context_Control_fp
205 *     3. special interrupt level context :: Context_Control_interrupt
206 *
207 *  On some processors, it is cost-effective to save only the callee
208 *  preserved registers during a task context switch.  This means
209 *  that the ISR code needs to save those registers which do not
210 *  persist across function calls.  It is not mandatory to make this
211 *  distinctions between the caller/callee saves registers for the
212 *  purpose of minimizing context saved during task switch and on interrupts.
213 *  If the cost of saving extra registers is minimal, simplicity is the
214 *  choice.  Save the same context on interrupt entry as for tasks in
215 *  this case.
216 *
217 *  Additionally, if gdb is to be made aware of RTEMS tasks for this CPU, then
218 *  care should be used in designing the context area.
219 *
220 *  On some CPUs with hardware floating point support, the Context_Control_fp
221 *  structure will not be used or it simply consist of an array of a
222 *  fixed number of bytes.   This is done when the floating point context
223 *  is dumped by a "FP save context" type instruction and the format
224 *  is not really defined by the CPU.  In this case, there is no need
225 *  to figure out the exact format -- only the size.  Of course, although
226 *  this is enough information for RTEMS, it is probably not enough for
227 *  a debugger such as gdb.  But that is another problem.
228 *
229 *
230 */
231#ifndef ASM
232#ifdef OR1K_64BIT_ARCH
233#define or1kreg uint64_t
234#else
235#define or1kreg uint32_t
236#endif
237
238typedef struct {
239  uint32_t  r1;     /* Stack pointer */
240  uint32_t  r2;     /* Frame pointer */
241  uint32_t  r3;
242  uint32_t  r4;
243  uint32_t  r5;
244  uint32_t  r6;
245  uint32_t  r7;
246  uint32_t  r8;
247  uint32_t  r9;
248  uint32_t  r10;
249  uint32_t  r11;
250  uint32_t  r12;
251  uint32_t  r13;
252  uint32_t  r14;
253  uint32_t  r15;
254  uint32_t  r16;
255  uint32_t  r17;
256  uint32_t  r18;
257  uint32_t  r19;
258  uint32_t  r20;
259  uint32_t  r21;
260  uint32_t  r22;
261  uint32_t  r23;
262  uint32_t  r24;
263  uint32_t  r25;
264  uint32_t  r26;
265  uint32_t  r27;
266  uint32_t  r28;
267  uint32_t  r29;
268  uint32_t  r30;
269  uint32_t  r31;
270
271  uint32_t  sr;  /* Current supervision register non persistent values */
272  uint32_t  epcr;
273  uint32_t  eear;
274  uint32_t  esr;
275} Context_Control;
276
277#define _CPU_Context_Get_SP( _context ) \
278  (_context)->r1
279
280typedef struct {
281  /** FPU registers are listed here */
282  double      some_float_register;
283} Context_Control_fp;
284
285typedef Context_Control CPU_Interrupt_frame;
286
287/*
288 *  The size of the floating point context area.  On some CPUs this
289 *  will not be a "sizeof" because the format of the floating point
290 *  area is not defined -- only the size is.  This is usually on
291 *  CPUs with a "floating point save context" instruction.
292 *
293 *  Or1k Specific Information:
294 *
295 */
296
297#define CPU_CONTEXT_FP_SIZE  0
298
299/*
300 *  Amount of extra stack (above minimum stack size) required by
301 *  MPCI receive server thread.  Remember that in a multiprocessor
302 *  system this thread must exist and be able to process all directives.
303 *
304 */
305
306#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
307
308/*
309 *  Should be large enough to run all RTEMS tests.  This insures
310 *  that a "reasonable" small application should not have any problems.
311 *
312 */
313
314#define CPU_STACK_MINIMUM_SIZE  4096
315
316/*
317 *  CPU's worst alignment requirement for data types on a byte boundary.  This
318 *  alignment does not take into account the requirements for the stack.
319 *
320 */
321
322#define CPU_ALIGNMENT  8
323
324/*
325 *  This is defined if the port has a special way to report the ISR nesting
326 *  level.  Most ports maintain the variable _ISR_Nest_level.
327 */
328#define CPU_PROVIDES_ISR_IS_IN_PROGRESS FALSE
329
330/**
331 * Size of a pointer.
332 *
333 * This must be an integer literal that can be used by the assembler.  This
334 * value will be used to calculate offsets of structure members.  These
335 * offsets will be used in assembler code.
336 */
337#define CPU_SIZEOF_POINTER         4
338
339/*
340 *  This number corresponds to the byte alignment requirement for the
341 *  heap handler.  This alignment requirement may be stricter than that
342 *  for the data types alignment specified by CPU_ALIGNMENT.  It is
343 *  common for the heap to follow the same alignment requirement as
344 *  CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict enough for the heap,
345 *  then this should be set to CPU_ALIGNMENT.
346 *
347 *  NOTE:  This does not have to be a power of 2 although it should be
348 *         a multiple of 2 greater than or equal to 2.  The requirement
349 *         to be a multiple of 2 is because the heap uses the least
350 *         significant field of the front and back flags to indicate
351 *         that a block is in use or free.  So you do not want any odd
352 *         length blocks really putting length data in that bit.
353 *
354 *         On byte oriented architectures, CPU_HEAP_ALIGNMENT normally will
355 *         have to be greater or equal to than CPU_ALIGNMENT to ensure that
356 *         elements allocated from the heap meet all restrictions.
357 *
358 */
359
360#define CPU_HEAP_ALIGNMENT         CPU_ALIGNMENT
361
362/*
363 *  This number corresponds to the byte alignment requirement for memory
364 *  buffers allocated by the partition manager.  This alignment requirement
365 *  may be stricter than that for the data types alignment specified by
366 *  CPU_ALIGNMENT.  It is common for the partition to follow the same
367 *  alignment requirement as CPU_ALIGNMENT.  If the CPU_ALIGNMENT is strict
368 *  enough for the partition, then this should be set to CPU_ALIGNMENT.
369 *
370 *  NOTE:  This does not have to be a power of 2.  It does have to
371 *         be greater or equal to than CPU_ALIGNMENT.
372 *
373 */
374
375#define CPU_PARTITION_ALIGNMENT    CPU_ALIGNMENT
376
377/*
378 *  This number corresponds to the byte alignment requirement for the
379 *  stack.  This alignment requirement may be stricter than that for the
380 *  data types alignment specified by CPU_ALIGNMENT.  If the CPU_ALIGNMENT
381 *  is strict enough for the stack, then this should be set to 0.
382 *
383 *  NOTE:  This must be a power of 2 either 0 or greater than CPU_ALIGNMENT.
384 *
385 */
386
387#define CPU_STACK_ALIGNMENT        0
388
389#define CPU_INTERRUPT_STACK_ALIGNMENT CPU_CACHE_LINE_BYTES
390
391/* ISR handler macros */
392
393/*
394 *  Support routine to initialize the RTEMS vector table after it is allocated.
395 *
396 *  NO_CPU Specific Information:
397 *
398 *  XXX document implementation including references if appropriate
399 */
400
401#define _CPU_Initialize_vectors()
402
403/*
404 *  Disable all interrupts for an RTEMS critical section.  The previous
405 *  level is returned in _level.
406 *
407 */
408
409static inline uint32_t or1k_interrupt_disable( void )
410{
411  uint32_t sr;
412  sr = _OR1K_mfspr(CPU_OR1K_SPR_SR);
413
414  _OR1K_mtspr(CPU_OR1K_SPR_SR, (sr & ~CPU_OR1K_SPR_SR_IEE));
415
416  return sr;
417}
418
419static inline void or1k_interrupt_enable(uint32_t level)
420{
421  uint32_t sr;
422
423  /* Enable interrupts and restore rs */
424  sr = level | CPU_OR1K_SPR_SR_IEE | CPU_OR1K_SPR_SR_TEE;
425  _OR1K_mtspr(CPU_OR1K_SPR_SR, sr);
426
427}
428
429#define _CPU_ISR_Disable( _level ) \
430    _level = or1k_interrupt_disable()
431
432
433/*
434 *  Enable interrupts to the previous level (returned by _CPU_ISR_Disable).
435 *  This indicates the end of an RTEMS critical section.  The parameter
436 *  _level is not modified.
437 *
438 */
439
440#define _CPU_ISR_Enable( _level )  \
441  or1k_interrupt_enable( _level )
442
443/*
444 *  This temporarily restores the interrupt to _level before immediately
445 *  disabling them again.  This is used to divide long RTEMS critical
446 *  sections into two or more parts.  The parameter _level is not
447 *  modified.
448 *
449 */
450
451#define _CPU_ISR_Flash( _level ) \
452  do{ \
453      _CPU_ISR_Enable( _level ); \
454      _OR1K_mtspr(CPU_OR1K_SPR_SR, (_level & ~CPU_OR1K_SPR_SR_IEE)); \
455    } while(0)
456
457RTEMS_INLINE_ROUTINE bool _CPU_ISR_Is_enabled( uint32_t level )
458{
459  return ( level & CPU_OR1K_SPR_SR ) != 0;
460}
461
462/*
463 *  Map interrupt level in task mode onto the hardware that the CPU
464 *  actually provides.  Currently, interrupt levels which do not
465 *  map onto the CPU in a generic fashion are undefined.  Someday,
466 *  it would be nice if these were "mapped" by the application
467 *  via a callout.  For example, m68k has 8 levels 0 - 7, levels
468 *  8 - 255 would be available for bsp/application specific meaning.
469 *  This could be used to manage a programmable interrupt controller
470 *  via the rtems_task_mode directive.
471 *
472 *  The get routine usually must be implemented as a subroutine.
473 *
474 */
475
476void _CPU_ISR_Set_level( uint32_t level );
477
478uint32_t _CPU_ISR_Get_level( void );
479
480/* end of ISR handler macros */
481
482/* Context handler macros */
483
484#define OR1K_FAST_CONTEXT_SWITCH_ENABLED FALSE
485/*
486 *  Initialize the context to a state suitable for starting a
487 *  task after a context restore operation.  Generally, this
488 *  involves:
489 *
490 *     - setting a starting address
491 *     - preparing the stack
492 *     - preparing the stack and frame pointers
493 *     - setting the proper interrupt level in the context
494 *     - initializing the floating point context
495 *
496 *  This routine generally does not set any unnecessary register
497 *  in the context.  The state of the "general data" registers is
498 *  undefined at task start time.
499 *
500 *  NOTE: This is_fp parameter is TRUE if the thread is to be a floating
501 *        point thread.  This is typically only used on CPUs where the
502 *        FPU may be easily disabled by software such as on the SPARC
503 *        where the PSR contains an enable FPU bit.
504 *
505 */
506
507/**
508 * @brief Initializes the CPU context.
509 *
510 * The following steps are performed:
511 *  - setting a starting address
512 *  - preparing the stack
513 *  - preparing the stack and frame pointers
514 *  - setting the proper interrupt level in the context
515 *
516 * @param[in] context points to the context area
517 * @param[in] stack_area_begin is the low address of the allocated stack area
518 * @param[in] stack_area_size is the size of the stack area in bytes
519 * @param[in] new_level is the interrupt level for the task
520 * @param[in] entry_point is the task's entry point
521 * @param[in] is_fp is set to @c true if the task is a floating point task
522 * @param[in] tls_area is the thread-local storage (TLS) area
523 */
524void _CPU_Context_Initialize(
525  Context_Control *context,
526  void *stack_area_begin,
527  size_t stack_area_size,
528  uint32_t new_level,
529  void (*entry_point)( void ),
530  bool is_fp,
531  void *tls_area
532);
533
534/*
535 *  This routine is responsible for somehow restarting the currently
536 *  executing task.  If you are lucky, then all that is necessary
537 *  is restoring the context.  Otherwise, there will need to be
538 *  a special assembly routine which does something special in this
539 *  case.  Context_Restore should work most of the time.  It will
540 *  not work if restarting self conflicts with the stack frame
541 *  assumptions of restoring a context.
542 *
543 */
544
545#define _CPU_Context_Restart_self( _the_context ) \
546   _CPU_Context_restore( (_the_context) );
547
548/*
549 *  This routine is responsible to initialize the FP context.
550 *
551 *  The FP area pointer is passed by reference to allow the initial pointer
552 *  into a floating point context area (used to save the floating point
553 *  context) to be at an arbitrary place in the floating point context area.
554 *
555 *  This is necessary because some FP units are designed to have
556 *  their context saved as a stack which grows into lower addresses.
557 *  Other FP units can be saved by simply moving registers into offsets
558 *  from the base of the context area.  Finally some FP units provide
559 *  a "dump context" instruction which could fill in from high to low
560 *  or low to high based on the whim of the CPU designers.
561 */
562#define _CPU_Context_Initialize_fp( _fp_area_p ) \
563  memset( *( _fp_area_p ), 0, CPU_CONTEXT_FP_SIZE )
564
565/* end of Context handler macros */
566
567/* Fatal Error manager macros */
568
569/*
570 *  This routine copies _error into a known place -- typically a stack
571 *  location or a register, optionally disables interrupts, and
572 *  halts/stops the CPU.
573 *
574 */
575
576#include <inttypes.h>
577
578#define _CPU_Fatal_halt(_source, _error ) \
579        printk("Fatal Error %d.%" PRId32 " Halted\n",_source, _error); \
580        _OR1KSIM_CPU_Halt(); \
581        for(;;)
582
583/* end of Fatal Error manager macros */
584
585#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
586
587#endif /* ASM */
588
589#define CPU_SIZEOF_POINTER 4
590
591#define CPU_MAXIMUM_PROCESSORS 32
592
593#ifndef ASM
594typedef struct {
595  uint32_t r[32];
596
597  /* The following registers must be saved if we have
598  fast context switch disabled and nested interrupt
599  levels are enabled.
600  */
601#if !OR1K_FAST_CONTEXT_SWITCH_ENABLED
602  uint32_t epcr; /* exception PC register */
603  uint32_t eear; /* exception effective address register */
604  uint32_t esr; /* exception supervision register */
605#endif
606
607} CPU_Exception_frame;
608
609/**
610 * @brief Prints the exception frame via printk().
611 *
612 * @see rtems_fatal() and RTEMS_FATAL_SOURCE_EXCEPTION.
613 */
614void _CPU_Exception_frame_print( const CPU_Exception_frame *frame );
615
616
617/* end of Priority handler macros */
618
619/* functions */
620
621/*
622 *  _CPU_Initialize
623 *
624 *  This routine performs CPU dependent initialization.
625 *
626 */
627
628void _CPU_Initialize(
629  void
630);
631
632/*
633 *  _CPU_ISR_install_raw_handler
634 *
635 *  This routine installs a "raw" interrupt handler directly into the
636 *  processor's vector table.
637 *
638 */
639
640void _CPU_ISR_install_raw_handler(
641  uint32_t    vector,
642  proc_ptr    new_handler,
643  proc_ptr   *old_handler
644);
645
646/*
647 *  _CPU_ISR_install_vector
648 *
649 *  This routine installs an interrupt vector.
650 *
651 *  NO_CPU Specific Information:
652 *
653 *  XXX document implementation including references if appropriate
654 */
655
656void _CPU_ISR_install_vector(
657  uint32_t    vector,
658  proc_ptr   new_handler,
659  proc_ptr   *old_handler
660);
661
662/*
663 *  _CPU_Thread_Idle_body
664 *
665 *  This routine is the CPU dependent IDLE thread body.
666 *
667 *  NOTE:  It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY
668 *         is TRUE.
669 *
670 */
671
672void *_CPU_Thread_Idle_body( uintptr_t ignored );
673
674/*
675 *  _CPU_Context_switch
676 *
677 *  This routine switches from the run context to the heir context.
678 *
679 *  Or1k Specific Information:
680 *
681 *  Please see the comments in the .c file for a description of how
682 *  this function works. There are several things to be aware of.
683 */
684
685void _CPU_Context_switch(
686  Context_Control  *run,
687  Context_Control  *heir
688);
689
690/*
691 *  _CPU_Context_restore
692 *
693 *  This routine is generally used only to restart self in an
694 *  efficient manner.  It may simply be a label in _CPU_Context_switch.
695 *
696 *  NOTE: May be unnecessary to reload some registers.
697 *
698 */
699
700void _CPU_Context_restore(
701  Context_Control *new_context
702) RTEMS_NO_RETURN;
703
704/*
705 *  _CPU_Context_save_fp
706 *
707 *  This routine saves the floating point context passed to it.
708 *
709 */
710
711void _CPU_Context_save_fp(
712  void **fp_context_ptr
713);
714
715/*
716 *  _CPU_Context_restore_fp
717 *
718 *  This routine restores the floating point context passed to it.
719 *
720 */
721
722void _CPU_Context_restore_fp(
723  void **fp_context_ptr
724);
725
726/*  The following routine swaps the endian format of an unsigned int.
727 *  It must be static because it is referenced indirectly.
728 *
729 *  This version will work on any processor, but if there is a better
730 *  way for your CPU PLEASE use it.  The most common way to do this is to:
731 *
732 *     swap least significant two bytes with 16-bit rotate
733 *     swap upper and lower 16-bits
734 *     swap most significant two bytes with 16-bit rotate
735 *
736 *  Some CPUs have special instructions which swap a 32-bit quantity in
737 *  a single instruction (e.g. i486).  It is probably best to avoid
738 *  an "endian swapping control bit" in the CPU.  One good reason is
739 *  that interrupts would probably have to be disabled to insure that
740 *  an interrupt does not try to access the same "chunk" with the wrong
741 *  endian.  Another good reason is that on some CPUs, the endian bit
742 *  endianness for ALL fetches -- both code and data -- so the code
743 *  will be fetched incorrectly.
744 *
745 */
746
747static inline unsigned int CPU_swap_u32(
748  unsigned int value
749)
750{
751  uint32_t   byte1, byte2, byte3, byte4, swapped;
752
753  byte4 = (value >> 24) & 0xff;
754  byte3 = (value >> 16) & 0xff;
755  byte2 = (value >> 8)  & 0xff;
756  byte1 =  value        & 0xff;
757
758  swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
759  return( swapped );
760}
761
762#define CPU_swap_u16( value ) \
763  (((value&0xff) << 8) | ((value >> 8)&0xff))
764
765typedef uint32_t CPU_Counter_ticks;
766
767uint32_t _CPU_Counter_frequency( void );
768
769CPU_Counter_ticks _CPU_Counter_read( void );
770
771CPU_Counter_ticks _CPU_Counter_difference(
772  CPU_Counter_ticks second,
773  CPU_Counter_ticks first
774);
775
776/** Type that can store a 32-bit integer or a pointer. */
777typedef uintptr_t CPU_Uint32ptr;
778
779#endif /* ASM */
780
781#ifdef __cplusplus
782}
783#endif
784
785#endif
Note: See TracBrowser for help on using the repository browser.