Go version

go version go1.24.4 linux/arm64, and master(71c2bf551303)

Output of go env in your module/workspace:

$ go env
AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/ubuntu/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/ubuntu/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build4184793924=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/home/ubuntu/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/ubuntu/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/snap/go/10905'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/ubuntu/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/snap/go/10905/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.24.4'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

$ cat test.s
TEXT foo(SB),0,$0-0
        FMOVQ   F0, (R0)(R2)

Then run $ go tool asm test.s

What did you see happen?

$ go tool asm test.s
asm: illegal combination: 00000 (test.s:2)      FMOVQ   F0, (R0)(R2) FREG NONE NONE ROFF NONE, 7 3
asm: illegal combination: 00000 (test.s:2)      FMOVQ   F0, (R0)(R2) FREG NONE NONE ROFF NONE, 7 3
asm: illegal combination: 00000 (test.s:2)      FMOVQ   F0, (R0)(R2) FREG NONE NONE ROFF NONE, 7 3
asm: illegal combination: 00000 (test.s:2)      FMOVQ   F0, (R0)(R2) FREG NONE NONE ROFF NONE, 7 3
asm: illegal combination: 00000 (test.s:2)      FMOVQ   F0, (R0)(R2) FREG NONE NONE ROFF NONE, 7 3
asm: illegal combination: 00000 (test.s:2)      FMOVQ   F0, (R0)(R2) FREG NONE NONE ROFF NONE, 7 3
asm: assembly failed

What did you expect to see?

The "go tool asm test.s" command runs successfully, outputting an object file(test.o), which can be disassembled into the GNU-style instructions

$ go tool asm test.s # run success
$ go tool objdump  -gnu test.o
TEXT foo(SB) /home/ubuntu/work/go/test.s
  test.s:2              0x2fc                   3ca26800                FMOVQ F0, (R0)(R2)                   // str q0, [x0,x2]

Comment From: xin3liang

We can use the directive WORD to insert this binary instruction WORD $0x3CA26800 // FMOVQ F0, (R0)(R2) a.k.a str q0, [x0, x2]

Comment From: randall77

By Q here, you mean a 128-bit vector value?

I'm not sure what our assembly support for such instructions is. It is surprising that we can disassemble it, but we can't assemble it.

We do assemble MOVQ F0, (R0) correctly (to a 128-bit vector store).

Related: https://go-review.googlesource.com/c/arch/+/300729

@golang/arm

Comment From: mknyszek

CC @golang/compiler

Comment From: erifan

We do not support this instruction format for now, you can refer to https://github.com/golang/go/blob/3636ced112d89da03739fa7d5468c0270addaa28/src/cmd/internal/obj/arm64/asm7.go#L703 to support it. The assembler and disassembler are in two different repos, and there are indeed some inconsistency.

Comment From: xin3liang

By Q here, you mean a 128-bit vector value?

Yes, q0 is a 128-bit vector register.

I'm not sure what our assembly support for such instructions is. It is surprising that we can disassemble it, but we can't assemble it.

Yes, I found that we can disassemble it(disassembling GCC object file works), but we can't assemble it.

We do assemble MOVQ F0, (R0) correctly (to a 128-bit vector store).

And below asm works

FMOVD   F0, (R0)(R2)
FMOVS   F0, (R0)(R2)
FMOVS   F0, (R0)(R2<<2)

But below asm does not work

FMOVQ   F0, (R0)(R2<<2)
FMOVD   F0, (R0)(R2<<2)

Related: https://go-review.googlesource.com/c/arch/+/300729

@golang/arm