source: rtems/c/src/lib/libcpu/powerpc/shared/include/powerpc-utility.h @ c6c998b

4.115
Last change on this file since c6c998b was c6c998b, checked in by Sebastian Huber <sebastian.huber@…>, on 08/01/13 at 14:36:55

bsps/powerpc: Per-CPU thread dispatch disable

Interrupt support for per-CPU thread dispatch disable level.

  • Property mode set to 100644
File size: 18.1 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup powerpc_shared
5 *
6 * @brief General purpose assembler macros, linker command file support and
7 * some inline functions for direct register access.
8 */
9
10/*
11 * Copyright (c) 2008-2013 embedded brains GmbH.
12 *
13 *  embedded brains GmbH
14 *  Dornierstr. 4
15 *  82178 Puchheim
16 *  Germany
17 *  <rtems@embedded-brains.de>
18 *
19 * access function for Device Control Registers inspired by "ppc405common.h"
20 * from Michael Hamel ADInstruments May 2008
21 *
22 * The license and distribution terms for this file may be
23 * found in the file LICENSE in this distribution or at
24 * http://www.rtems.com/license/LICENSE.
25 */
26
27/**
28 * @defgroup powerpc_shared Shared PowerPC Code
29 */
30
31#ifndef __LIBCPU_POWERPC_UTILITY_H
32#define __LIBCPU_POWERPC_UTILITY_H
33
34#if !defined(ASM)
35  #include <rtems.h>
36#endif
37
38#include <rtems/score/cpu.h>
39#include <rtems/powerpc/registers.h>
40#include <rtems/powerpc/powerpc.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46#if !defined(ASM)
47
48#include <rtems/bspIo.h>
49#include <rtems/system.h>
50
51#include <libcpu/cpuIdent.h>
52
53#define LINKER_SYMBOL(sym) extern char sym [];
54
55/**
56 * @brief Read one byte from @a src.
57 */
58static inline uint8_t ppc_read_byte(const volatile void *src)
59{
60  uint8_t value;
61
62  __asm__ volatile (
63    "lbz %0, 0(%1)"
64    : "=r" (value)
65    : "b" (src)
66  );
67
68  return value;
69}
70
71/**
72 * @brief Read one half word from @a src.
73 */
74static inline uint16_t ppc_read_half_word(const volatile void *src)
75{
76  uint16_t value;
77
78  __asm__ volatile (
79    "lhz %0, 0(%1)"
80    : "=r" (value)
81    : "b" (src)
82  );
83
84  return value;
85}
86
87/**
88 * @brief Read one word from @a src.
89 */
90static inline uint32_t ppc_read_word(const volatile void *src)
91{
92  uint32_t value;
93
94  __asm__ volatile (
95    "lwz %0, 0(%1)"
96    : "=r" (value)
97    : "b" (src)
98  );
99
100  return value;
101}
102
103/**
104 * @brief Write one byte @a value to @a dest.
105 */
106static inline void ppc_write_byte(uint8_t value, volatile void *dest)
107{
108  __asm__ volatile (
109    "stb %0, 0(%1)"
110    :
111    : "r" (value), "b" (dest)
112  );
113}
114
115/**
116 * @brief Write one half word @a value to @a dest.
117 */
118static inline void ppc_write_half_word(uint16_t value, volatile void *dest)
119{
120  __asm__ volatile (
121    "sth %0, 0(%1)"
122    :
123    : "r" (value), "b" (dest)
124  );
125}
126
127/**
128 * @brief Write one word @a value to @a dest.
129 */
130static inline void ppc_write_word(uint32_t value, volatile void *dest)
131{
132  __asm__ volatile (
133    "stw %0, 0(%1)" :
134    : "r" (value), "b" (dest)
135  );
136}
137
138
139static inline void *ppc_stack_pointer(void)
140{
141  void *sp;
142
143  __asm__ volatile (
144    "mr %0, 1"
145    : "=r" (sp)
146  );
147
148  return sp;
149}
150
151static inline void ppc_set_stack_pointer(void *sp)
152{
153  __asm__ volatile (
154    "mr 1, %0"
155    :
156    : "r" (sp)
157  );
158}
159
160static inline void *ppc_link_register(void)
161{
162  void *lr;
163
164  __asm__ volatile (
165    "mflr %0"
166    : "=r" (lr)
167  );
168
169  return lr;
170}
171
172static inline void ppc_set_link_register(void *lr)
173{
174  __asm__ volatile (
175    "mtlr %0"
176    :
177    : "r" (lr)
178  );
179}
180
181static inline uint32_t ppc_machine_state_register(void)
182{
183  uint32_t msr;
184
185  __asm__ volatile (
186    "mfmsr %0"
187    : "=r" (msr)
188  );
189
190  return msr;
191}
192
193static inline void ppc_set_machine_state_register(uint32_t msr)
194{
195  __asm__ volatile (
196    "mtmsr %0"
197    :
198    : "r" (msr)
199  );
200}
201
202static inline void ppc_synchronize_data(void)
203{
204  RTEMS_COMPILER_MEMORY_BARRIER();
205
206  __asm__ volatile ("sync");
207}
208
209static inline void ppc_synchronize_instructions(void)
210{
211  RTEMS_COMPILER_MEMORY_BARRIER();
212
213  __asm__ volatile ("isync");
214}
215
216static inline void ppc_enforce_in_order_execution_of_io(void)
217{
218  RTEMS_COMPILER_MEMORY_BARRIER();
219
220  __asm__ volatile ("eieio");
221}
222
223static inline void ppc_data_cache_block_flush(void *addr)
224{
225  __asm__ volatile (
226    "dcbf 0, %0"
227    :
228    : "r" (addr)
229    : "memory"
230  );
231}
232
233static inline void ppc_data_cache_block_flush_2(
234  void *base,
235  uintptr_t offset
236)
237{
238  __asm__ volatile (
239    "dcbf %0, %1"
240    :
241    : "b" (base), "r" (offset)
242    : "memory"
243  );
244}
245
246static inline void ppc_data_cache_block_invalidate(void *addr)
247{
248  __asm__ volatile (
249    "dcbi 0, %0"
250    :
251    : "r" (addr)
252    : "memory"
253  );
254}
255
256static inline void ppc_data_cache_block_invalidate_2(
257  void *base,
258  uintptr_t offset
259)
260{
261  __asm__ volatile (
262    "dcbi %0, %1"
263    :
264    : "b" (base), "r" (offset)
265    : "memory"
266  );
267}
268
269static inline void ppc_data_cache_block_store(const void *addr)
270{
271  __asm__ volatile (
272    "dcbst 0, %0"
273    :
274    : "r" (addr)
275  );
276}
277
278static inline void ppc_data_cache_block_store_2(
279  const void *base,
280  uintptr_t offset
281)
282{
283  __asm__ volatile (
284    "dcbst %0, %1"
285    :
286    : "b" (base), "r" (offset)
287  );
288}
289
290static inline void ppc_data_cache_block_touch(const void *addr)
291{
292  __asm__ volatile (
293    "dcbt 0, %0"
294    :
295    : "r" (addr)
296  );
297}
298
299static inline void ppc_data_cache_block_touch_2(
300  const void *base,
301  uintptr_t offset
302)
303{
304  __asm__ volatile (
305    "dcbt %0, %1"
306    :
307    : "b" (base), "r" (offset)
308  );
309}
310
311static inline void ppc_data_cache_block_touch_for_store(const void *addr)
312{
313  __asm__ volatile (
314    "dcbtst 0, %0"
315    :
316    : "r" (addr)
317  );
318}
319
320static inline void ppc_data_cache_block_touch_for_store_2(
321  const void *base,
322  uintptr_t offset
323)
324{
325  __asm__ volatile (
326    "dcbtst %0, %1"
327    :
328    : "b" (base), "r" (offset)
329  );
330}
331
332static inline void ppc_data_cache_block_clear_to_zero(void *addr)
333{
334  __asm__ volatile (
335    "dcbz 0, %0"
336    :
337    : "r" (addr)
338    : "memory"
339  );
340}
341
342static inline void ppc_data_cache_block_clear_to_zero_2(
343  void *base,
344  uintptr_t offset
345)
346{
347  __asm__ volatile (
348    "dcbz %0, %1"
349    :
350    : "b" (base), "r" (offset)
351    : "memory"
352  );
353}
354
355static inline void ppc_instruction_cache_block_invalidate(void *addr)
356{
357  __asm__ volatile (
358    "icbi 0, %0"
359    :
360    : "r" (addr)
361  );
362}
363
364static inline void ppc_instruction_cache_block_invalidate_2(
365  void *base,
366  uintptr_t offset
367)
368{
369  __asm__ volatile (
370    "icbi %0, %1"
371    :
372    : "b" (base), "r" (offset)
373  );
374}
375
376/**
377 * @brief Enables external exceptions.
378 *
379 * You can use this function to enable the external exceptions and restore the
380 * machine state with ppc_external_exceptions_disable() later.
381 */
382static inline uint32_t ppc_external_exceptions_enable(void)
383{
384  uint32_t current_msr;
385  uint32_t new_msr;
386
387  RTEMS_COMPILER_MEMORY_BARRIER();
388
389  __asm__ volatile (
390    "mfmsr %0;"
391    "ori %1, %0, 0x8000;"
392    "mtmsr %1"
393    : "=r" (current_msr), "=r" (new_msr)
394  );
395
396  return current_msr;
397}
398
399/**
400 * @brief Restores machine state.
401 *
402 * @see ppc_external_exceptions_enable()
403 */
404static inline void ppc_external_exceptions_disable(uint32_t msr)
405{
406  ppc_set_machine_state_register(msr);
407
408  RTEMS_COMPILER_MEMORY_BARRIER();
409}
410
411static inline uint32_t ppc_count_leading_zeros(uint32_t value)
412{
413  uint32_t count;
414
415  __asm__ (
416    "cntlzw %0, %1;"
417    : "=r" (count)
418    : "r" (value)
419  );
420
421  return count;
422}
423
424/*
425 *  Simple spin delay in microsecond units for device drivers.
426 *  This is very dependent on the clock speed of the target.
427 */
428
429#if defined(mpx8xx) || defined(mpc860) || defined(mpc821)
430/* Wonderful bookE doesn't have mftb/mftbu; they only
431 * define the TBRU/TBRL SPRs so we use these. Luckily,
432 * we run in supervisory mode so that should work on
433 * all CPUs. In user mode we'd have a problem...
434 * 2007/11/30, T.S.
435 *
436 * OTOH, PSIM currently lacks support for reading
437 * SPRs 268/269. You need GDB patch sim/2376 to avoid
438 * a crash...
439 * OTOH, the MPC8xx do not allow to read the timebase registers via mfspr.
440 * we NEED a mftb to access the time base.
441 * 2009/10/30 Th. D.
442 */
443#define CPU_Get_timebase_low( _value ) \
444    __asm__ volatile( "mftb  %0" : "=r" (_value) )
445#else
446#define CPU_Get_timebase_low( _value ) \
447    __asm__ volatile( "mfspr %0,268" : "=r" (_value) )
448#endif
449
450/* Must be provided for rtems_bsp_delay to work */
451extern     uint32_t bsp_clicks_per_usec;
452
453#define rtems_bsp_delay( _microseconds ) \
454  do { \
455    uint32_t   start, ticks, now; \
456    CPU_Get_timebase_low( start ) ; \
457    ticks = (_microseconds) * bsp_clicks_per_usec; \
458    do \
459      CPU_Get_timebase_low( now ) ; \
460    while (now - start < ticks); \
461  } while (0)
462
463#define rtems_bsp_delay_in_bus_cycles( _cycles ) \
464  do { \
465    uint32_t   start, now; \
466    CPU_Get_timebase_low( start ); \
467    do \
468      CPU_Get_timebase_low( now ); \
469    while (now - start < (_cycles)); \
470  } while (0)
471
472/*
473 *  Routines to access the decrementer register
474 */
475
476#define PPC_Set_decrementer( _clicks ) \
477  do { \
478    __asm__ volatile( "mtdec %0" : : "r" ((_clicks)) ); \
479  } while (0)
480
481#define PPC_Get_decrementer( _clicks ) \
482    __asm__ volatile( "mfdec  %0" : "=r" (_clicks) )
483
484/*
485 *  Routines to access the time base register
486 */
487
488static inline uint64_t PPC_Get_timebase_register( void )
489{
490  uint32_t tbr_low;
491  uint32_t tbr_high;
492  uint32_t tbr_high_old;
493  uint64_t tbr;
494
495  do {
496#if defined(mpx8xx) || defined(mpc860) || defined(mpc821)
497/* See comment above (CPU_Get_timebase_low) */
498    __asm__ volatile( "mftbu %0" : "=r" (tbr_high_old));
499    __asm__ volatile( "mftb  %0" : "=r" (tbr_low));
500    __asm__ volatile( "mftbu %0" : "=r" (tbr_high));
501#else
502    __asm__ volatile( "mfspr %0, 269" : "=r" (tbr_high_old));
503    __asm__ volatile( "mfspr %0, 268" : "=r" (tbr_low));
504    __asm__ volatile( "mfspr %0, 269" : "=r" (tbr_high));
505#endif
506  } while ( tbr_high_old != tbr_high );
507
508  tbr = tbr_high;
509  tbr <<= 32;
510  tbr |= tbr_low;
511  return tbr;
512}
513
514static inline  void PPC_Set_timebase_register (uint64_t tbr)
515{
516  uint32_t tbr_low;
517  uint32_t tbr_high;
518
519  tbr_low = (uint32_t) tbr;
520  tbr_high = (uint32_t) (tbr >> 32);
521  __asm__ volatile( "mtspr 284, %0" : : "r" (tbr_low));
522  __asm__ volatile( "mtspr 285, %0" : : "r" (tbr_high));
523
524}
525
526static inline uint32_t ppc_decrementer_register(void)
527{
528  uint32_t dec;
529
530  PPC_Get_decrementer(dec);
531
532  return dec;
533}
534
535static inline void ppc_set_decrementer_register(uint32_t dec)
536{
537  PPC_Set_decrementer(dec);
538}
539
540/**
541 * @brief Preprocessor magic for stringification of @a x.
542 */
543#define PPC_STRINGOF(x) #x
544
545/**
546 * @brief Returns the value of the Special Purpose Register with number @a spr.
547 *
548 * @note This macro uses a GNU C extension.
549 */
550#define PPC_SPECIAL_PURPOSE_REGISTER(spr) \
551  ({ \
552    uint32_t val; \
553    __asm__ volatile (\
554      "mfspr %0, " PPC_STRINGOF(spr) \
555      : "=r" (val) \
556    ); \
557    val;\
558  } )
559
560/**
561 * @brief Sets the Special Purpose Register with number @a spr to the value in
562 * @a val.
563 */
564#define PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val) \
565  do { \
566    __asm__ volatile (\
567      "mtspr " PPC_STRINGOF(spr) ", %0" \
568      : \
569      : "r" (val) \
570    ); \
571  } while (0)
572
573/**
574 * @brief Sets in the Special Purpose Register with number @a spr all bits
575 * which are set in @a bits.
576 *
577 * Interrupts are disabled throughout this operation.
578 */
579#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(spr, bits) \
580  do { \
581    rtems_interrupt_level level; \
582    uint32_t val; \
583    uint32_t mybits = bits; \
584    rtems_interrupt_disable(level); \
585    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
586    val |= mybits; \
587    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
588    rtems_interrupt_enable(level); \
589  } while (0)
590
591/**
592 * @brief Sets in the Special Purpose Register with number @a spr all bits
593 * which are set in @a bits.  The previous register value will be masked with
594 * @a mask.
595 *
596 * Interrupts are disabled throughout this operation.
597 */
598#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS_MASKED(spr, bits, mask) \
599  do { \
600    rtems_interrupt_level level; \
601    uint32_t val; \
602    uint32_t mybits = bits; \
603    uint32_t mymask = mask; \
604    rtems_interrupt_disable(level); \
605    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
606    val &= ~mymask; \
607    val |= mybits; \
608    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
609    rtems_interrupt_enable(level); \
610  } while (0)
611
612/**
613 * @brief Clears in the Special Purpose Register with number @a spr all bits
614 * which are set in @a bits.
615 *
616 * Interrupts are disabled throughout this operation.
617 */
618#define PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(spr, bits) \
619  do { \
620    rtems_interrupt_level level; \
621    uint32_t val; \
622    uint32_t mybits = bits; \
623    rtems_interrupt_disable(level); \
624    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
625    val &= ~mybits; \
626    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
627    rtems_interrupt_enable(level); \
628  } while (0)
629
630/**
631 * @brief Returns the value of the Device Control Register with number @a dcr.
632 *
633 * The PowerPC 4XX family has Device Control Registers.
634 *
635 * @note This macro uses a GNU C extension.
636 */
637#define PPC_DEVICE_CONTROL_REGISTER(dcr) \
638  ({ \
639    uint32_t val; \
640    __asm__ volatile (\
641      "mfdcr %0, " PPC_STRINGOF(dcr) \
642      : "=r" (val) \
643    ); \
644    val;\
645  } )
646
647/**
648 * @brief Sets the Device Control Register with number @a dcr to the value in
649 * @a val.
650 *
651 * The PowerPC 4XX family has Device Control Registers.
652 */
653#define PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val) \
654  do { \
655    __asm__ volatile (\
656      "mtdcr " PPC_STRINGOF(dcr) ", %0" \
657      : \
658      : "r" (val) \
659    ); \
660  } while (0)
661
662/**
663 * @brief Sets in the Device Control Register with number @a dcr all bits
664 * which are set in @a bits.
665 *
666 * Interrupts are disabled throughout this operation.
667 */
668#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS(dcr, bits) \
669  do { \
670    rtems_interrupt_level level; \
671    uint32_t val; \
672    uint32_t mybits = bits; \
673    rtems_interrupt_disable(level); \
674    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
675    val |= mybits; \
676    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
677    rtems_interrupt_enable(level); \
678  } while (0)
679
680/**
681 * @brief Sets in the Device Control Register with number @a dcr all bits
682 * which are set in @a bits.  The previous register value will be masked with
683 * @a mask.
684 *
685 * Interrupts are disabled throughout this operation.
686 */
687#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS_MASKED(dcr, bits, mask) \
688  do { \
689    rtems_interrupt_level level; \
690    uint32_t val; \
691    uint32_t mybits = bits; \
692    uint32_t mymask = mask; \
693    rtems_interrupt_disable(level); \
694    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
695    val &= ~mymask; \
696    val |= mybits; \
697    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
698    rtems_interrupt_enable(level); \
699  } while (0)
700
701/**
702 * @brief Clears in the Device Control Register with number @a dcr all bits
703 * which are set in @a bits.
704 *
705 * Interrupts are disabled throughout this operation.
706 */
707#define PPC_CLEAR_DEVICE_CONTROL_REGISTER_BITS(dcr, bits) \
708  do { \
709    rtems_interrupt_level level; \
710    uint32_t val; \
711    uint32_t mybits = bits; \
712    rtems_interrupt_disable(level); \
713    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
714    val &= ~mybits; \
715    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
716    rtems_interrupt_enable(level); \
717  } while (0)
718
719static inline uint32_t ppc_time_base(void)
720{
721  uint32_t val;
722
723  CPU_Get_timebase_low(val);
724
725  return val;
726}
727
728static inline void ppc_set_time_base(uint32_t val)
729{
730  PPC_SET_SPECIAL_PURPOSE_REGISTER(TBWL, val);
731}
732
733static inline uint32_t ppc_time_base_upper(void)
734{
735  return PPC_SPECIAL_PURPOSE_REGISTER(TBRU);
736}
737
738static inline void ppc_set_time_base_upper(uint32_t val)
739{
740  PPC_SET_SPECIAL_PURPOSE_REGISTER(TBWU, val);
741}
742
743static inline uint64_t ppc_time_base_64(void)
744{
745  return PPC_Get_timebase_register();
746}
747
748static inline void ppc_set_time_base_64(uint64_t val)
749{
750  PPC_Set_timebase_register(val);
751}
752
753static inline uint32_t ppc_alternate_time_base(void)
754{
755  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_ATBL);
756}
757
758static inline uint32_t ppc_alternate_time_base_upper(void)
759{
760  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_ATBU);
761}
762
763static inline uint64_t ppc_alternate_time_base_64(void)
764{
765  uint32_t atbl;
766  uint32_t atbu_0;
767  uint32_t atbu_1;
768
769  do {
770    atbu_0 = ppc_alternate_time_base_upper();
771    atbl = ppc_alternate_time_base();
772    atbu_1 = ppc_alternate_time_base_upper();
773  } while (atbu_0 != atbu_1);
774
775  return (((uint64_t) atbu_1) << 32) | ((uint64_t) atbl);
776}
777
778static inline uint32_t ppc_processor_id(void)
779{
780  return PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR);
781}
782
783static inline void ppc_set_processor_id(uint32_t val)
784{
785  PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, val);
786}
787
788static inline uint32_t ppc_fsl_system_version(void)
789{
790  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_SVR);
791}
792
793static inline uint32_t ppc_fsl_system_version_cid(uint32_t svr)
794{
795  return (svr >> 28) & 0xf;
796}
797
798static inline uint32_t ppc_fsl_system_version_sid(uint32_t svr)
799{
800  return (svr >> 16) & 0xfff;
801}
802
803static inline uint32_t ppc_fsl_system_version_proc(uint32_t svr)
804{
805  return (svr >> 12) & 0xf;
806}
807
808static inline uint32_t ppc_fsl_system_version_mfg(uint32_t svr)
809{
810  return (svr >> 8) & 0xf;
811}
812
813static inline uint32_t ppc_fsl_system_version_mjrev(uint32_t svr)
814{
815  return (svr >> 4) & 0xf;
816}
817
818static inline uint32_t ppc_fsl_system_version_mnrev(uint32_t svr)
819{
820  return (svr >> 0) & 0xf;
821}
822
823void ppc_code_copy(void *dest, const void *src, size_t n);
824
825#endif /* ifndef ASM */
826
827#if defined(ASM)
828#include <rtems/asm.h>
829
830.macro LA reg, addr
831        lis     \reg, (\addr)@h
832        ori     \reg, \reg, (\addr)@l
833.endm
834
835.macro LWI reg, value
836        lis \reg, (\value)@h
837        ori     \reg, \reg, (\value)@l
838.endm
839
840.macro LW reg, addr
841        lis     \reg, \addr@ha
842        lwz     \reg, \addr@l(\reg)
843.endm
844
845/*
846 * Tests the bits in reg1 against the bits set in mask.  A match is indicated
847 * by EQ = 0 in CR0.  A mismatch is indicated by EQ = 1 in CR0.  The register
848 * reg2 is used to load the mask.
849 */
850.macro  TSTBITS reg1, reg2, mask
851        LWI     \reg2, \mask
852        and     \reg1, \reg1, \reg2
853        cmplw   \reg1, \reg2
854.endm
855
856.macro  SETBITS reg1, reg2, mask
857        LWI     \reg2, \mask
858        or      \reg1, \reg1, \reg2
859.endm
860
861.macro  CLRBITS reg1, reg2, mask
862        LWI     \reg2, \mask
863        andc    \reg1, \reg1, \reg2
864.endm
865
866.macro GLOBAL_FUNCTION name
867        .global \name
868        .type \name, @function
869\name:
870.endm
871
872/*
873 * Obtain interrupt mask
874 */
875.macro GET_INTERRUPT_MASK mask
876        mfspr   \mask, sprg0
877.endm
878
879/*
880 * Disables all asynchronous exeptions (interrupts) which may cause a context
881 * switch.
882 */
883.macro INTERRUPT_DISABLE level, mask
884        mfmsr   \level
885        GET_INTERRUPT_MASK mask=\mask
886        andc    \mask, \level, \mask
887        mtmsr   \mask
888.endm
889
890/*
891 * Restore previous machine state.
892 */
893.macro INTERRUPT_ENABLE level
894        mtmsr   \level
895.endm
896
897.macro GET_SELF_CPU_CONTROL reg
898#if defined(RTEMS_SMP)
899        /* Use Book E Processor ID Register (PIR) */
900        mfspr   \reg, 286
901        slwi    \reg, \reg, PER_CPU_CONTROL_SIZE_LOG2
902        addis   \reg, \reg, _Per_CPU_Information@ha
903        addi    \reg, \reg, _Per_CPU_Information@l
904#else
905        lis     \reg, _Per_CPU_Information@h
906        ori     \reg, \reg, _Per_CPU_Information@l
907#endif
908.endm
909
910#define LINKER_SYMBOL(sym) .extern sym
911
912#endif /* ASM */
913
914#ifdef __cplusplus
915}
916#endif
917
918#endif /* __LIBCPU_POWERPC_UTILITY_H */
Note: See TracBrowser for help on using the repository browser.