MOVW $2147483649, R5 // 6405800060a50001 or 0600800038a00001
MOVD $2147483649, R5 // 6405800060a50001 or 0600800038a00001
// Hex constant 0xFFFFFFFF80000001
- MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
- // Hex constant 0xFFFFFFFE00000000 (load of constant on < power10, pli on >= power10
- MOVD $-8589934592, R5 // 3ca00000e8a50000 or 0602000038a00000
- // Hex constant 0xFFFFFFFE00000000
- ADD $-8589934592, R5 // 3fe0fffe63ff00007bff83e463ff00007cbf2a14 or 0602000038a50000
+ MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
+ // Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
+ MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
+
+ // TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
+ // This only captures the MOVD. Should the SLD be appended to the encoding by the test?
+ // Hex constant 0x20004000000
+ MOVD $2199090364416, R5 // 60058001
+ // Hex constant 0xFFFFFE0004000000
+ MOVD $-2198956146688, R5 // 38a08001
+
MOVD 8(R3), R4 // e8830008
MOVD (R3)(R4), R5 // 7ca4182a
MOVD (R3)(R0), R5 // 7ca0182a
ADD $-32767, R5, R4 // 38858001
ADD $-32768, R6 // 38c68000
ADD $-32768, R6, R5 // 38a68000
+ // Hex constant 0xFFFFFFFE00000000
+ ADD $-8589934592, R5 // 3fe0fffe63ff00007bff83e463ff00007cbf2a14 or 0602000038a50000
//TODO: this compiles to add r5,r6,r0. It should be addi r5,r6,0.
// this is OK since r0 == $0, but the latter is preferred.
"cmd/internal/sys"
"internal/abi"
"log"
+ "math/bits"
)
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
}
case AMOVD:
- // 32b constants (signed and unsigned) can be generated via 1 or 2 instructions.
+ // 32b constants (signed and unsigned) can be generated via 1 or 2 instructions. They can be assembled directly.
isS32 := int64(int32(p.From.Offset)) == p.From.Offset
isU32 := uint64(uint32(p.From.Offset)) == uint64(p.From.Offset)
// If prefixed instructions are supported, a 34b signed constant can be generated by one pli instruction.
isS34 := pfxEnabled && (p.From.Offset<<30)>>30 == p.From.Offset
-
- // If the constant cannot be generated with 2 or less instructions, it must be placed in memory and loaded.
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && !isS32 && !isU32 && !isS34 {
- p.From.Type = obj.TYPE_MEM
- p.From.Sym = ctxt.Int64Sym(p.From.Offset)
- p.From.Name = obj.NAME_EXTERN
- p.From.Offset = 0
+
+ // Is this a shifted 16b constant? If so, rewrite it to avoid a creating and loading a constant.
+ val := p.From.Offset
+ shift := bits.TrailingZeros64(uint64(val))
+ mask := 0xFFFF << shift
+ if val&int64(mask) == val || (val>>(shift+16) == -1 && (val>>shift)<<shift == val) {
+ // Rewrite this value into MOVD $const>>shift, Rto; SLD $shift, Rto
+ q := obj.Appendp(p, c.newprog)
+ q.As = ASLD
+ q.From.Type = obj.TYPE_CONST
+ q.From.Offset = int64(shift)
+ q.To = p.To
+ p.From.Offset >>= shift
+ p = q
+ } else {
+ // Load the constant from memory.
+ p.From.Type = obj.TYPE_MEM
+ p.From.Sym = ctxt.Int64Sym(p.From.Offset)
+ p.From.Name = obj.NAME_EXTERN
+ p.From.Offset = 0
+ }
}
}
--- /dev/null
+// asmcheck
+
+// Copyright 2023 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 codegen
+
+func shifted16BitConstants(out [64]uint64) {
+ // ppc64x: "MOVD\t[$]8193,", "SLD\t[$]27,"
+ out[0] = 0x0000010008000000
+ // ppc64x: "MOVD\t[$]-32767", "SLD\t[$]26,"
+ out[1] = 0xFFFFFE0004000000
+ // ppc64x: "MOVD\t[$]-1", "SLD\t[$]48,"
+ out[2] = 0xFFFF000000000000
+ // ppc64x: "MOVD\t[$]65535", "SLD\t[$]44,"
+ out[3] = 0x0FFFF00000000000
+
+ // ppc64x: "MOVD\t[$]i64.fffff00000000001[(]SB[)]"
+ out[4] = 0xFFFFF00000000001
+ // ppc64x: "MOVD\t[$]i64.fffff80000000001[(]SB[)]"
+ out[5] = 0xFFFFF80000000001
+ // ppc64x: "MOVD\t[$]i64.0ffff80000000000[(]SB[)]"
+ out[6] = 0x0FFFF80000000000
+}