Bug in avo -- MOVL should allow XMM registers as a destination.
davecgh opened this issue · 0 comments
davecgh commented
In order to move a 32-bit value from memory into an SSE register, as discussed in this issue, the Go assembler requires the use of MOVL (which is different than the intel/at&t syntax which uses MOVD and chooses based on the source operand).
Go will do a 64-bit load with MOVD despite being a pointer to a 32-bit value. However, avo complains about bad operands when using MOVL since it's not mark as one of its accepted forms.
Here is a minimal example to show the incorrect behavior of MOVD and that MOVL is indeed the correct opcode:
foo.go:
//go:build ignore
package main
import (
"github.com/mmcloughlin/avo/attr"
. "github.com/mmcloughlin/avo/build"
)
func main() {
TEXT("foo", attr.NOSPLIT, "func(n *uint32, out *[16]byte)")
Pragma("noescape")
n, _ := Dereference(Param("n")).Resolve()
r := XMM()
MOVD(n.Addr, r)
out, _ := Dereference(Param("out")).Index(0).Resolve()
MOVOU(r, out.Addr)
RET()
Generate()
}
main.go:
//go:generate go run foo.go -out foo_amd64.s -stubs foo_amd64.go -pkg main
package main
import "fmt"
func main() {
n := uint32(0xaaaaaaaa)
var out [16]byte
foo(&n, &out)
fmt.Printf("%032x\n", out)
}
$ go generate
$ go build && ./issue
aaaaaaaa9854c3000000000000000000 # notice the junk because it moved 64 bits
$ sed -i 's/MOVD/MOVL/' foo_amd64.s # replace MOVD with MOVL in generated asm
$ go build && ./issue
aaaaaaaa000000000000000000000000 # correct result
It's also pretty evident in looking at the compiled code that the first case using MOVD generates an incorrect MOVQ:
$ go tool objdump -s foo issue
foo_amd64.s:8 0x48ad40 488b442408 MOVQ 0x8(SP), AX
foo_amd64.s:9 0x48ad45 f30f7e00 MOVQ 0(AX), X0 <--------- MOVQ
foo_amd64.s:10 0x48ad49 488b442410 MOVQ 0x10(SP), AX
foo_amd64.s:11 0x48ad4e f30f7f00 MOVDQU X0, 0(AX)
foo_amd64.s:12 0x48ad52 c3 RET
Whereas MOVL generates the correct MOVD:
$ go tool objdump -s foo issue
foo_amd64.s:8 0x48ad40 488b442408 MOVQ 0x8(SP), AX
foo_amd64.s:9 0x48ad45 660f6e00 MOVD 0(AX), X0 <--------- MOVD
foo_amd64.s:10 0x48ad49 488b442410 MOVQ 0x10(SP), AX
foo_amd64.s:11 0x48ad4e f30f7f00 MOVDQU X0, 0(AX)
foo_amd64.s:12 0x48ad52 c3 RET