Source file test/codegen/bits.go

     1  // asmcheck
     2  
     3  // Copyright 2018 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package codegen
     8  
     9  import "math/bits"
    10  
    11  //
    12  // 64 bit instructions
    13  //
    14  
    15  func bitsCheckConstLeftShiftU64(a uint64) (n int) {
    16  	// amd64:"BTQ [$]63,"
    17  	// arm64:"TBNZ [$]63,"
    18  	// riscv64:"MOV [$]" "AND" "BNEZ"
    19  	if a&(1<<63) != 0 {
    20  		return 1
    21  	}
    22  	// amd64:"BTQ [$]60,"
    23  	// arm64:"TBNZ [$]60,"
    24  	// riscv64:"MOV [$]" "AND" "BNEZ"
    25  	if a&(1<<60) != 0 {
    26  		return 1
    27  	}
    28  	// amd64:"BTL [$]0,"
    29  	// arm64:"TBZ [$]0,"
    30  	// riscv64:"ANDI" "BEQZ"
    31  	if a&(1<<0) != 0 {
    32  		return 1
    33  	}
    34  	return 0
    35  }
    36  
    37  func bitsCheckConstRightShiftU64(a [8]uint64) (n int) {
    38  	// amd64:"BTQ [$]63,"
    39  	// arm64:"LSR [$]63," "TBNZ [$]0,"
    40  	// riscv64:"SRLI" "ANDI" "BNEZ"
    41  	if (a[0]>>63)&1 != 0 {
    42  		return 1
    43  	}
    44  	// amd64:"BTQ [$]63,"
    45  	// arm64:"LSR [$]63," "CBNZ"
    46  	// riscv64:"SRLI" "BNEZ"
    47  	if a[1]>>63 != 0 {
    48  		return 1
    49  	}
    50  	// amd64:"BTQ [$]63,"
    51  	// arm64:"LSR [$]63," "CBZ"
    52  	// riscv64:"SRLI" "BEQZ"
    53  	if a[2]>>63 == 0 {
    54  		return 1
    55  	}
    56  	// amd64:"BTQ [$]60,"
    57  	// arm64:"LSR [$]60," "TBZ [$]0,"
    58  	// riscv64:"SRLI", "ANDI" "BEQZ"
    59  	if (a[3]>>60)&1 == 0 {
    60  		return 1
    61  	}
    62  	// amd64:"BTL [$]1,"
    63  	// arm64:"LSR [$]1," "TBZ [$]0,"
    64  	// riscv64:"SRLI" "ANDI" "BEQZ"
    65  	if (a[4]>>1)&1 == 0 {
    66  		return 1
    67  	}
    68  	// amd64:"BTL [$]0,"
    69  	// arm64:"TBZ [$]0," -"LSR"
    70  	// riscv64:"ANDI" "BEQZ" -"SRLI"
    71  	if (a[5]>>0)&1 == 0 {
    72  		return 1
    73  	}
    74  	// amd64:"BTL [$]7,"
    75  	// arm64:"LSR [$]5," "TBNZ [$]2,"
    76  	// riscv64:"SRLI" "ANDI" "BNEZ"
    77  	if (a[6]>>5)&4 == 0 {
    78  		return 1
    79  	}
    80  	return 0
    81  }
    82  
    83  func bitsCheckVarU64(a, b uint64) (n int) {
    84  	// amd64:"BTQ"
    85  	// arm64:"MOVD [$]1," "LSL" "TST"
    86  	// riscv64:"ANDI [$]63," "SLL " "AND "
    87  	if a&(1<<(b&63)) != 0 {
    88  		return 1
    89  	}
    90  	// amd64:"BTQ" -"BT. [$]0,"
    91  	// arm64:"LSR" "TBZ [$]0,"
    92  	// riscv64:"ANDI [$]63," "SRL" "ANDI [$]1,"
    93  	if (b>>(a&63))&1 != 0 {
    94  		return 1
    95  	}
    96  	return 0
    97  }
    98  
    99  func bitsCheckMaskU64(a uint64) (n int) {
   100  	// amd64:"BTQ [$]63,"
   101  	// arm64:"TBNZ [$]63,"
   102  	// riscv64:"MOV [$]" "AND" "BNEZ"
   103  	if a&0x8000000000000000 != 0 {
   104  		return 1
   105  	}
   106  	// amd64:"BTQ [$]59,"
   107  	// arm64:"TBNZ [$]59,"
   108  	// riscv64:"MOV [$]" "AND" "BNEZ"
   109  	if a&0x800000000000000 != 0 {
   110  		return 1
   111  	}
   112  	// amd64:"BTL [$]0,"
   113  	// arm64:"TBZ [$]0,"
   114  	// riscv64:"ANDI" "BEQZ"
   115  	if a&0x1 != 0 {
   116  		return 1
   117  	}
   118  	return 0
   119  }
   120  
   121  func bitsSetU64(a, b uint64) (n uint64) {
   122  	// amd64:"BTSQ"
   123  	// arm64:"MOVD [$]1," "LSL" "ORR"
   124  	// riscv64:"ANDI" "SLL" "OR"
   125  	n += b | (1 << (a & 63))
   126  
   127  	// amd64:"BTSQ [$]63,"
   128  	// arm64:"ORR [$]-9223372036854775808,"
   129  	// riscv64:"MOV [$]" "OR "
   130  	n += a | (1 << 63)
   131  
   132  	// amd64:"BTSQ [$]60,"
   133  	// arm64:"ORR [$]1152921504606846976,"
   134  	// riscv64:"MOV [$]" "OR "
   135  	n += a | (1 << 60)
   136  
   137  	// amd64:"ORQ [$]1,"
   138  	// arm64:"ORR [$]1,"
   139  	// riscv64:"ORI"
   140  	n += a | (1 << 0)
   141  
   142  	return n
   143  }
   144  
   145  func bitsClearU64(a, b uint64) (n uint64) {
   146  	// amd64:"BTRQ"
   147  	// arm64:"MOVD [$]1," "LSL" "BIC"
   148  	// riscv64:"ANDI" "SLL" "ANDN"
   149  	n += b &^ (1 << (a & 63))
   150  
   151  	// amd64:"BTRQ [$]63,"
   152  	// arm64:"AND [$]9223372036854775807,"
   153  	// riscv64:"MOV [$]" "AND "
   154  	n += a &^ (1 << 63)
   155  
   156  	// amd64:"BTRQ [$]60,"
   157  	// arm64:"AND [$]-1152921504606846977,"
   158  	// riscv64:"MOV [$]" "AND "
   159  	n += a &^ (1 << 60)
   160  
   161  	// amd64:"ANDQ [$]-2"
   162  	// arm64:"AND [$]-2"
   163  	// riscv64:"ANDI [$]-2"
   164  	n += a &^ (1 << 0)
   165  
   166  	return n
   167  }
   168  
   169  func bitsClearLowest(x int64, y int32) (int64, int32) {
   170  	// amd64:"ANDQ [$]-2,"
   171  	// arm64:"AND [$]-2,"
   172  	// riscv64:"ANDI [$]-2,"
   173  	a := (x >> 1) << 1
   174  
   175  	// amd64:"ANDL [$]-2,"
   176  	// arm64:"AND [$]-2,"
   177  	// riscv64:"ANDI [$]-2,"
   178  	b := (y >> 1) << 1
   179  
   180  	return a, b
   181  }
   182  
   183  func bitsFlipU64(a, b uint64) (n uint64) {
   184  	// amd64:"BTCQ"
   185  	// arm64:"MOVD [$]1," "LSL" "EOR"
   186  	// riscv64:"ANDI" "SLL" "XOR "
   187  	n += b ^ (1 << (a & 63))
   188  
   189  	// amd64:"BTCQ [$]63,"
   190  	// arm64:"EOR [$]-9223372036854775808,"
   191  	// riscv64:"MOV [$]" "XOR "
   192  	n += a ^ (1 << 63)
   193  
   194  	// amd64:"BTCQ [$]60,"
   195  	// arm64:"EOR [$]1152921504606846976,"
   196  	// riscv64:"MOV [$]" "XOR "
   197  	n += a ^ (1 << 60)
   198  
   199  	// amd64:"XORQ [$]1,"
   200  	// arm64:"EOR [$]1,"
   201  	// riscv64:"XORI [$]1,"
   202  	n += a ^ (1 << 0)
   203  
   204  	return n
   205  }
   206  
   207  //
   208  // 32 bit instructions
   209  //
   210  
   211  func bitsCheckConstShiftLeftU32(a uint32) (n int) {
   212  	// amd64:"BTL [$]31,"
   213  	// arm64:"TBNZ [$]31,"
   214  	// riscv64:"MOV [$]" "AND" "BNEZ"
   215  	if a&(1<<31) != 0 {
   216  		return 1
   217  	}
   218  	// amd64:"BTL [$]28,"
   219  	// arm64:"TBNZ [$]28,"
   220  	// riscv64:"ANDI" "BNEZ"
   221  	if a&(1<<28) != 0 {
   222  		return 1
   223  	}
   224  	// amd64:"BTL [$]0,"
   225  	// arm64:"TBZ [$]0,"
   226  	// riscv64:"ANDI" "BEQZ"
   227  	if a&(1<<0) != 0 {
   228  		return 1
   229  	}
   230  	return 0
   231  }
   232  
   233  func bitsCheckConstRightShiftU32(a [8]uint32) (n int) {
   234  	// amd64:"BTL [$]31,"
   235  	// arm64:"UBFX [$]31," "CBNZW"
   236  	// riscv64:"SRLI" "ANDI" "BNEZ"
   237  	if (a[0]>>31)&1 != 0 {
   238  		return 1
   239  	}
   240  	// amd64:"BTL [$]31,"
   241  	// arm64:"UBFX [$]31," "CBNZW"
   242  	// riscv64:"SRLI" "BNEZ"
   243  	if a[1]>>31 != 0 {
   244  		return 1
   245  	}
   246  	// amd64:"BTL [$]31,"
   247  	// arm64:"UBFX [$]31," "CBZW"
   248  	// riscv64:"SRLI" "BEQZ"
   249  	if a[2]>>31 == 0 {
   250  		return 1
   251  	}
   252  	// amd64:"BTL [$]28,"
   253  	// arm64:"UBFX [$]28," "TBZ"
   254  	// riscv64:"SRLI" "ANDI" "BEQZ"
   255  	if (a[3]>>28)&1 == 0 {
   256  		return 1
   257  	}
   258  	// amd64:"BTL [$]1,"
   259  	// arm64:"UBFX [$]1," "TBZ"
   260  	// riscv64:"SRLI" "ANDI" "BEQZ"
   261  	if (a[4]>>1)&1 == 0 {
   262  		return 1
   263  	}
   264  	// amd64:"BTL [$]0,"
   265  	// arm64:"TBZ" -"UBFX" -"SRL"
   266  	// riscv64:"ANDI" "BEQZ" -"SRLI "
   267  	if (a[5]>>0)&1 == 0 {
   268  		return 1
   269  	}
   270  	// amd64:"BTL [$]7,"
   271  	// arm64:"UBFX [$]5," "TBNZ"
   272  	// riscv64:"SRLI" "ANDI" "BNEZ"
   273  	if (a[6]>>5)&4 == 0 {
   274  		return 1
   275  	}
   276  	return 0
   277  }
   278  
   279  func bitsCheckVarU32(a, b uint32) (n int) {
   280  	// amd64:"BTL"
   281  	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "TSTW"
   282  	// riscv64:"ANDI [$]31," "SLL " "AND "
   283  	if a&(1<<(b&31)) != 0 {
   284  		return 1
   285  	}
   286  	// amd64:"BTL" -"BT. [$]0"
   287  	// arm64:"AND [$]31," "LSR" "TBZ"
   288  	// riscv64:"ANDI [$]31," "SRLW " "ANDI [$]1,"
   289  	if (b>>(a&31))&1 != 0 {
   290  		return 1
   291  	}
   292  	return 0
   293  }
   294  
   295  func bitsCheckMaskU32(a uint32) (n int) {
   296  	// amd64:"BTL [$]31,"
   297  	// arm64:"TBNZ [$]31,"
   298  	// riscv64:"MOV [$]" "AND" "BNEZ"
   299  	if a&0x80000000 != 0 {
   300  		return 1
   301  	}
   302  	// amd64:"BTL [$]27,"
   303  	// arm64:"TBNZ [$]27,"
   304  	// riscv64:"ANDI" "BNEZ"
   305  	if a&0x8000000 != 0 {
   306  		return 1
   307  	}
   308  	// amd64:"BTL [$]0,"
   309  	// arm64:"TBZ [$]0,"
   310  	// riscv64:"ANDI" "BEQZ"
   311  	if a&0x1 != 0 {
   312  		return 1
   313  	}
   314  	return 0
   315  }
   316  
   317  func bitsSetU32(a, b uint32) (n uint32) {
   318  	// amd64:"BTSL"
   319  	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "ORR"
   320  	// riscv64:"ANDI" "SLL" "OR"
   321  	n += b | (1 << (a & 31))
   322  
   323  	// amd64:"ORL [$]-2147483648,"
   324  	// arm64:"ORR [$]-2147483648,"
   325  	// riscv64:"ORI [$]-2147483648,"
   326  	n += a | (1 << 31)
   327  
   328  	// amd64:"ORL [$]268435456,"
   329  	// arm64:"ORR [$]268435456,"
   330  	// riscv64:"ORI [$]268435456,"
   331  	n += a | (1 << 28)
   332  
   333  	// amd64:"ORL [$]1,"
   334  	// arm64:"ORR [$]1,"
   335  	// riscv64:"ORI [$]1,"
   336  	n += a | (1 << 0)
   337  
   338  	return n
   339  }
   340  
   341  func bitsClearU32(a, b uint32) (n uint32) {
   342  	// amd64:"BTRL"
   343  	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "BIC"
   344  	// riscv64:"ANDI" "SLL" "ANDN"
   345  	n += b &^ (1 << (a & 31))
   346  
   347  	// amd64:"ANDL [$]2147483647,"
   348  	// arm64:"AND [$]2147483647,"
   349  	// riscv64:"ANDI [$]2147483647,"
   350  	n += a &^ (1 << 31)
   351  
   352  	// amd64:"ANDL [$]-268435457,"
   353  	// arm64:"AND [$]-268435457,"
   354  	// riscv64:"ANDI [$]-268435457,"
   355  	n += a &^ (1 << 28)
   356  
   357  	// amd64:"ANDL [$]-2,"
   358  	// arm64:"AND [$]-2,"
   359  	// riscv64:"ANDI [$]-2,"
   360  	n += a &^ (1 << 0)
   361  
   362  	return n
   363  }
   364  
   365  func bitsFlipU32(a, b uint32) (n uint32) {
   366  	// amd64:"BTCL"
   367  	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "EOR"
   368  	// riscv64:"ANDI" "SLL" "XOR "
   369  	n += b ^ (1 << (a & 31))
   370  
   371  	// amd64:"XORL [$]-2147483648,"
   372  	// arm64:"EOR [$]-2147483648,"
   373  	// riscv64:"XORI [$]-2147483648,"
   374  	n += a ^ (1 << 31)
   375  
   376  	// amd64:"XORL [$]268435456,"
   377  	// arm64:"EOR [$]268435456,"
   378  	// riscv64:"XORI [$]268435456,"
   379  	n += a ^ (1 << 28)
   380  
   381  	// amd64:"XORL [$]1,"
   382  	// arm64:"EOR [$]1,"
   383  	// riscv64:"XORI [$]1,"
   384  	n += a ^ (1 << 0)
   385  
   386  	return n
   387  }
   388  
   389  func bitsOpOnMem(a []uint32, b, c, d uint32) {
   390  	// check direct operation on memory with constant
   391  
   392  	// amd64:`ANDL\s[$]200,\s\([A-Z][A-Z0-9]+\)`
   393  	a[0] &= 200
   394  	// amd64:`ORL\s[$]220,\s4\([A-Z][A-Z0-9]+\)`
   395  	a[1] |= 220
   396  	// amd64:`XORL\s[$]240,\s8\([A-Z][A-Z0-9]+\)`
   397  	a[2] ^= 240
   398  }
   399  
   400  func bitsCheckMostNegative(b uint8) bool {
   401  	// amd64:"TESTB"
   402  	// arm64:"TSTW" "CSET"
   403  	// riscv64:"ANDI [$]128," "SNEZ" -"ADDI"
   404  	return b&0x80 == 0x80
   405  }
   406  
   407  func bitsIssue19857a(a uint64) uint64 {
   408  	// arm64:`AND `
   409  	return a & ((1 << 63) - 1)
   410  }
   411  
   412  func bitsIssue19857b(a uint64) uint64 {
   413  	// arm64:`AND `
   414  	return a & (1 << 63)
   415  }
   416  
   417  func bitsIssue19857c(a, b uint32) (uint32, uint32) {
   418  	// arm/7:`BIC`,-`AND`
   419  	a &= 0xffffaaaa
   420  	// arm/7:`BFC`,-`AND`,-`BIC`
   421  	b &= 0xffc003ff
   422  	return a, b
   423  }
   424  
   425  func bitsAndNot(x, y uint32) uint32 {
   426  	// arm64:`BIC `,-`AND`
   427  	// loong64:"ANDN " -"AND "
   428  	// riscv64:"ANDN" -"AND "
   429  	return x &^ y
   430  }
   431  
   432  func bitsXorNot(x, y, z uint32, a []uint32, n, m uint64) uint64 {
   433  	// arm64:`EON `,-`EOR`,-`MVN`
   434  	// riscv64:"XNOR " -"MOV [$]" -"XOR"
   435  	a[0] = x ^ (y ^ 0xffffffff)
   436  
   437  	// arm64:`EON `,-`EOR`,-`MVN`
   438  	// riscv64:"XNOR" -"XOR"
   439  	a[1] = ^(y ^ z)
   440  
   441  	// arm64:`EON `,-`XOR`
   442  	// riscv64:"XNOR" -"XOR" -"NOT"
   443  	a[2] = x ^ ^z
   444  
   445  	// arm64:`EON `,-`EOR`,-`MVN`
   446  	// riscv64:"XNOR" -"MOV [$]" -"XOR"
   447  	return n ^ (m ^ 0xffffffffffffffff)
   448  }
   449  
   450  func bitsOrNot(x, y uint32) uint32 {
   451  	// arm64:"ORN " -"ORR"
   452  	// loong64:"ORN" -"OR "
   453  	// riscv64:"ORN" -"OR "
   454  	return x | ^y
   455  }
   456  
   457  func bitsNotOr(x int64, a []int64) {
   458  	// loong64: "MOVV [$]0" "NOR R"
   459  	a[0] = ^(0x1234 | x)
   460  	// loong64:"NOR" -"XOR"
   461  	a[1] = (-1) ^ x
   462  	// loong64: "MOVV [$]-55" -"OR" -"NOR"
   463  	a[2] = ^(0x12 | 0x34)
   464  }
   465  
   466  func bitsSetPowerOf2Test(x int) bool {
   467  	// amd64:"BTL [$]3"
   468  	// riscv64:"ANDI [$]8," "SNEZ" -"ADDI"
   469  	return x&8 == 8
   470  }
   471  
   472  func bitsSetTest(x int) bool {
   473  	// amd64:"ANDL [$]9, AX"
   474  	// amd64:"CMPQ AX, [$]9"
   475  	// riscv64:"ANDI [$]9," "ADDI [$]-9," "SEQZ"
   476  	return x&9 == 9
   477  }
   478  
   479  func bitsMaskContiguousOnes64U(x uint64) uint64 {
   480  	// s390x:"RISBGZ [$]16, [$]47, [$]0,"
   481  	return x & 0x0000ffffffff0000
   482  }
   483  
   484  func bitsMaskContiguousZeroes64U(x uint64) uint64 {
   485  	// s390x:"RISBGZ [$]48, [$]15, [$]0,"
   486  	return x & 0xffff00000000ffff
   487  }
   488  
   489  func bitsIssue44228a(a []int64, i int) bool {
   490  	// amd64: "BTQ", -"SHL"
   491  	return a[i>>6]&(1<<(i&63)) != 0
   492  }
   493  
   494  func bitsIssue44228b(a []int32, i int) bool {
   495  	// amd64: "BTL", -"SHL"
   496  	return a[i>>5]&(1<<(i&31)) != 0
   497  }
   498  
   499  func bitsIssue48467(x, y uint64) uint64 {
   500  	// arm64: -"NEG"
   501  	d, borrow := bits.Sub64(x, y, 0)
   502  	return x - d&(-borrow)
   503  }
   504  
   505  func bitsFoldConst(x, y uint64) uint64 {
   506  	// arm64: "ADDS [$]7" -"MOVD [$]7"
   507  	// ppc64x: "ADDC [$]7,"
   508  	d, b := bits.Add64(x, 7, 0)
   509  	return b & d
   510  }
   511  
   512  func bitsFoldConstOutOfRange(a uint64) uint64 {
   513  	// arm64: "MOVD [$]19088744" -"ADD [$]19088744"
   514  	return a + 0x1234568
   515  }
   516  
   517  func bitsSignExtendAndMask8to64U(a int8) (s, z uint64) {
   518  	// Verify sign-extended values are not zero-extended under a bit mask (#61297)
   519  
   520  	// ppc64x: "MOVB", "ANDCC [$]1015,"
   521  	s = uint64(a) & 0x3F7
   522  	// ppc64x: -"MOVB", "ANDCC [$]247,"
   523  	z = uint64(uint8(a)) & 0x3F7
   524  	return
   525  }
   526  
   527  func bitsZeroExtendAndMask8toU64(a int8, b int16) (x, y uint64) {
   528  	// Verify zero-extended values are not sign-extended under a bit mask (#61297)
   529  
   530  	// ppc64x: -"MOVB ", -"ANDCC", "MOVBZ"
   531  	x = uint64(a) & 0xFF
   532  	// ppc64x: -"MOVH ", -"ANDCC", "MOVHZ"
   533  	y = uint64(b) & 0xFFFF
   534  	return
   535  }
   536  
   537  func bitsRotateAndMask(io64 [8]uint64, io32 [4]uint32, io16 [4]uint16, io8 [4]uint8) {
   538  	// Verify rotate and mask instructions, and further simplified instructions for small types
   539  
   540  	// ppc64x: "RLDICR [$]0, R[0-9]*, [$]47, R"
   541  	io64[0] = io64[0] & 0xFFFFFFFFFFFF0000
   542  	// ppc64x: "RLDICL [$]0, R[0-9]*, [$]16, R"
   543  	io64[1] = io64[1] & 0x0000FFFFFFFFFFFF
   544  	// ppc64x: -"SRD", -"AND", "RLDICL [$]60, R[0-9]*, [$]16, R"
   545  	io64[2] = (io64[2] >> 4) & 0x0000FFFFFFFFFFFF
   546  	// ppc64x: -"SRD", -"AND", "RLDICL [$]36, R[0-9]*, [$]28, R"
   547  	io64[3] = (io64[3] >> 28) & 0x0000FFFFFFFFFFFF
   548  
   549  	// ppc64x: "MOVWZ", "RLWNM [$]1, R[0-9]*, [$]28, [$]3, R"
   550  	io64[4] = uint64(bits.RotateLeft32(io32[0], 1) & 0xF000000F)
   551  
   552  	// ppc64x: "RLWNM [$]0, R[0-9]*, [$]4, [$]19, R"
   553  	io32[0] = io32[0] & 0x0FFFF000
   554  	// ppc64x: "RLWNM [$]0, R[0-9]*, [$]20, [$]3, R"
   555  	io32[1] = io32[1] & 0xF0000FFF
   556  	// ppc64x: -"RLWNM", MOVD, AND
   557  	io32[2] = io32[2] & 0xFFFF0002
   558  
   559  	var bigc uint32 = 0x12345678
   560  	// ppc64x: "ANDCC [$]22136"
   561  	io16[0] = io16[0] & uint16(bigc)
   562  
   563  	// ppc64x: "ANDCC [$]120"
   564  	io8[0] = io8[0] & uint8(bigc)
   565  }
   566  

View as plain text