MOVD $0x11110000, R1 // MOVD $286326784, R1 // 2122a2d2
MOVD $0xaaaa0000aaaa1111, R1 // MOVD $-6149102338357718767, R1 // 212282d24155b5f24155f5f2
MOVD $0x1111ffff1111aaaa, R1 // MOVD $1230045644216969898, R1 // a1aa8a922122a2f22122e2f2
+ MOVD $0xaaaaaaaaaaaaaaab, R1 // MOVD $-6148914691236517205, R1 // e1f301b2615595f2
+ MOVD $0x0ff019940ff00ff0, R1 // MOVD $1148446028692721648, R1 // e19f0cb28132c3f2
MOVD $0, R1 // e1031faa
MOVD $-1, R1 // 01008092
MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
"fmt"
"log"
"math"
+ "math/bits"
"slices"
"strings"
)
return C_MOVCON
} else if zeroCount == 2 || negCount == 2 {
return C_MOVCON2
- } else if zeroCount == 1 || negCount == 1 {
+ }
+ // See omovlconst for description of this loop.
+ for i := 0; i < 4; i++ {
+ mask := uint64(0xffff) << (i * 16)
+ for period := 2; period <= 32; period *= 2 {
+ x := uint64(a.Offset)&^mask | bits.RotateLeft64(uint64(a.Offset), max(period, 16))&mask
+ if isbitcon(x) {
+ return C_MOVCON2
+ }
+ }
+ }
+ if zeroCount == 1 || negCount == 1 {
return C_MOVCON3
} else {
return C_VCON
}
}
return 2
+ }
+
+ // Look for a two instruction pair, a bit pattern encodeable
+ // as a bitcon immediate plus a fixup MOVK instruction.
+ // Constants like this often occur from strength reduction of divides.
+ for i = 0; i < 4; i++ {
+ mask := uint64(0xffff) << (i * 16)
+ for period := 2; period <= 32; period *= 2 { // TODO: handle period==64 somehow?
+ // Copy in bits from outside of the masked region
+ x := uint64(d)&^mask | bits.RotateLeft64(uint64(d), max(period, 16))&mask
+ if isbitcon(x) {
+ // ORR $c1, ZR, rt
+ os[0] = c.opirr(p, AORR)
+ os[0] |= bitconEncode(x, 64) | uint32(REGZERO&31)<<5 | uint32(rt&31)
+ // MOVK $c2<<(i*16), rt
+ os[1] = c.opirr(p, AMOVK)
+ os[1] |= MOVCONST(d, i, rt)
+ return 2
+ }
+ }
+ }
+ // TODO: other fixups, like ADD or SUB?
+ // TODO: 3-instruction variant, instead of the full MOVD+3*MOVK version below?
+
+ switch {
case zeroCount == 1:
// one MOVZ and two MOVKs
t.Errorf("Got %x want %x\n", x, want)
}
}
+
+func testCombined() (a uint64, b uint64)
+func TestCombined(t *testing.T) {
+ got1, got2 := testCombined()
+ want1 := uint64(0xaaaaaaaaaaaaaaab)
+ want2 := uint64(0x0ff019940ff00ff0)
+ if got1 != want1 {
+ t.Errorf("First result, got %x want %x", got1, want1)
+ }
+ if got2 != want2 {
+ t.Errorf("First result, got %x want %x", got2, want2)
+ }
+}