aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal/obj/arm64/obj7.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/internal/obj/arm64/obj7.go')
-rw-r--r--src/cmd/internal/obj/arm64/obj7.go30
1 files changed, 20 insertions, 10 deletions
diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go
index ffa1b416d6..3f606dd697 100644
--- a/src/cmd/internal/obj/arm64/obj7.go
+++ b/src/cmd/internal/obj/arm64/obj7.go
@@ -279,20 +279,30 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
// Rewrite negative immediates as positive immediates with
// complementary instruction.
switch p.As {
- case AADD,
- AADDW,
- ASUB,
- ASUBW,
- ACMP,
- ACMPW,
- ACMN,
- ACMNW:
- if p.From.Type == obj.NAME_EXTERN && p.From.Offset < 0 {
+ case AADD, ASUB, ACMP, ACMN:
+ if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && p.From.Offset != -1<<63 {
p.From.Offset = -p.From.Offset
p.As = complements[p.As]
}
+ case AADDW, ASUBW, ACMPW, ACMNW:
+ if p.From.Type == obj.TYPE_CONST && p.From.Offset < 0 && int32(p.From.Offset) != -1<<31 {
+ p.From.Offset = -p.From.Offset
+ p.As = complements[p.As]
+ }
+ }
- break
+ // For 32-bit logical instruction with constant,
+ // rewrite the high 32-bit to be a repetition of
+ // the low 32-bit, so that the BITCON test can be
+ // shared for both 32-bit and 64-bit. 32-bit ops
+ // will zero the high 32-bit of the destination
+ // register anyway.
+ switch p.As {
+ case AANDW, AORRW, AEORW, AANDSW:
+ if p.From.Type == obj.TYPE_CONST {
+ v := p.From.Offset & 0xffffffff
+ p.From.Offset = v | v<<32
+ }
}
if ctxt.Flag_dynlink {