Skip to content
Sixth target: s390x

Sixth target: s390x

Sixth target: s390x

s390x (IBM Z) is the sixth and final 64-bit Go SIMD target — and the first big-endian one. It reuses the shared ABI0 model (abi) unchanged and adds only a move table; the big-endian byte order is handled by cmd/asm and the Go runtime, so the layout model needs no change.

The move table

Typearm64s390x
int64 / uint64 / pointerMOVDMOVD
int8/int16/int32 (signed)MOVB/MOVH/MOVWMOVB/MOVH/MOVW
uint8/uint16/uint32MOVBU/MOVHU/MOVWUMOVBZ/MOVHZ/MOVWZ
float32FMOVSFMOVS
float64FMOVDFMOVD

s390x’s 8-byte integer move is MOVD, floats use FMOVS/FMOVD, and unsigned sub-word loads use the Z zero-extend suffix (MOVBZ/MOVHZ/MOVWZ). The move surface is identical to ppc64le; what differs is the byte order.

Big-endian

s390x is big-endian. ABI0 offsets are still byte-for-byte identical to the little-endian targets — FP-relative slot placement is endianness-agnostic — but the runtime test deliberately exercises the big-endian path, catching any accidental little-endian assumption in the emitted assembly.

Example

sig := s390x.Layout(
    []string{"a", "b"}, []s390x.Type{s390x.Int64, s390x.Int64},
    []string{"ret"}, []s390x.Type{s390x.Int64},
)
b := s390x.NewFunc("add", sig, 0)
b.LoadArg("a", "R1").
    LoadArg("b", "R2").
    Raw("ADD R2, R1, R3").
    StoreRet("R3", "ret").
    Ret()

emits:

TEXT ·add(SB), NOSPLIT, $0-24
	MOVD a+0(FP), R1
	MOVD b+8(FP), R2
	ADD R2, R1, R3
	MOVD R3, ret+16(FP)
	RET

SIMD

The packed-add example uses the z/Architecture vector facility (VL / VAF / VST) through Raw over pointer arguments — see SIMD. It runs on the big-endian target, so lane order is checked there too.

Validation

There is no common s390x developer host, so correctness is established in layers — asmdecl (cross-arch), cmd/asm cross-build, and runtime under qemu-user (qemu-user-static), in a dedicated asm-s390x CI job on ubuntu-latest (the only big-endian runtime job; QEMU_CPU=max enables the vector facility). Only the SIMD example is runtime-proven today (no dedicated aggregate/array example yet, see the Roadmap):

go generate ./examples/simd/s390x/...
GOOS=linux GOARCH=s390x go vet ./examples/simd/s390x/...
GOOS=linux GOARCH=s390x go build ./examples/simd/s390x/...
QEMU_CPU=max GOARCH=s390x go test -exec=qemu-s390x-static ./examples/simd/s390x/...