Go Assembly by Example: Sqrt

This example is taken from Golang’s math package in its standard library. The function has been implemented in different assembly languages in order to leverage different architecture’s hardware support for the square root function.

package math
func Sqrt(x float64) float64

The Go compiler will look for files ending in _GOOS or _GOARCH or _GOOS_GOARCH to consider which assembly file to compile. See go/build.

∕∕ sqrt_386.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD   x+0(FP),F0
	FSQRT
	FMOVDP  F0,ret+8(FP)
	RET
∕∕ sqrt_amd64.s
#include "textflag.h"
TEXT ·Sqrt(SB), NOSPLIT, $0
	XORPS  X0, X0 // break dependency
	SQRTSD x+0(FP), X0
	MOVSD  X0, ret+8(FP)
	RET

amd64p32 is the native client (Nacl) amd64 instruction set with a 32-bit address space, 32-bit pointers and 32-bit type ints and uints. It is a sandbox architecture used for example in play.golang.org

∕∕ `sqrt_amd64p32.s`

As the amd64 assembly file is fine, we’ll use that.

#include "sqrt_amd64.s"
∕∕ sqrt_arm.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	MOVD   x+0(FP),F0
	SQRTD  F0,F0
	MOVD  F0,ret+8(FP)
	RET
∕∕ sqrt_arm64.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD	x+0(FP), F0
	FSQRTD	F0, F0
	FMOVD	F0, ret+8(FP)
	RET
∕∕ sqrt_mipsx.s

This file’s name doesn’t match any _GOOS.s pattern. Instead it uses the following comment to warn the compiler that both mips and mipsle can use this assembly file.

∕∕ +build mips mipsle
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	MOVD	x+0(FP), F0
	SQRTD	F0, F0
	MOVD	F0, ret+8(FP)
	RET
∕∕ sqrt_ppc64x.s
∕∕ +build ppc64 ppc64le
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD	x+0(FP), F0
	FSQRT	F0, F0
	FMOVD	F0, ret+8(FP)
	RET
∕∕ sqart_s389x.s
#include "textflag.h"
TEXT ·Sqrt(SB),NOSPLIT,$0
	FMOVD x+0(FP), F1
	FSQRT F1, F1
	FMOVD F1, ret+8(FP)
	RET