diff --git a/disasm/parity_test.go b/disasm/parity_test.go index 40786a5..249c0bc 100644 --- a/disasm/parity_test.go +++ b/disasm/parity_test.go @@ -128,6 +128,44 @@ func TestBranchTargetConvention(t *testing.T) { // of the disassembler's text, and the fixtures carry it stripped. } +// TestVectorSpaceStaysRejected pins the instruction spaces x/arch carries +// no decode tables for at all: the RISC-V vector extension (riscv64.s +// spells 40 such rows) and the LoongArch LSX/LASX vector families +// (loong64enc1.s spells 807), plus the loong64 WORD data directive, which +// is no instruction. The corpus assembles every one of these encodings, +// so the rows are honest negatives: they pin today's refusal, and a +// decoder bump that learns one of these spaces flips a row here and asks +// for the naming pass to cover it. +func TestVectorSpaceStaysRejected(t *testing.T) { + for _, tt := range []struct { + a arch.Arch + code []byte + }{ + // riscv64.s: VANDNVV V1, V2, V3 // d7812006 and VCLMULVV V1, + // V2, V3 // d7a12032. + {arch.RISCV, []byte{0xd7, 0x81, 0x20, 0x06}}, + {arch.RISCV, []byte{0xd7, 0xa1, 0x20, 0x32}}, + // loong64enc1.s: VMOVQ V2, (R5)(R5) // a2144438 and the XV + // form // 82144838. + {arch.LOONG64, []byte{0xa2, 0x14, 0x44, 0x38}}, + {arch.LOONG64, []byte{0x82, 0x14, 0x48, 0x38}}, + // loong64enc1.s: VADDW V1, V2, V3 // 43040b70. + {arch.LOONG64, []byte{0x43, 0x04, 0x0b, 0x70}}, + // loong64enc1.s: WORD $74565 // 45230100: a data word the + // assembler emits verbatim, no instruction to decode. + {arch.LOONG64, []byte{0x45, 0x23, 0x01, 0x00}}, + } { + ins, err := Decode(tt.a, tt.code, 0) + if err != nil { + t.Errorf("%s % x: %v", tt.a, tt.code, err) + continue + } + if ins.Text != "???" { + t.Errorf("%s % x: %q, want the placeholder", tt.a, tt.code, ins.Text) + } + } +} + // relativeBranch reports whether the rendered text carries a PC-relative // or position-dependent target. Such an operand is an address, not a // datum: it is faithful to the bytes only at the address the instruction