aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/arm64/asm7.go
diff options
context:
space:
mode:
authorJoel Sing <joel@sing.id.au>2023-04-29 20:29:41 +1000
committerJoel Sing <joel@sing.id.au>2023-07-31 16:39:36 +0000
commit6eaad824e56aec91266854bf7890a94c3f08b614 (patch)
treecbf6a147f0aaee20e26fae62da66a1a5b00d4378 /src/cmd/internal/obj/arm64/asm7.go
parent03bec7dc6ff6bbcdf077753230cee11211aa78ba (diff)
downloadgo-6eaad824e56aec91266854bf7890a94c3f08b614.tar.gz
go-6eaad824e56aec91266854bf7890a94c3f08b614.zip
cmd/internal/obj/arm64: improve splitting of 24 bit unsigned scaled immediates
The previous implementation would limit itself to 0xfff000 | 0xfff << shift, while the maximum possible value is 0xfff000 + 0xfff << shift. In practical terms, this means that an additional ((1 << shift) - 1) * 0x1000 of offset is reachable for operations that use this splitting format. In the case of an 8 byte load/store, this is an additional 0x7000 that can be reached without needing to use the literal pool. Updates #59615 Change-Id: Ice7023104042d31c115eafb9398c2b999bdd6583 Reviewed-on: https://go-review.googlesource.com/c/go/+/512540 Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Joel Sing <joel@sing.id.au>
Diffstat (limited to 'src/cmd/internal/obj/arm64/asm7.go')
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go19
1 files changed, 13 insertions, 6 deletions
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 05cf62773e..ea53a838e3 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -1420,13 +1420,20 @@ func splitImm24uScaled(v int32, shift int) (int32, int32, error) {
if v < 0 {
return 0, 0, fmt.Errorf("%d is not a 24 bit unsigned immediate", v)
}
+ if v > 0xfff000+0xfff<<shift {
+ return 0, 0, fmt.Errorf("%d is too large for a scaled 24 bit unsigned immediate", v)
+ }
if v&((1<<shift)-1) != 0 {
return 0, 0, fmt.Errorf("%d is not a multiple of %d", v, 1<<shift)
}
lo := (v >> shift) & 0xfff
hi := v - (lo << shift)
- if hi&^0xfff000 != 0 {
- return 0, 0, fmt.Errorf("%d is too large for a scaled 24 bit unsigned immediate %x %x", v, lo, hi)
+ if hi > 0xfff000 {
+ hi = 0xfff000
+ lo = (v - hi) >> shift
+ }
+ if hi & ^0xfff000 != 0 {
+ panic(fmt.Sprintf("bad split for %x with shift %v (%x, %x)", v, shift, hi, lo))
}
return hi, lo, nil
}
@@ -1975,28 +1982,28 @@ func (c *ctxt7) loadStoreClass(p *obj.Prog, lsc int, v int64) int {
if cmp(C_UAUTO8K, lsc) || cmp(C_UOREG8K, lsc) {
return lsc
}
- if v >= 0 && v <= 0xfffffe && v&1 == 0 {
+ if v >= 0 && v <= 0xfff000+0xfff<<1 && v&1 == 0 {
needsPool = false
}
case AMOVW, AMOVWU, AFMOVS:
if cmp(C_UAUTO16K, lsc) || cmp(C_UOREG16K, lsc) {
return lsc
}
- if v >= 0 && v <= 0xfffffc && v&3 == 0 {
+ if v >= 0 && v <= 0xfff000+0xfff<<2 && v&3 == 0 {
needsPool = false
}
case AMOVD, AFMOVD:
if cmp(C_UAUTO32K, lsc) || cmp(C_UOREG32K, lsc) {
return lsc
}
- if v >= 0 && v <= 0xfffff8 && v&7 == 0 {
+ if v >= 0 && v <= 0xfff000+0xfff<<3 && v&7 == 0 {
needsPool = false
}
case AFMOVQ:
if cmp(C_UAUTO64K, lsc) || cmp(C_UOREG64K, lsc) {
return lsc
}
- if v >= 0 && v <= 0xfffff0 && v&15 == 0 {
+ if v >= 0 && v <= 0xfff000+0xfff<<4 && v&15 == 0 {
needsPool = false
}
}