aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/internal
diff options
context:
space:
mode:
authorAlexander Musman <alexander.musman@gmail.com>2026-04-02 11:00:59 +0300
committerGopher Robot <gobot@golang.org>2026-04-08 03:51:51 -0700
commitb1c8857f95581ef3cb3daa0767985bba9f72320f (patch)
tree9ec36f73935b56ff344ffda2cfc797fd23bd4b0d /src/cmd/internal
parent9111d85e2f699672d67dcee1d6432a940f5306e1 (diff)
downloadgo-b1c8857f95581ef3cb3daa0767985bba9f72320f.tar.xz
cmd/internal/obj/arm64: add ASIMD arithmetic instructions
Add encoding support for ASIMD three-register instructions covering floating-point, saturating, halving, integer multiply/accumulate, min/max (including pairwise variants), and bitwise operations. These belong to the "Advanced SIMD Three-register (same)" instruction class defined by the ARM architecture, meaning the two source registers use the same element arrangement (e.g., both .S4 or both .D2). In the assembler they share a common encoding path using the ASIMDSAME() macro. New instructions by group: Floating-point arithmetic: VFADD, VFSUB, VFMUL, VFDIV Floating-point min/max: VFMAX, VFMAXNM, VFMIN, VFMINNM Pairwise floating-point: VFADDP, VFMAXP, VFMINP, VFMAXNMP, VFMINNMP Saturating arithmetic: VSQADD, VUQADD, VSQSUB, VUQSUB Average (halving add): VSHADD, VSRHADD, VUHADD, VURHADD Integer multiply/accum: VMUL, VMLA, VMLS Integer min/max: VSMAX, VSMIN Pairwise integer min/max: VSMAXP, VSMINP, VUMAXP, VUMINP Bitwise: VBIC, VORN Change-Id: I732c84123ad1f302260514fdfe0d020787da017b Reviewed-on: https://go-review.googlesource.com/c/go/+/762200 Auto-Submit: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/cmd/internal')
-rw-r--r--src/cmd/internal/obj/arm64/a.out.go32
-rw-r--r--src/cmd/internal/obj/arm64/anames.go32
-rw-r--r--src/cmd/internal/obj/arm64/asm7.go138
3 files changed, 197 insertions, 5 deletions
diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go
index 56f68756fd..3d7173155a 100644
--- a/src/cmd/internal/obj/arm64/a.out.go
+++ b/src/cmd/internal/obj/arm64/a.out.go
@@ -1113,6 +1113,8 @@ const (
AUXTW
AVADD
AVADDP
+ AVSHADD
+ AVSRHADD
AVADDV
AVAND
AVBCAX
@@ -1139,6 +1141,28 @@ const (
AVFCMGT
AVFCMLE
AVFCMLT
+ AVFADDP
+ AVFADD
+ AVFSUB
+ AVFMUL
+ AVFDIV
+ AVFMAX
+ AVFMAXNM
+ AVFMAXP
+ AVFMIN
+ AVFMINNM
+ AVFMINP
+ AVFMAXNMP
+ AVFMINNMP
+ AVSQADD
+ AVUQADD
+ AVSQSUB
+ AVUQSUB
+ AVUHADD
+ AVURHADD
+ AVMUL
+ AVMLA
+ AVMLS
AVLD1
AVLD1R
AVLD2
@@ -1153,6 +1177,8 @@ const (
AVMOVQ
AVMOVS
AVORR
+ AVORN
+ AVBIC
AVPMULL
AVPMULL2
AVRAX1
@@ -1174,6 +1200,10 @@ const (
AVST3
AVST4
AVSUB
+ AVSMAX
+ AVSMIN
+ AVSMAXP
+ AVSMINP
AVTBL
AVTBX
AVTRN1
@@ -1183,6 +1213,8 @@ const (
AVUADDW2
AVUMAX
AVUMIN
+ AVUMAXP
+ AVUMINP
AVUSHLL
AVUSHLL2
AVUSHR
diff --git a/src/cmd/internal/obj/arm64/anames.go b/src/cmd/internal/obj/arm64/anames.go
index e40c043edd..1f07580ae7 100644
--- a/src/cmd/internal/obj/arm64/anames.go
+++ b/src/cmd/internal/obj/arm64/anames.go
@@ -469,6 +469,8 @@ var Anames = []string{
"UXTW",
"VADD",
"VADDP",
+ "VSHADD",
+ "VSRHADD",
"VADDV",
"VAND",
"VBCAX",
@@ -495,6 +497,28 @@ var Anames = []string{
"VFCMGT",
"VFCMLE",
"VFCMLT",
+ "VFADDP",
+ "VFADD",
+ "VFSUB",
+ "VFMUL",
+ "VFDIV",
+ "VFMAX",
+ "VFMAXNM",
+ "VFMAXP",
+ "VFMIN",
+ "VFMINNM",
+ "VFMINP",
+ "VFMAXNMP",
+ "VFMINNMP",
+ "VSQADD",
+ "VUQADD",
+ "VSQSUB",
+ "VUQSUB",
+ "VUHADD",
+ "VURHADD",
+ "VMUL",
+ "VMLA",
+ "VMLS",
"VLD1",
"VLD1R",
"VLD2",
@@ -509,6 +533,8 @@ var Anames = []string{
"VMOVQ",
"VMOVS",
"VORR",
+ "VORN",
+ "VBIC",
"VPMULL",
"VPMULL2",
"VRAX1",
@@ -530,6 +556,10 @@ var Anames = []string{
"VST3",
"VST4",
"VSUB",
+ "VSMAX",
+ "VSMIN",
+ "VSMAXP",
+ "VSMINP",
"VTBL",
"VTBX",
"VTRN1",
@@ -539,6 +569,8 @@ var Anames = []string{
"VUADDW2",
"VUMAX",
"VUMIN",
+ "VUMAXP",
+ "VUMINP",
"VUSHLL",
"VUSHLL2",
"VUSHR",
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index 0d8c1f417e..4fd79f3b4b 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -3215,15 +3215,34 @@ func buildop(ctxt *obj.Link) {
oprangeset(AVAND, t)
oprangeset(AVORR, t)
oprangeset(AVEOR, t)
+ oprangeset(AVBIC, t)
+ oprangeset(AVORN, t)
oprangeset(AVBSL, t)
oprangeset(AVBIT, t)
oprangeset(AVCMTST, t)
oprangeset(AVCMHI, t)
+ oprangeset(AVSQADD, t)
+ oprangeset(AVUQADD, t)
+ oprangeset(AVSQSUB, t)
+ oprangeset(AVUQSUB, t)
+ oprangeset(AVMUL, t)
+ oprangeset(AVMLA, t)
+ oprangeset(AVMLS, t)
+ oprangeset(AVSHADD, t)
+ oprangeset(AVSRHADD, t)
oprangeset(AVSSHL, t)
oprangeset(AVUSHL, t)
+ oprangeset(AVUHADD, t)
+ oprangeset(AVURHADD, t)
oprangeset(AVCMHS, t)
oprangeset(AVUMAX, t)
oprangeset(AVUMIN, t)
+ oprangeset(AVSMAX, t)
+ oprangeset(AVSMIN, t)
+ oprangeset(AVSMAXP, t)
+ oprangeset(AVSMINP, t)
+ oprangeset(AVUMAXP, t)
+ oprangeset(AVUMINP, t)
oprangeset(AVUZP1, t)
oprangeset(AVUZP2, t)
oprangeset(AVBIF, t)
@@ -3272,6 +3291,19 @@ func buildop(ctxt *obj.Link) {
case AVFMLA:
oprangeset(AVFMLS, t)
+ oprangeset(AVFADD, t)
+ oprangeset(AVFSUB, t)
+ oprangeset(AVFMUL, t)
+ oprangeset(AVFDIV, t)
+ oprangeset(AVFMAX, t)
+ oprangeset(AVFMAXNM, t)
+ oprangeset(AVFMAXP, t)
+ oprangeset(AVFADDP, t)
+ oprangeset(AVFMIN, t)
+ oprangeset(AVFMINNM, t)
+ oprangeset(AVFMINP, t)
+ oprangeset(AVFMAXNMP, t)
+ oprangeset(AVFMINNMP, t)
case AVPMULL:
oprangeset(AVPMULL2, t)
@@ -4782,27 +4814,27 @@ func (c *ctxt7) asmout(p *obj.Prog, out []uint32) (count int) {
}
switch p.As {
- case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
+ case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF, AVBIC, AVORN:
if af != ARNG_16B && af != ARNG_8B {
c.ctxt.Diag("invalid arrangement: %v", p)
}
- case AVFMLA, AVFMLS, AVFCMEQ, AVFCMGE, AVFCMGT:
+ case AVFMLA, AVFMLS, AVFCMEQ, AVFCMGE, AVFCMGT, AVFADD, AVFSUB, AVFMUL, AVFDIV, AVFMAX, AVFMAXNM, AVFMAXP, AVFADDP, AVFMIN, AVFMINNM, AVFMINP, AVFMAXNMP, AVFMINNMP:
if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
c.ctxt.Diag("invalid arrangement: %v", p)
}
- case AVUMAX, AVUMIN:
+ case AVUMAX, AVUMIN, AVUMAXP, AVUMINP, AVMUL, AVMLA, AVMLS, AVSMAX, AVSMIN, AVSMAXP, AVSMINP:
if af == ARNG_2D {
c.ctxt.Diag("invalid arrangement: %v", p)
}
}
switch p.As {
- case AVAND, AVEOR:
+ case AVAND, AVEOR, AVBIC, AVORN:
size = 0
case AVBSL:
size = 1
case AVORR, AVBIT, AVBIF:
size = 2
- case AVFMLA, AVFMLS, AVFCMEQ, AVFCMGE, AVFCMGT:
+ case AVFMLA, AVFMLS, AVFCMEQ, AVFCMGE, AVFCMGT, AVFADD, AVFSUB, AVFMUL, AVFDIV, AVFMAX, AVFMAXNM, AVFMAXP, AVFADDP, AVFMIN, AVFMINNM, AVFMINP, AVFMAXNMP, AVFMINNMP:
if af == ARNG_2D {
size = 1
} else {
@@ -6565,24 +6597,60 @@ func (c *ctxt7) oprrr(p *obj.Prog, a obj.As, rd, rn, rm int16) uint32 {
case AVSUB:
op = ASIMDSAME(1, 0, 0x10)
+ case AVSHADD:
+ op = ASIMDSAME(0, 0, 0x0)
+
+ case AVSRHADD:
+ op = ASIMDSAME(0, 0, 0x2)
+
case AVSSHL:
op = ASIMDSAME(0, 0, 0x8)
case AVUSHL:
op = ASIMDSAME(1, 0, 0x8)
+ case AVUHADD:
+ op = ASIMDSAME(1, 0, 0x0)
+
+ case AVURHADD:
+ op = ASIMDSAME(1, 0, 0x2)
+
case AVADDP:
op = ASIMDSAME(0, 0, 0x17)
+ case AVSQADD:
+ op = ASIMDSAME(0, 0, 0x1)
+
+ case AVUQADD:
+ op = ASIMDSAME(1, 0, 0x1)
+
case AVSQSHL:
op = ASIMDSAME(0, 0, 0x9)
case AVUQSHL:
op = ASIMDSAME(1, 0, 0x9)
+ case AVSQSUB:
+ op = ASIMDSAME(0, 0, 0x5)
+
+ case AVUQSUB:
+ op = ASIMDSAME(1, 0, 0x5)
+
+ case AVMUL:
+ op = ASIMDSAME(0, 0, 0x13)
+
+ case AVMLA:
+ op = ASIMDSAME(0, 0, 0x12)
+
+ case AVMLS:
+ op = ASIMDSAME(1, 0, 0x12)
+
case AVAND:
op = ASIMDSAME(0, 0, 0x03)
+ case AVBIC:
+ op = ASIMDSAME(0, 1, 0x03)
+
case AVBCAX:
op = 0xCE<<24 | 1<<21
@@ -6628,6 +6696,9 @@ func (c *ctxt7) oprrr(p *obj.Prog, a obj.As, rd, rn, rm int16) uint32 {
case AVORR:
op = ASIMDSAME(0, 2, 0x03)
+ case AVORN:
+ op = ASIMDSAME(0, 3, 0x03)
+
case AVRAX1:
op = 0xCE<<24 | 3<<21 | 1<<15 | 3<<10
@@ -6655,6 +6726,45 @@ func (c *ctxt7) oprrr(p *obj.Prog, a obj.As, rd, rn, rm int16) uint32 {
case AVFMLS:
op = ASIMDSAME(0, 2, 0x19)
+ case AVFADD:
+ op = ASIMDSAME(0, 0, 0x1A)
+
+ case AVFSUB:
+ op = ASIMDSAME(0, 2, 0x1A)
+
+ case AVFMUL:
+ op = ASIMDSAME(1, 0, 0x1B)
+
+ case AVFDIV:
+ op = ASIMDSAME(1, 0, 0x1F)
+
+ case AVFMAX:
+ op = ASIMDSAME(0, 0, 0x1E)
+
+ case AVFMAXNM:
+ op = ASIMDSAME(0, 0, 0x18)
+
+ case AVFMAXP:
+ op = ASIMDSAME(1, 0, 0x1E)
+
+ case AVFADDP:
+ op = ASIMDSAME(1, 0, 0x1A)
+
+ case AVFMIN:
+ op = ASIMDSAME(0, 2, 0x1E)
+
+ case AVFMINNM:
+ op = ASIMDSAME(0, 2, 0x18)
+
+ case AVFMINP:
+ op = ASIMDSAME(1, 2, 0x1E)
+
+ case AVFMAXNMP:
+ op = ASIMDSAME(1, 0, 0x18)
+
+ case AVFMINNMP:
+ op = ASIMDSAME(1, 2, 0x18)
+
case AVPMULL, AVPMULL2:
op = ASIMDDIFF(0, 0xE)
@@ -6688,6 +6798,24 @@ func (c *ctxt7) oprrr(p *obj.Prog, a obj.As, rd, rn, rm int16) uint32 {
case AVUMIN:
op = ASIMDSAME(1, 0, 0x0D)
+ case AVUMAXP:
+ op = ASIMDSAME(1, 0, 0x14)
+
+ case AVUMINP:
+ op = ASIMDSAME(1, 0, 0x15)
+
+ case AVSMAX:
+ op = ASIMDSAME(0, 0, 0x0C)
+
+ case AVSMIN:
+ op = ASIMDSAME(0, 0, 0x0D)
+
+ case AVSMAXP:
+ op = ASIMDSAME(0, 0, 0x14)
+
+ case AVSMINP:
+ op = ASIMDSAME(0, 0, 0x15)
+
case AVUZP1:
op = ASIMDPERM(0x1)