asmcheck

package
v1.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package asmcheck validates this repository's hand-written assembly.

Two independent checks live here. ARM64 hand-encoded WORD directives are decoded and compared against the instruction their comment claims, using the same disassembler go tool objdump uses. AMD64 kernels are classified by the x86 SIMD feature level their instructions require, so a kernel's body cannot outrun the CPU feature its dispatch guard demands.

Both are pure source analysis, so they run on any architecture with no ARM or x86 hardware.

Index

Constants

View Source
const SIMDObjdumpEnv = "SIMD_OBJDUMP"

SIMDObjdumpEnv names an environment variable that, when set, overrides the objdump program used for the aarch64 cross-check (highest priority).

Variables

This section is empty.

Functions

func Decode

func Decode(hex uint32) (string, error)

Decode returns the GNU-syntax disassembly of a 32-bit ARM64 instruction word.

func DisassembleWords

func DisassembleWords(ctx context.Context, tool string, words []uint32) (map[uint32]string, error)

DisassembleWords disassembles each 32-bit word with the given objdump, returning a map from instruction word to its GNU-syntax disassembly. Words are written little-endian (aarch64 byte order) and decoded with `-D -b binary -m aarch64`. Identical words collapse to a single map entry.

func FindObjdump

func FindObjdump() string

FindObjdump returns the path to an objdump that can disassemble aarch64 FP16 (.8H) instructions, or "" if none is usable. Each candidate is probed on a known instruction, so a wrong-architecture objdump (or a non-GNU one such as llvm-objdump that does not understand -m aarch64) is rejected rather than trusted.

func Normalize

func Normalize(s string) string

Normalize canonicalizes an instruction string for comparison: upper case, single-spaced, no space after commas, with aliased mnemonics folded.

func ParseWordLine

func ParseWordLine(line string) (hex uint32, comment string, ok bool)

ParseWordLine extracts the hex value and inline comment from a single assembly line. ok is false when the line is not a WORD $0x... directive.

Types

type CommentSource

type CommentSource int

CommentSource records where a directive's describing comment came from.

const (
	// NoComment means the WORD directive has no associated comment.
	NoComment CommentSource = iota
	// InlineComment means the comment is on the same line as the WORD.
	InlineComment
	// PrecedingComment means the comment is on the line directly above.
	PrecedingComment
)

type Directive

type Directive struct {
	Line    int    // 1-based line number
	Hex     uint32 // the 32-bit instruction word
	Comment string // the claimed instruction text, empty if NoComment
	Source  CommentSource
}

Directive is one parsed WORD $0x... line with its associated comment.

func ScanSource

func ScanSource(src string) []Directive

ScanSource parses every ARM64 WORD $0x... directive in src, associating each with its inline comment, or the comment on the line directly above it. For the AMD64 feature-level scanner see ScanX86Source.

type Result

type Result struct {
	Status  Status
	Decoded string // normalized decoded instruction (empty when Undecodable)
	Claimed string // normalized claimed instruction
	Err     error  // decode error when Undecodable
}

Result is the outcome of Verify.

func Verify

func Verify(hex uint32, claimed string) Result

Verify decodes hex and checks it against the claimed instruction text. The decoded instruction must equal the claim or be a token-boundary prefix of it, so comments may carry a trailing free-form annotation after the operands.

func VerifyDecoded

func VerifyDecoded(decoded, claimed string) Result

VerifyDecoded checks an already-decoded instruction string against the claimed instruction text, using the same normalization and token-boundary prefix rule as Verify. It lets callers supply a disassembly from a source other than arm64asm (for example aarch64 objdump, see objdump.go) while sharing one comparison policy. The status is never Undecodable: the input is already decoded, so the result is either Match or Mismatch.

type Status

type Status int

Status is the outcome of verifying one WORD directive.

const (
	// Match means the decoded instruction matches the comment.
	Match Status = iota + 1
	// Mismatch means the bytes decode to a different instruction than claimed.
	Mismatch
	// Undecodable means the disassembler could not decode the bytes.
	Undecodable
)

type X86Feature added in v1.7.0

type X86Feature string

X86Feature names a CPUID feature bit that is ORTHOGONAL to the AVX level ladder, so it cannot be expressed as an X86Level. A CPU can have AVX1 with or without it, which is why it needs its own axis rather than a rung.

const X86FeatureFMA X86Feature = "FMA"

X86FeatureFMA is FMA3, CPUID.01H:ECX.FMA[bit 12], reported by Go as cpu.X86.HasFMA. It is a separate bit from AVX: Sandy Bridge and Ivy Bridge have AVX and no FMA3, and this repo keeps an initAVXNoFMA dispatch tier for exactly those parts. A VFMADD-family instruction reaching such a CPU faults with #UD (SIGILL), the same failure #196 and #197 were about on the AVX2 axis.

type X86Kernel added in v1.7.0

type X86Kernel struct {
	Name  string   // symbol name, without the leading interpunct
	Line  int      // 1-based line of the TEXT directive
	Level X86Level // the highest level any instruction in the body needs
	Uses  []X86Use // qualifying instructions, in source order; nil when clean
}

X86Kernel is one TEXT symbol together with the instructions in it that need more than plain AVX1.

Off-ladder features are derived from Uses rather than stored alongside Level, so there is one place a feature can be recorded and no second field to keep in step with it.

func ScanX86Source added in v1.7.0

func ScanX86Source(src string) []X86Kernel

ScanX86Source parses every TEXT symbol in an AMD64 assembly source and reports each one's required feature level together with the instructions that set it. Kernels are returned in source order. Content before the first TEXT directive (constant pools, includes) is ignored.

func (X86Kernel) FeatureUses added in v1.7.0

func (k X86Kernel) FeatureUses(f X86Feature) []X86Use

FeatureUses returns the instructions in the kernel that require f, in source order.

func (X86Kernel) Needs added in v1.7.0

func (k X86Kernel) Needs(f X86Feature) bool

Needs reports whether the kernel's body uses an instruction requiring f.

type X86Level added in v1.7.0

type X86Level int

X86Level is the minimum x86 SIMD feature level an instruction requires.

const (
	// X86LevelAVX covers AVX1 and everything below it (SSE, scalar, and any
	// non-SIMD instruction). It is the zero value, so an unclassified
	// instruction never inflates a kernel's level.
	X86LevelAVX X86Level = iota
	// X86LevelAVX2 means the instruction was introduced by AVX2.
	X86LevelAVX2
	// X86LevelAVX512 means the instruction needs an AVX-512 extension.
	X86LevelAVX512
)

func DeclaredX86Level added in v1.7.0

func DeclaredX86Level(name string) X86Level

DeclaredX86Level reports the feature level a kernel's name claims, from its suffix. Names ending in AVX512 claim AVX-512 and names ending in AVX2 claim AVX2. AVXVNNI also claims AVX2: AVX-VNNI is the VEX-encoded form of the dot-product instructions and every part that implements it also implements AVX2. Everything else (an ...AVX, ...SSE2 or unsuffixed kernel) claims no more than AVX1.

func (X86Level) String added in v1.7.0

func (l X86Level) String() string

String names the feature level as it appears in this repo's kernel suffixes.

type X86Use added in v1.7.0

type X86Use struct {
	Line    int        // 1-based line number in the scanned source
	Text    string     // the instruction as written, with any comment stripped
	Level   X86Level   // the level the instruction needs
	Feature X86Feature // an off-ladder feature it needs, or "" for none
	Reason  string     // why it needs that level or feature
}

X86Use is one instruction that requires a feature level above AVX1, or a feature off the level ladder, or both.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL