Files
gasm-sdk/asm/amd64_families.go
T

122 lines
2.8 KiB
Go
Raw Permalink Normal View History

2026-10-06 20:08:34 +02:00
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package asm
2026-10-06 20:10:22 +02:00
import "strings"
2026-10-06 20:08:34 +02:00
// 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
}
2026-10-06 20:10:22 +02:00
if ok, err := e.encodeXsave(upper, ops); ok {
return true, err
}
if ok, err := e.encodeSSEMore(upper, ops); ok {
return true, err
}
2026-10-06 20:08:34 +02:00
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
}
2026-10-06 20:10:22 +02:00
if upper == "CMPXCHG8B" || upper == "CMPXCHG16B" {
return true
}
if upper == "INVPCID" || upper == "XABORT" {
return true
}
2026-10-06 20:10:22 +02:00
if _, ok := xsaveTable[upper]; ok {
return true
}
if before, ok := strings.CutSuffix(upper, "64"); ok {
if _, ok := xsaveTable[before]; ok {
return true
}
}
switch upper {
case "EMMS", "PSHUFW", "PSLLO", "PSRLO", "PMOVMSKB", "MOVQOZX", "MOVZWW", "MOVSWW":
return true
}
if _, ok := sseMaskmov[upper]; ok {
return true
}
if _, ok := mmxShiftImm[upper]; ok {
return true
}
if _, ok := mmxShiftVar[upper]; ok {
return true
}
2026-10-06 20:10:22 +02:00
return false
2026-10-06 20:08:34 +02:00
}