blob: 160a862313a1602034e706b7d40727fdcc9f91e3 [file]
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package rewritearm64latelower
// isARM64addcon reports whether x can be encoded as the immediate value in an ADD or SUB instruction.
func isARM64addcon(v int64) bool {
/* uimm12 or uimm24? */
if v < 0 {
return false
}
if (v & 0xFFF) == 0 {
v >>= 12
}
return v <= 0xFFF
}
// isARM64bitcon reports whether a constant can be encoded into a logical instruction.
func isARM64bitcon(x uint64) bool {
if x == 1<<64-1 || x == 0 {
return false
}
// determine the period and sign-extend a unit to 64 bits
switch {
case x != x>>32|x<<32:
// period is 64
// nothing to do
case x != x>>16|x<<48:
// period is 32
x = uint64(int64(int32(x)))
case x != x>>8|x<<56:
// period is 16
x = uint64(int64(int16(x)))
case x != x>>4|x<<60:
// period is 8
x = uint64(int64(int8(x)))
default:
// period is 4 or 2, always true
// 0001, 0010, 0100, 1000 -- 0001 rotate
// 0011, 0110, 1100, 1001 -- 0011 rotate
// 0111, 1011, 1101, 1110 -- 0111 rotate
// 0101, 1010 -- 01 rotate, repeat
return true
}
return sequenceOfOnes(x) || sequenceOfOnes(^x)
}
// sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros.
func sequenceOfOnes(x uint64) bool {
y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
y += x
return (y-1)&y == 0
}