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

     1  // Copyright 2016 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  //go:build !386
     6  
     7  // TODO finish intrinsifying 386, deadcode the assembly, remove build tags, merge w/ intrinsics_common
     8  
     9  package sys
    10  
    11  // Copied from math/bits to avoid dependence.
    12  
    13  var deBruijn32tab = [32]byte{
    14  	0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
    15  	31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9,
    16  }
    17  
    18  const deBruijn32 = 0x077CB531
    19  
    20  var deBruijn64tab = [64]byte{
    21  	0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4,
    22  	62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5,
    23  	63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11,
    24  	54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6,
    25  }
    26  
    27  const deBruijn64 = 0x03f79d71b4ca8b09
    28  
    29  const ntz8tab = "" +
    30  	"\x08\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    31  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    32  	"\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    33  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    34  	"\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    35  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    36  	"\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    37  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    38  	"\x07\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    39  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    40  	"\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    41  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    42  	"\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    43  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    44  	"\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" +
    45  	"\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00"
    46  
    47  // TrailingZeros32 returns the number of trailing zero bits in x; the result is 32 for x == 0.
    48  func TrailingZeros32(x uint32) int {
    49  	if x == 0 {
    50  		return 32
    51  	}
    52  	// see comment in TrailingZeros64
    53  	return int(deBruijn32tab[(x&-x)*deBruijn32>>(32-5)])
    54  }
    55  
    56  // TrailingZeros64 returns the number of trailing zero bits in x; the result is 64 for x == 0.
    57  func TrailingZeros64(x uint64) int {
    58  	if x == 0 {
    59  		return 64
    60  	}
    61  	// If popcount is fast, replace code below with return popcount(^x & (x - 1)).
    62  	//
    63  	// x & -x leaves only the right-most bit set in the word. Let k be the
    64  	// index of that bit. Since only a single bit is set, the value is two
    65  	// to the power of k. Multiplying by a power of two is equivalent to
    66  	// left shifting, in this case by k bits. The de Bruijn (64 bit) constant
    67  	// is such that all six bit, consecutive substrings are distinct.
    68  	// Therefore, if we have a left shifted version of this constant we can
    69  	// find by how many bits it was shifted by looking at which six bit
    70  	// substring ended up at the top of the word.
    71  	// (Knuth, volume 4, section 7.3.1)
    72  	return int(deBruijn64tab[(x&-x)*deBruijn64>>(64-6)])
    73  }
    74  
    75  // TrailingZeros8 returns the number of trailing zero bits in x; the result is 8 for x == 0.
    76  func TrailingZeros8(x uint8) int {
    77  	return int(ntz8tab[x])
    78  }
    79  
    80  // Bswap64 returns its input with byte order reversed
    81  // 0x0102030405060708 -> 0x0807060504030201
    82  func Bswap64(x uint64) uint64 {
    83  	c8 := uint64(0x00ff00ff00ff00ff)
    84  	a := x >> 8 & c8
    85  	b := (x & c8) << 8
    86  	x = a | b
    87  	c16 := uint64(0x0000ffff0000ffff)
    88  	a = x >> 16 & c16
    89  	b = (x & c16) << 16
    90  	x = a | b
    91  	c32 := uint64(0x00000000ffffffff)
    92  	a = x >> 32 & c32
    93  	b = (x & c32) << 32
    94  	x = a | b
    95  	return x
    96  }
    97  
    98  // Bswap32 returns its input with byte order reversed
    99  // 0x01020304 -> 0x04030201
   100  func Bswap32(x uint32) uint32 {
   101  	c8 := uint32(0x00ff00ff)
   102  	a := x >> 8 & c8
   103  	b := (x & c8) << 8
   104  	x = a | b
   105  	c16 := uint32(0x0000ffff)
   106  	a = x >> 16 & c16
   107  	b = (x & c16) << 16
   108  	x = a | b
   109  	return x
   110  }