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

4.115
Last change on this file since 7bad672 was 7bad672, checked in by Sebastian Huber <sebastian.huber@…>, on 12/23/14 at 07:30:40

bsps/powerpc: Add TMR access macros

  • Property mode set to 100644
File size: 18.8 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-2014 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.org/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    ISR_Level level; \
582    uint32_t val; \
583    uint32_t mybits = bits; \
584    _ISR_Disable_without_giant(level); \
585    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
586    val |= mybits; \
587    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
588    _ISR_Enable_without_giant(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    ISR_Level level; \
601    uint32_t val; \
602    uint32_t mybits = bits; \
603    uint32_t mymask = mask; \
604    _ISR_Disable_without_giant(level); \
605    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
606    val &= ~mymask; \
607    val |= mybits; \
608    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
609    _ISR_Enable_without_giant(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    ISR_Level level; \
621    uint32_t val; \
622    uint32_t mybits = bits; \
623    _ISR_Disable_without_giant(level); \
624    val = PPC_SPECIAL_PURPOSE_REGISTER(spr); \
625    val &= ~mybits; \
626    PPC_SET_SPECIAL_PURPOSE_REGISTER(spr, val); \
627    _ISR_Enable_without_giant(level); \
628  } while (0)
629
630/**
631 * @brief Returns the value of the Thread Management Register with number @a tmr.
632 *
633 * @note This macro uses a GNU C extension.
634 */
635#define PPC_THREAD_MGMT_REGISTER(tmr) \
636  ({ \
637    uint32_t val; \
638    __asm__ volatile (\
639      "mftmr %0, " PPC_STRINGOF(tmr) \
640      : "=r" (val) \
641    ); \
642    val;\
643  } )
644
645/**
646 * @brief Sets the Thread Management Register with number @a tmr to the value in
647 * @a val.
648 */
649#define PPC_SET_THREAD_MGMT_REGISTER(tmr, val) \
650  do { \
651    __asm__ volatile (\
652      "mttmr " PPC_STRINGOF(tmr) ", %0" \
653      : \
654      : "r" (val) \
655    ); \
656  } while (0)
657
658/**
659 * @brief Returns the value of the Device Control Register with number @a dcr.
660 *
661 * The PowerPC 4XX family has Device Control Registers.
662 *
663 * @note This macro uses a GNU C extension.
664 */
665#define PPC_DEVICE_CONTROL_REGISTER(dcr) \
666  ({ \
667    uint32_t val; \
668    __asm__ volatile (\
669      "mfdcr %0, " PPC_STRINGOF(dcr) \
670      : "=r" (val) \
671    ); \
672    val;\
673  } )
674
675/**
676 * @brief Sets the Device Control Register with number @a dcr to the value in
677 * @a val.
678 *
679 * The PowerPC 4XX family has Device Control Registers.
680 */
681#define PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val) \
682  do { \
683    __asm__ volatile (\
684      "mtdcr " PPC_STRINGOF(dcr) ", %0" \
685      : \
686      : "r" (val) \
687    ); \
688  } while (0)
689
690/**
691 * @brief Sets in the Device Control Register with number @a dcr all bits
692 * which are set in @a bits.
693 *
694 * Interrupts are disabled throughout this operation.
695 */
696#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS(dcr, bits) \
697  do { \
698    ISR_Level level; \
699    uint32_t val; \
700    uint32_t mybits = bits; \
701    _ISR_Disable_without_giant(level); \
702    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
703    val |= mybits; \
704    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
705    _ISR_Enable_without_giant(level); \
706  } while (0)
707
708/**
709 * @brief Sets in the Device Control Register with number @a dcr all bits
710 * which are set in @a bits.  The previous register value will be masked with
711 * @a mask.
712 *
713 * Interrupts are disabled throughout this operation.
714 */
715#define PPC_SET_DEVICE_CONTROL_REGISTER_BITS_MASKED(dcr, bits, mask) \
716  do { \
717    ISR_Level level; \
718    uint32_t val; \
719    uint32_t mybits = bits; \
720    uint32_t mymask = mask; \
721    _ISR_Disable_without_giant(level); \
722    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
723    val &= ~mymask; \
724    val |= mybits; \
725    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
726    _ISR_Enable_without_giant(level); \
727  } while (0)
728
729/**
730 * @brief Clears in the Device Control Register with number @a dcr all bits
731 * which are set in @a bits.
732 *
733 * Interrupts are disabled throughout this operation.
734 */
735#define PPC_CLEAR_DEVICE_CONTROL_REGISTER_BITS(dcr, bits) \
736  do { \
737    ISR_Level level; \
738    uint32_t val; \
739    uint32_t mybits = bits; \
740    _ISR_Disable_without_giant(level); \
741    val = PPC_DEVICE_CONTROL_REGISTER(dcr); \
742    val &= ~mybits; \
743    PPC_SET_DEVICE_CONTROL_REGISTER(dcr, val); \
744    _ISR_Enable_without_giant(level); \
745  } while (0)
746
747static inline uint32_t ppc_time_base(void)
748{
749  uint32_t val;
750
751  CPU_Get_timebase_low(val);
752
753  return val;
754}
755
756static inline void ppc_set_time_base(uint32_t val)
757{
758  PPC_SET_SPECIAL_PURPOSE_REGISTER(TBWL, val);
759}
760
761static inline uint32_t ppc_time_base_upper(void)
762{
763  return PPC_SPECIAL_PURPOSE_REGISTER(TBRU);
764}
765
766static inline void ppc_set_time_base_upper(uint32_t val)
767{
768  PPC_SET_SPECIAL_PURPOSE_REGISTER(TBWU, val);
769}
770
771static inline uint64_t ppc_time_base_64(void)
772{
773  return PPC_Get_timebase_register();
774}
775
776static inline void ppc_set_time_base_64(uint64_t val)
777{
778  PPC_Set_timebase_register(val);
779}
780
781static inline uint32_t ppc_alternate_time_base(void)
782{
783  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_ATBL);
784}
785
786static inline uint32_t ppc_alternate_time_base_upper(void)
787{
788  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_ATBU);
789}
790
791static inline uint64_t ppc_alternate_time_base_64(void)
792{
793  uint32_t atbl;
794  uint32_t atbu_0;
795  uint32_t atbu_1;
796
797  do {
798    atbu_0 = ppc_alternate_time_base_upper();
799    atbl = ppc_alternate_time_base();
800    atbu_1 = ppc_alternate_time_base_upper();
801  } while (atbu_0 != atbu_1);
802
803  return (((uint64_t) atbu_1) << 32) | ((uint64_t) atbl);
804}
805
806static inline uint32_t ppc_processor_id(void)
807{
808  return PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR);
809}
810
811static inline void ppc_set_processor_id(uint32_t val)
812{
813  PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, val);
814}
815
816static inline uint32_t ppc_fsl_system_version(void)
817{
818  return PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_SVR);
819}
820
821static inline uint32_t ppc_fsl_system_version_cid(uint32_t svr)
822{
823  return (svr >> 28) & 0xf;
824}
825
826static inline uint32_t ppc_fsl_system_version_sid(uint32_t svr)
827{
828  return (svr >> 16) & 0xfff;
829}
830
831static inline uint32_t ppc_fsl_system_version_proc(uint32_t svr)
832{
833  return (svr >> 12) & 0xf;
834}
835
836static inline uint32_t ppc_fsl_system_version_mfg(uint32_t svr)
837{
838  return (svr >> 8) & 0xf;
839}
840
841static inline uint32_t ppc_fsl_system_version_mjrev(uint32_t svr)
842{
843  return (svr >> 4) & 0xf;
844}
845
846static inline uint32_t ppc_fsl_system_version_mnrev(uint32_t svr)
847{
848  return (svr >> 0) & 0xf;
849}
850
851void ppc_code_copy(void *dest, const void *src, size_t n);
852
853/* FIXME: Do not use this function */
854void printBAT(int bat, uint32_t upper, uint32_t lower);
855
856/* FIXME: Do not use this function */
857void ShowBATS(void);
858
859#endif /* ifndef ASM */
860
861#if defined(ASM)
862#include <rtems/asm.h>
863
864.macro LA reg, addr
865        lis     \reg, (\addr)@h
866        ori     \reg, \reg, (\addr)@l
867.endm
868
869.macro LWI reg, value
870        lis \reg, (\value)@h
871        ori     \reg, \reg, (\value)@l
872.endm
873
874.macro LW reg, addr
875        lis     \reg, \addr@ha
876        lwz     \reg, \addr@l(\reg)
877.endm
878
879/*
880 * Tests the bits in reg1 against the bits set in mask.  A match is indicated
881 * by EQ = 0 in CR0.  A mismatch is indicated by EQ = 1 in CR0.  The register
882 * reg2 is used to load the mask.
883 */
884.macro  TSTBITS reg1, reg2, mask
885        LWI     \reg2, \mask
886        and     \reg1, \reg1, \reg2
887        cmplw   \reg1, \reg2
888.endm
889
890.macro  SETBITS reg1, reg2, mask
891        LWI     \reg2, \mask
892        or      \reg1, \reg1, \reg2
893.endm
894
895.macro  CLRBITS reg1, reg2, mask
896        LWI     \reg2, \mask
897        andc    \reg1, \reg1, \reg2
898.endm
899
900.macro GLOBAL_FUNCTION name
901        .global \name
902        .type \name, @function
903\name:
904.endm
905
906/*
907 * Obtain interrupt mask
908 */
909.macro GET_INTERRUPT_MASK mask
910        lis     \mask, _PPC_INTERRUPT_DISABLE_MASK@h
911        ori     \mask, \mask, _PPC_INTERRUPT_DISABLE_MASK@l
912.endm
913
914/*
915 * Disables all asynchronous exeptions (interrupts) which may cause a context
916 * switch.
917 */
918.macro INTERRUPT_DISABLE level, mask
919        mfmsr   \level
920        GET_INTERRUPT_MASK mask=\mask
921        andc    \mask, \level, \mask
922        mtmsr   \mask
923.endm
924
925/*
926 * Restore previous machine state.
927 */
928.macro INTERRUPT_ENABLE level
929        mtmsr   \level
930.endm
931
932.macro GET_SELF_CPU_CONTROL reg
933#if defined(RTEMS_SMP)
934        /* Use Book E Processor ID Register (PIR) */
935        mfspr   \reg, 286
936        slwi    \reg, \reg, PER_CPU_CONTROL_SIZE_LOG2
937        addis   \reg, \reg, _Per_CPU_Information@ha
938        addi    \reg, \reg, _Per_CPU_Information@l
939#else
940        lis     \reg, _Per_CPU_Information@h
941        ori     \reg, \reg, _Per_CPU_Information@l
942#endif
943.endm
944
945#define LINKER_SYMBOL(sym) .extern sym
946
947#endif /* ASM */
948
949#ifdef __cplusplus
950}
951#endif
952
953#endif /* __LIBCPU_POWERPC_UTILITY_H */
Note: See TracBrowser for help on using the repository browser.