github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/runtime/internal/sys/intrinsics_common.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package sys
     6  
     7  // Copied from math/bits to avoid dependence.
     8  
     9  const len8tab = "" +
    10  	"\x00\x01\x02\x02\x03\x03\x03\x03\x04\x04\x04\x04\x04\x04\x04\x04" +
    11  	"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" +
    12  	"\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" +
    13  	"\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" +
    14  	"\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
    15  	"\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
    16  	"\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
    17  	"\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07" +
    18  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    19  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    20  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    21  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    22  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    23  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    24  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08" +
    25  	"\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08"
    26  
    27  // len64 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
    28  //
    29  // nosplit because this is used in src/runtime/histogram.go, which make run in sensitive contexts.
    30  //
    31  //go:nosplit
    32  func Len64(x uint64) (n int) {
    33  	if x >= 1<<32 {
    34  		x >>= 32
    35  		n = 32
    36  	}
    37  	if x >= 1<<16 {
    38  		x >>= 16
    39  		n += 16
    40  	}
    41  	if x >= 1<<8 {
    42  		x >>= 8
    43  		n += 8
    44  	}
    45  	return n + int(len8tab[x])
    46  }
    47  
    48  // --- OnesCount ---
    49  
    50  const m0 = 0x5555555555555555 // 01010101 ...
    51  const m1 = 0x3333333333333333 // 00110011 ...
    52  const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ...
    53  
    54  // OnesCount64 returns the number of one bits ("population count") in x.
    55  func OnesCount64(x uint64) int {
    56  	// Implementation: Parallel summing of adjacent bits.
    57  	// See "Hacker's Delight", Chap. 5: Counting Bits.
    58  	// The following pattern shows the general approach:
    59  	//
    60  	//   x = x>>1&(m0&m) + x&(m0&m)
    61  	//   x = x>>2&(m1&m) + x&(m1&m)
    62  	//   x = x>>4&(m2&m) + x&(m2&m)
    63  	//   x = x>>8&(m3&m) + x&(m3&m)
    64  	//   x = x>>16&(m4&m) + x&(m4&m)
    65  	//   x = x>>32&(m5&m) + x&(m5&m)
    66  	//   return int(x)
    67  	//
    68  	// Masking (& operations) can be left away when there's no
    69  	// danger that a field's sum will carry over into the next
    70  	// field: Since the result cannot be > 64, 8 bits is enough
    71  	// and we can ignore the masks for the shifts by 8 and up.
    72  	// Per "Hacker's Delight", the first line can be simplified
    73  	// more, but it saves at best one instruction, so we leave
    74  	// it alone for clarity.
    75  	const m = 1<<64 - 1
    76  	x = x>>1&(m0&m) + x&(m0&m)
    77  	x = x>>2&(m1&m) + x&(m1&m)
    78  	x = (x>>4 + x) & (m2 & m)
    79  	x += x >> 8
    80  	x += x >> 16
    81  	x += x >> 32
    82  	return int(x) & (1<<7 - 1)
    83  }
    84  
    85  // LeadingZeros64 returns the number of leading zero bits in x; the result is 64 for x == 0.
    86  func LeadingZeros64(x uint64) int { return 64 - Len64(x) }
    87  
    88  // LeadingZeros8 returns the number of leading zero bits in x; the result is 8 for x == 0.
    89  func LeadingZeros8(x uint8) int { return 8 - Len8(x) }
    90  
    91  // Len8 returns the minimum number of bits required to represent x; the result is 0 for x == 0.
    92  func Len8(x uint8) int {
    93  	return int(len8tab[x])
    94  }
    95  
    96  // Prefetch prefetches data from memory addr to cache
    97  //
    98  // AMD64: Produce PREFETCHT0 instruction
    99  //
   100  // ARM64: Produce PRFM instruction with PLDL1KEEP option
   101  func Prefetch(addr uintptr) {}
   102  
   103  // PrefetchStreamed prefetches data from memory addr, with a hint that this data is being streamed.
   104  // That is, it is likely to be accessed very soon, but only once. If possible, this will avoid polluting the cache.
   105  //
   106  // AMD64: Produce PREFETCHNTA instruction
   107  //
   108  // ARM64: Produce PRFM instruction with PLDL1STRM option
   109  func PrefetchStreamed(addr uintptr) {}