Files
gasm-sdk/asm/amd64_xsave_test.go
T
petrbalvin 257feace6e feat(asm): encode the amd64 XSAVE family
XSAVE, XSAVEOPT, XSAVEC and XSAVES with their restore twins, plain and
64, each pinned byte for byte against go tool asm through every corpus
line the toolchain's own amd64enc.s carries for the family (24 lines).
The toolchain emits XSAVEOPT without the manual's 0x66 prefix; the bytes
are the oracle, so the family carries none.

Assisted-by: GLM 5.3 Flash
2026-10-06 23:59:47 +02:00

57 lines
1.8 KiB
Go

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package asm
import "testing"
// amd64XsaveCorpus holds every line the Go toolchain's own
// amd64enc.s carries for the XSAVE family (XSAVE, XSAVEOPT, XSAVEC, XSAVES and the restores, plain and 64), with the bytes go tool asm
// emits for each: the differential ground truth the family is proven
// against, line for line.
var amd64XsaveCorpus = []struct {
line string
want string
}{
{"XRSTOR (BX)", "0f ae 2b"},
{"XRSTOR (R11)", "41 0f ae 2b"},
{"XRSTOR64 (BX)", "48 0f ae 2b"},
{"XRSTOR64 (R11)", "49 0f ae 2b"},
{"XRSTORS (BX)", "0f c7 1b"},
{"XRSTORS (R11)", "41 0f c7 1b"},
{"XRSTORS64 (BX)", "48 0f c7 1b"},
{"XRSTORS64 (R11)", "49 0f c7 1b"},
{"XSAVE (BX)", "0f ae 23"},
{"XSAVE (R11)", "41 0f ae 23"},
{"XSAVE64 (BX)", "48 0f ae 23"},
{"XSAVE64 (R11)", "49 0f ae 23"},
{"XSAVEC (BX)", "0f c7 23"},
{"XSAVEC (R11)", "41 0f c7 23"},
{"XSAVEC64 (BX)", "48 0f c7 23"},
{"XSAVEC64 (R11)", "49 0f c7 23"},
{"XSAVEOPT (BX)", "0f ae 33"},
{"XSAVEOPT (R11)", "41 0f ae 33"},
{"XSAVEOPT64 (BX)", "48 0f ae 33"},
{"XSAVEOPT64 (R11)", "49 0f ae 33"},
{"XSAVES (BX)", "0f c7 2b"},
{"XSAVES (R11)", "41 0f c7 2b"},
{"XSAVES64 (BX)", "48 0f c7 2b"},
{"XSAVES64 (R11)", "49 0f c7 2b"},
}
// TestAmd64XsaveCorpus assembles every corpus line and requires the same bytes
// go tool asm emits for it.
func TestAmd64XsaveCorpus(t *testing.T) {
for _, tc := range amd64XsaveCorpus {
fn := firstText(t, "TEXT ·p(SB), 4, $0\n\t"+tc.line+"\n")
code, _, err := Assemble(fn)
if err != nil {
t.Errorf("%s: %v", tc.line, err)
continue
}
if got := hexBytes(code); got != tc.want {
t.Errorf("%s: got %s, want %s", tc.line, got, tc.want)
}
}
}