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
- func Decode(hex uint32) (string, error)
- func DisassembleWords(ctx context.Context, tool string, words []uint32) (map[uint32]string, error)
- func FindObjdump() string
- func Normalize(s string) string
- func ParseWordLine(line string) (hex uint32, comment string, ok bool)
- type CommentSource
- type Directive
- type Result
- type Status
- type X86Feature
- type X86Kernel
- type X86Level
- type X86Use
Constants ¶
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 DisassembleWords ¶
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.
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 ¶
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 ¶
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 ¶
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 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
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
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.
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.