Files
gasm-sdk/asm/amd64_families.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

104 lines
2.4 KiB
Go

// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package asm
import "strings"
// encodeAmd64Family routes a mnemonic through the amd64 corpus families the
// dedicated amd64_*.go files implement. The first family that owns the name
// decides the outcome: its bytes, or its error. A name no family claims
// falls through to the scalar dispatch in (*enc).encode untouched.
func (e *enc) encodeAmd64Family(upper string, ops []Operand) (bool, error) {
if ok, err := e.encodeX87(upper, ops); ok {
return true, err
}
if ok, err := e.encodeSystem(upper, ops); ok {
return true, err
}
if ok, err := e.encodeXsave(upper, ops); ok {
return true, err
}
return false, nil
}
// amd64FamilyEncodable mirrors encodeAmd64Family for the lint-time
// predicate: true when some family owns the mnemonic, whatever the operand
// shapes. It must claim exactly the names encodeAmd64Family does.
func amd64FamilyEncodable(upper string) bool {
if _, ok := x87NoOperand[upper]; ok {
return true
}
if _, ok := x87Arith[upper]; ok {
return true
}
if _, ok := x87FCmov[upper]; ok {
return true
}
if _, ok := x87Compare[upper]; ok {
return true
}
if _, ok := x87MemUnary[upper]; ok {
return true
}
if _, ok := x87Fxsav[upper]; ok {
return true
}
if upper == "FADDDP" {
return true
}
if _, ok := systemNoOperand[upper]; ok {
return true
}
if b, size := splitSize(upper); size != 0 {
switch upper[len(upper)-1] {
case 'B', 'W', 'L', 'Q':
if _, ok := stringOp[b]; ok {
return true
}
}
if m, ok := sysRm[b]; ok && m.sized {
return true
}
}
if _, ok := nopWidth[upper]; ok {
return true
}
if _, ok := cacheControl[upper]; ok {
return true
}
if _, ok := movbeSize[upper]; ok {
return true
}
if _, ok := randSource[base(upper, 6)]; ok {
return true
}
if _, ok := fsGsBase[base(upper, 8)]; ok {
return true
}
if _, ok := descTable[upper]; ok {
return true
}
if _, ok := sysRm[upper]; ok {
return true
}
if _, ok := selectorRead[base(upper, 3)]; ok {
return true
}
if _, ok := farSegLoad[base(upper, 3)]; ok {
return true
}
if upper == "CMPXCHG8B" || upper == "CMPXCHG16B" {
return true
}
if _, ok := xsaveTable[upper]; ok {
return true
}
if before, ok := strings.CutSuffix(upper, "64"); ok {
if _, ok := xsaveTable[before]; ok {
return true
}
}
return false
}