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