Files
gasm-sdk/asm/amd64_xsave.go
T

58 lines
1.9 KiB
Go
Raw Permalink Normal View History

2026-10-06 20:10:22 +02:00
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package asm
import (
"fmt"
"strings"
)
// This file implements the XSAVE family: the extended-state save and restore
// pair in its four generations (XSAVE/XRSTOR, XSAVEOPT, XSAVEC, XSAVES) and
// their 64 spellings. Each takes one memory operand alone; the 64 spellings
// carry REX.W. Every encoding here is pinned byte for byte against
// go tool asm through the corpus lines in amd64_xsave_test.go.
// xsaveSpec is one XSAVE family member: the opcode group and the /digit.
// XSAVEOPT carries no mandatory prefix in the toolchain's encoding despite
// the manual's 0x66, so the family has none anywhere.
type xsaveSpec struct {
op []byte
digit int
}
// xsaveTable maps the save/restore mnemonics to their encodings. The 64
// spellings share the base's digit with REX.W.
var xsaveTable = map[string]xsaveSpec{
"XSAVE": {[]byte{0x0F, 0xAE}, 4},
"XRSTOR": {[]byte{0x0F, 0xAE}, 5},
"XSAVEOPT": {[]byte{0x0F, 0xAE}, 6},
"XSAVEC": {[]byte{0x0F, 0xC7}, 4},
"XSAVES": {[]byte{0x0F, 0xC7}, 5},
"XRSTORS": {[]byte{0x0F, 0xC7}, 3},
}
// encodeXsave encodes the XSAVE family. It reports whether the mnemonic
// belongs to the family.
func (e *enc) encodeXsave(upper string, ops []Operand) (bool, error) {
name, rexW := upper, false
if base, ok := strings.CutSuffix(upper, "64"); ok {
name, rexW = base, true
}
spec, ok := xsaveTable[name]
if !ok {
return false, nil
}
if len(ops) != 1 {
return true, fmt.Errorf("%s expects 1 memory operand, got %d", upper, len(ops))
}
if !isX86Mem(ops[0]) {
return true, fmt.Errorf("%s requires a memory operand", upper)
}
i := &instr{opcode: append([]byte(nil), spec.op...), modrm: -1, sib: -1, rexW: rexW}
if err := setRMDigit(i, spec.digit, ops[0], 8); err != nil {
return true, err
}
return true, e.emit(i)
}