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

4.11
Last change on this file since 0e27119 was 0e27119, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 11, 2012 at 8:52:18 PM

Use proper 3 line form of license text

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