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

4.115
Last change on this file since 4fe3ad2 was 4fe3ad2, checked in by Sebastian Huber <sebastian.huber@…>, on 07/09/13 at 14:37:32

bsps/powerpc: Add ppc_count_leading_zeros()

  • Property mode set to 100644
File size: 17.7 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
410static inline uint32_t ppc_count_leading_zeros(uint32_t value)
411{
412  uint32_t count;
413
414  __asm__ (
415    "cntlzw %0, %1;"
416    : "=r" (count)
417    : "r" (value)
418  );
419
420  return count;
421}
422
423/*
424 *  Simple spin delay in microsecond units for device drivers.
425 *  This is very dependent on the clock speed of the target.
426 */
427
428#if defined(mpx8xx) || defined(mpc860) || defined(mpc821)
429/* Wonderful bookE doesn't have mftb/mftbu; they only
430 * define the TBRU/TBRL SPRs so we use these. Luckily,
431 * we run in supervisory mode so that should work on
432 * all CPUs. In user mode we'd have a problem...
433 * 2007/11/30, T.S.
434 *
435 * OTOH, PSIM currently lacks support for reading
436 * SPRs 268/269. You need GDB patch sim/2376 to avoid
437 * a crash...
438 * OTOH, the MPC8xx do not allow to read the timebase registers via mfspr.
439 * we NEED a mftb to access the time base.
440 * 2009/10/30 Th. D.
441 */
442#define CPU_Get_timebase_low( _value ) \
443    __asm__ volatile( "mftb  %0" : "=r" (_value) )
444#else
445#define CPU_Get_timebase_low( _value ) \
446    __asm__ volatile( "mfspr %0,268" : "=r" (_value) )
447#endif
448
449/* Must be provided for rtems_bsp_delay to work */
450extern     uint32_t bsp_clicks_per_usec;
451
452#define rtems_bsp_delay( _microseconds ) \
453  do { \
454    uint32_t   start, ticks, now; \
455    CPU_Get_timebase_low( start ) ; \
456    ticks = (_microseconds) * bsp_clicks_per_usec; \
457    do \
458      CPU_Get_timebase_low( now ) ; \
459    while (now - start < ticks); \
460  } while (0)
461
462#define rtems_bsp_delay_in_bus_cycles( _cycles ) \
463  do { \
464    uint32_t   start, now; \
465    CPU_Get_timebase_low( start ); \
466    do \
467      CPU_Get_timebase_low( now ); \
468    while (now - start < (_cycles)); \
469  } while (0)
470
471/*
472 *  Routines to access the decrementer register
473 */
474
475#define PPC_Set_decrementer( _clicks ) \
476  do { \
477    __asm__ volatile( "mtdec %0" : : "r" ((_clicks)) ); \
478  } while (0)
479
480#define PPC_Get_decrementer( _clicks ) \
481    __asm__ volatile( "mfdec  %0" : "=r" (_clicks) )
482
483/*
484 *  Routines to access the time base register
485 */
486
487static inline uint64_t PPC_Get_timebase_register( void )
488{
489  uint32_t tbr_low;
490  uint32_t tbr_high;
491  uint32_t tbr_high_old;
492  uint64_t tbr;
493
494  do {
495#if defined(mpx8xx) || defined(mpc860) || defined(mpc821)
496/* See comment above (CPU_Get_timebase_low) */
497    __asm__ volatile( "mftbu %0" : "=r" (tbr_high_old));
498    __asm__ volatile( "mftb  %0" : "=r" (tbr_low));
499    __asm__ volatile( "mftbu %0" : "=r" (tbr_high));
500#else
501    __asm__ volatile( "mfspr %0, 269" : "=r" (tbr_high_old));
502    __asm__ volatile( "mfspr %0, 268" : "=r" (tbr_low));
503    __asm__ volatile( "mfspr %0, 269" : "=r" (tbr_high));
504#endif
505  } while ( tbr_high_old != tbr_high );
506
507  tbr = tbr_high;
508  tbr <<= 32;
509  tbr |= tbr_low;
510  return tbr;
511}
512
513static inline  void PPC_Set_timebase_register (uint64_t tbr)
514{
515  uint32_t tbr_low;
516  uint32_t tbr_high;
517
518  tbr_low = (uint32_t) tbr;
519  tbr_high = (uint32_t) (tbr >> 32);
520  __asm__ volatile( "mtspr 284, %0" : : "r" (tbr_low));
521  __asm__ volatile( "mtspr 285, %0" : : "r" (tbr_high));
522
523}
524
525static inline uint32_t ppc_decrementer_register(void)
526{
527  uint32_t dec;
528
529  PPC_Get_decrementer(dec);
530
531  return dec;
532}
533
534static inline void ppc_set_decrementer_register(uint32_t dec)
535{
536  PPC_Set_decrementer(dec);
537}
538
539/**
540 * @brief Preprocessor magic for stringification of @a x.
541 */
542#define PPC_STRINGOF(x) #x
543
544/**
545 * @brief Returns the value of the Special Purpose Register with number @a spr.
546 *
547 * @note This macro uses a GNU C extension.
548 */
549#define PPC_SPECIAL_PURPOSE_REGISTER(spr) \
550  ({ \
551    uint32_t val; \
552    __asm__ volatile (\
553      "mfspr %0, " PPC_STRINGOF(spr) \
554      : "=r" (val) \
555    ); \
556    val;\
557  } )
558
559/**
560 * @brief Sets the Special Purpose Register with number @a spr to the value in
561 * @a val.
562 */
563#define PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val) \
564  do { \
565    __asm__ volatile (\
566      "mtspr " PPC_STRINGOF(spr) ", %0" \
567      : \
568      : "r" (val) \
569    ); \
570  } while (0)
571
572/**
573 * @brief Sets in the Special Purpose Register with number @a spr all bits
574 * which are set in @a bits.
575 *
576 * Interrupts are disabled throughout this operation.
577 */
578#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(spr, bits) \
579  do { \
580    rtems_interrupt_level level; \
581    uint32_t val; \
582    uint32_t mybits = bits; \
583    rtems_interrupt_disable(level); \
584    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
585    val |= mybits; \
586    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
587    rtems_interrupt_enable(level); \
588  } while (0)
589
590/**
591 * @brief Sets in the Special Purpose Register with number @a spr all bits
592 * which are set in @a bits.  The previous register value will be masked with
593 * @a mask.
594 *
595 * Interrupts are disabled throughout this operation.
596 */
597#define PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS_MASKED(spr, bits, mask) \
598  do { \
599    rtems_interrupt_level level; \
600    uint32_t val; \
601    uint32_t mybits = bits; \
602    uint32_t mymask = mask; \
603    rtems_interrupt_disable(level); \
604    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
605    val &= ~mymask; \
606    val |= mybits; \
607    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
608    rtems_interrupt_enable(level); \
609  } while (0)
610
611/**
612 * @brief Clears in the Special Purpose Register with number @a spr all bits
613 * which are set in @a bits.
614 *
615 * Interrupts are disabled throughout this operation.
616 */
617#define PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(spr, bits) \
618  do { \
619    rtems_interrupt_level level; \
620    uint32_t val; \
621    uint32_t mybits = bits; \
622    rtems_interrupt_disable(level); \
623    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
624    val &= ~mybits; \
625    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
626    rtems_interrupt_enable(level); \
627  } while (0)
628
629/**
630 * @brief Returns the value of the Device Control Register with number @a dcr.
631 *
632 * The PowerPC 4XX family has Device Control Registers.
633 *
634 * @note This macro uses a GNU C extension.
635 */
636#define PPC_DEVICE_CONTROL_REGISTER(dcr) \
637  ({ \
638    uint32_t val; \
639    __asm__ volatile (\
640      "mfdcr %0, " PPC_STRINGOF(dcr) \
641      : "=r" (val) \
642    ); \
643    val;\
644  } )
645
646/**
647 * @brief Sets the Device Control Register with number @a dcr to the value in
648 * @a val.
649 *
650 * The PowerPC 4XX family has Device Control Registers.
651 */
652#define PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val) \
653  do { \
654    __asm__ volatile (\
655      "mtdcr " PPC_STRINGOF(dcr) ", %0" \
656      : \
657      : "r" (val) \
658    ); \
659  } while (0)
660
661/**
662 * @brief Sets in the Device Control Register with number @a dcr all bits
663 * which are set in @a bits.
664 *
665 * Interrupts are disabled throughout this operation.
666 */
667#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS(dcr, bits) \
668  do { \
669    rtems_interrupt_level level; \
670    uint32_t val; \
671    uint32_t mybits = bits; \
672    rtems_interrupt_disable(level); \
673    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
674    val |= mybits; \
675    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
676    rtems_interrupt_enable(level); \
677  } while (0)
678
679/**
680 * @brief Sets in the Device Control Register with number @a dcr all bits
681 * which are set in @a bits.  The previous register value will be masked with
682 * @a mask.
683 *
684 * Interrupts are disabled throughout this operation.
685 */
686#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS_MASKED(dcr, bits, mask) \
687  do { \
688    rtems_interrupt_level level; \
689    uint32_t val; \
690    uint32_t mybits = bits; \
691    uint32_t mymask = mask; \
692    rtems_interrupt_disable(level); \
693    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
694    val &= ~mymask; \
695    val |= mybits; \
696    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
697    rtems_interrupt_enable(level); \
698  } while (0)
699
700/**
701 * @brief Clears in the Device Control Register with number @a dcr all bits
702 * which are set in @a bits.
703 *
704 * Interrupts are disabled throughout this operation.
705 */
706#define PPC_CLEAR_DEVICE_CONTROL_REGISTER_BITS(dcr, bits) \
707  do { \
708    rtems_interrupt_level level; \
709    uint32_t val; \
710    uint32_t mybits = bits; \
711    rtems_interrupt_disable(level); \
712    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
713    val &= ~mybits; \
714    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
715    rtems_interrupt_enable(level); \
716  } while (0)
717
718static inline uint32_t ppc_time_base(void)
719{
720  uint32_t val;
721
722  CPU_Get_timebase_low(val);
723
724  return val;
725}
726
727static inline void ppc_set_time_base(uint32_t val)
728{
729  PPC_SET_SPECIAL_PURPOSE_REGISTER(TBWL, val);
730}
731
732static inline uint32_t ppc_time_base_upper(void)
733{
734  return PPC_SPECIAL_PURPOSE_REGISTER(TBRU);
735}
736
737static inline void ppc_set_time_base_upper(uint32_t val)
738{
739  PPC_SET_SPECIAL_PURPOSE_REGISTER(TBWU, val);
740}
741
742static inline uint64_t ppc_time_base_64(void)
743{
744  return PPC_Get_timebase_register();
745}
746
747static inline void ppc_set_time_base_64(uint64_t val)
748{
749  PPC_Set_timebase_register(val);
750}
751
752static inline uint32_t ppc_alternate_time_base(void)
753{
754  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_ATBL);
755}
756
757static inline uint32_t ppc_alternate_time_base_upper(void)
758{
759  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_ATBU);
760}
761
762static inline uint64_t ppc_alternate_time_base_64(void)
763{
764  uint32_t atbl;
765  uint32_t atbu_0;
766  uint32_t atbu_1;
767
768  do {
769    atbu_0 = ppc_alternate_time_base_upper();
770    atbl = ppc_alternate_time_base();
771    atbu_1 = ppc_alternate_time_base_upper();
772  } while (atbu_0 != atbu_1);
773
774  return (((uint64_t) atbu_1) << 32) | ((uint64_t) atbl);
775}
776
777static inline uint32_t ppc_processor_id(void)
778{
779  return PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR);
780}
781
782static inline void ppc_set_processor_id(uint32_t val)
783{
784  PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, val);
785}
786
787static inline uint32_t ppc_fsl_system_version(void)
788{
789  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_SVR);
790}
791
792static inline uint32_t ppc_fsl_system_version_cid(uint32_t svr)
793{
794  return (svr >> 28) & 0xf;
795}
796
797static inline uint32_t ppc_fsl_system_version_sid(uint32_t svr)
798{
799  return (svr >> 16) & 0xfff;
800}
801
802static inline uint32_t ppc_fsl_system_version_proc(uint32_t svr)
803{
804  return (svr >> 12) & 0xf;
805}
806
807static inline uint32_t ppc_fsl_system_version_mfg(uint32_t svr)
808{
809  return (svr >> 8) & 0xf;
810}
811
812static inline uint32_t ppc_fsl_system_version_mjrev(uint32_t svr)
813{
814  return (svr >> 4) & 0xf;
815}
816
817static inline uint32_t ppc_fsl_system_version_mnrev(uint32_t svr)
818{
819  return (svr >> 0) & 0xf;
820}
821
822void ppc_code_copy(void *dest, const void *src, size_t n);
823
824#endif /* ifndef ASM */
825
826#if defined(ASM)
827#include <rtems/asm.h>
828
829.macro LA reg, addr
830        lis     \reg, (\addr)@h
831        ori     \reg, \reg, (\addr)@l
832.endm
833
834.macro LWI reg, value
835        lis \reg, (\value)@h
836        ori     \reg, \reg, (\value)@l
837.endm
838
839.macro LW reg, addr
840        lis     \reg, \addr@ha
841        lwz     \reg, \addr@l(\reg)
842.endm
843
844/*
845 * Tests the bits in reg1 against the bits set in mask.  A match is indicated
846 * by EQ = 0 in CR0.  A mismatch is indicated by EQ = 1 in CR0.  The register
847 * reg2 is used to load the mask.
848 */
849.macro  TSTBITS reg1, reg2, mask
850        LWI     \reg2, \mask
851        and     \reg1, \reg1, \reg2
852        cmplw   \reg1, \reg2
853.endm
854
855.macro  SETBITS reg1, reg2, mask
856        LWI     \reg2, \mask
857        or      \reg1, \reg1, \reg2
858.endm
859
860.macro  CLRBITS reg1, reg2, mask
861        LWI     \reg2, \mask
862        andc    \reg1, \reg1, \reg2
863.endm
864
865.macro GLOBAL_FUNCTION name
866        .global \name
867        .type \name, @function
868\name:
869.endm
870
871/*
872 * Obtain interrupt mask
873 */
874.macro GET_INTERRUPT_MASK mask
875        mfspr   \mask, sprg0
876.endm
877
878/*
879 * Disables all asynchronous exeptions (interrupts) which may cause a context
880 * switch.
881 */
882.macro INTERRUPT_DISABLE level, mask
883        mfmsr   \level
884        GET_INTERRUPT_MASK mask=\mask
885        andc    \mask, \level, \mask
886        mtmsr   \mask
887.endm
888
889/*
890 * Restore previous machine state.
891 */
892.macro INTERRUPT_ENABLE level
893        mtmsr   \level
894.endm
895
896#define LINKER_SYMBOL(sym) .extern sym
897
898#endif /* ASM */
899
900#ifdef __cplusplus
901}
902#endif
903
904#endif /* __LIBCPU_POWERPC_UTILITY_H */
Note: See TracBrowser for help on using the repository browser.