// Copyright (c) 2026 Petr Balvín (https://petrbalvin.org) // SPDX-License-Identifier: BSD-3-Clause package lint import ( "testing" "sourcedock.dev/petrbalvin/gasm-devkit/asm" ) func TestUnencodableInstruction(t *testing.T) { // MOVBE is a real x86 instruction the architecture table knows about; // before the encoder grows it, lint must flag the gap at edit time. diags := lintSrc(t, ` #include "textflag.h" TEXT ·f(SB), NOSPLIT, $0 MOVQ AX, BX RET `) if codes(diags)[CodeUnencodable] != 0 { t.Fatalf("encodable instructions must not be flagged: %+v", diags) } // A mnemonic that is neither in the table nor encodable fires // unknown-instruction, not unencodable. diags = lintSrc(t, ` #include "textflag.h" TEXT ·f(SB), NOSPLIT, $0 FROBNICATE AX, BX RET `) if codes(diags)[CodeUnencodable] != 0 || codes(diags)[CodeUnknownInstr] != 1 { t.Fatalf("unknown instruction must fire unknown-instruction only: %+v", diags) } } func TestEncodableMirror(t *testing.T) { // Spot-check the predicate against instructions from every dispatch // family of the encoder. yes := []string{ "RET", "NOP", "CALL", "JMP", "JEQ", "JLT", "MOVQ", "MOVL", "ADDQ", "CMPQ", "LEAQ", "TESTL", "NOTL", "DECL", "SHRQ", "IMULQ", "PUSHQ", "POPQ", "BSWAPL", "TZCNTQ", "MOVBLZX", "MOVOU", "MOVSD", "PREFETCHT0", "PREFETCHNTA", "VMOVDQU", "VPCMPUB", "VPCOMPRESSD", "VPERMB", "VPGATHERDD", "VPSCATTERDD", "KMOVQ", "KANDNW", "VPMOVMSKB", "CMOVLGT", "SETNE", "PSHUFB", "PADDB", } for _, m := range yes { if !asm.Encodable(m) { t.Errorf("Encodable(%q) = false, want true", m) } } no := []string{"FROBNICATE", "MOVXX", "CMOVXX", "SETXX"} for _, m := range no { if asm.Encodable(m) { t.Errorf("Encodable(%q) = true, want false", m) } } }