1  /* Facilities specific to the PowerPC architecture
       2     Copyright (C) 2012-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #ifndef _SYS_PLATFORM_PPC_H
      20  #define _SYS_PLATFORM_PPC_H	1
      21  
      22  #include <features.h>
      23  #include <stdint.h>
      24  #include <bits/ppc.h>
      25  
      26  /* Read the Time Base Register.   */
      27  static __inline__ uint64_t
      28  __ppc_get_timebase (void)
      29  {
      30  #if __GNUC_PREREQ (4, 8)
      31    return __builtin_ppc_get_timebase ();
      32  #else
      33  # ifdef __powerpc64__
      34    uint64_t __tb;
      35    /* "volatile" is necessary here, because the user expects this assembly
      36       isn't moved after an optimization.  */
      37    __asm__ volatile ("mfspr %0, 268" : "=r" (__tb));
      38    return __tb;
      39  # else  /* not __powerpc64__ */
      40    uint32_t __tbu, __tbl, __tmp; \
      41    __asm__ volatile ("0:\n\t"
      42  		    "mftbu %0\n\t"
      43  		    "mftbl %1\n\t"
      44  		    "mftbu %2\n\t"
      45  		    "cmpw %0, %2\n\t"
      46  		    "bne- 0b"
      47  		    : "=r" (__tbu), "=r" (__tbl), "=r" (__tmp));
      48    return (((uint64_t) __tbu << 32) | __tbl);
      49  # endif  /* not __powerpc64__ */
      50  #endif
      51  }
      52  
      53  /* The following functions provide hints about the usage of shared processor
      54     resources, as defined in ISA 2.06 and newer. */
      55  
      56  /* Provides a hint that performance will probably be improved if shared
      57     resources dedicated to the executing processor are released for use by other
      58     processors.  */
      59  static __inline__ void
      60  __ppc_yield (void)
      61  {
      62    __asm__ volatile ("or 27,27,27");
      63  }
      64  
      65  /* Provides a hint that performance will probably be improved if shared
      66     resources dedicated to the executing processor are released until
      67     all outstanding storage accesses to caching-inhibited storage have been
      68     completed.  */
      69  static __inline__ void
      70  __ppc_mdoio (void)
      71  {
      72    __asm__ volatile ("or 29,29,29");
      73  }
      74  
      75  /* Provides a hint that performance will probably be improved if shared
      76     resources dedicated to the executing processor are released until all
      77     outstanding storage accesses to cacheable storage for which the data is not
      78     in the cache have been completed.  */
      79  static __inline__ void
      80  __ppc_mdoom (void)
      81  {
      82    __asm__ volatile ("or 30,30,30");
      83  }
      84  
      85  
      86  /* ISA 2.05 and beyond support the Program Priority Register (PPR) to adjust
      87     thread priorities based on lock acquisition, wait and release. The ISA
      88     defines the use of form 'or Rx,Rx,Rx' as the way to modify the PRI field.
      89     The unprivileged priorities are:
      90       Rx = 1 (low)
      91       Rx = 2 (medium)
      92       Rx = 6 (medium-low/normal)
      93     The 'or' instruction form is a nop in previous hardware, so it is safe to
      94     use unguarded. The default value is 'medium'.
      95   */
      96  
      97  static __inline__ void
      98  __ppc_set_ppr_med (void)
      99  {
     100    __asm__ volatile ("or 2,2,2");
     101  }
     102  
     103  static __inline__ void
     104  __ppc_set_ppr_med_low (void)
     105  {
     106    __asm__ volatile ("or 6,6,6");
     107  }
     108  
     109  static __inline__ void
     110  __ppc_set_ppr_low (void)
     111  {
     112    __asm__ volatile ("or 1,1,1");
     113  }
     114  
     115  /* Power ISA 2.07 (Book II, Chapter 3) extends the priorities that can be set
     116     to the Program Priority Register (PPR).  The form 'or Rx,Rx,Rx' is used to
     117     modify the PRI field of the PPR, the same way as described above.
     118     The new priority levels are:
     119       Rx = 31 (very low)
     120       Rx = 5 (medium high)
     121     Any program can set the priority to very low, low, medium low, and medium,
     122     as these are unprivileged.
     123     The medium high priority, on the other hand, is privileged, and may only be
     124     set during certain time intervals by problem-state programs.  If the program
     125     priority is medium high when the time interval expires or if an attempt is
     126     made to set the priority to medium high when it is not allowed, the PRI
     127     field is set to medium.
     128   */
     129  
     130  #ifdef _ARCH_PWR8
     131  
     132  static __inline__ void
     133  __ppc_set_ppr_very_low (void)
     134  {
     135    __asm__ volatile ("or 31,31,31");
     136  }
     137  
     138  static __inline__ void
     139  __ppc_set_ppr_med_high (void)
     140  {
     141    __asm__ volatile ("or 5,5,5");
     142  }
     143  
     144  #endif
     145  
     146  #endif  /* sys/platform/ppc.h */