Skip to content

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

Type arm64 s390x
int64 / uint64 / pointer MOVD MOVD
int8/int16/int32 (signed) MOVB/MOVH/MOVW MOVB/MOVH/MOVW
uint8/uint16/uint32 MOVBU/MOVHU/MOVWU MOVBZ/MOVHZ/MOVWZ
float32 FMOVS FMOVS
float64 FMOVD FMOVD

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, in a dedicated asm-s390x CI job on debian:trixie (the only big-endian runtime job):

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