diff --git a/internal/inst/table.go b/internal/inst/table.go new file mode 100644 index 0000000..532de80 --- /dev/null +++ b/internal/inst/table.go @@ -0,0 +1,12 @@ +package inst + +//go:generate avogen -data ../data -output ztable.go godata + +func Lookup(opcode string) (Instruction, bool) { + for _, i := range Instructions { + if i.Opcode == opcode { + return i, true + } + } + return Instruction{}, false +} diff --git a/internal/inst/inst_test.go b/internal/inst/table_test.go similarity index 61% rename from internal/inst/inst_test.go rename to internal/inst/table_test.go index e9d1a35..6659c30 100644 --- a/internal/inst/inst_test.go +++ b/internal/inst/table_test.go @@ -1,6 +1,8 @@ package inst_test import ( + "io/ioutil" + "strings" "testing" "github.com/mmcloughlin/avo/internal/gen" @@ -49,3 +51,27 @@ func TestAssembles(t *testing.T) { } test.Assembles(t, b) } + +func TestLookup(t *testing.T) { + if _, found := inst.Lookup("CPUID"); !found { + t.Fatalf("missing CPUID") + } + if _, found := inst.Lookup(strings.Repeat("XXX", 13)); found { + t.Fatalf("lookup returns true on an absurd opcode") + } +} + +func TestStdLibOpcodes(t *testing.T) { + t.Skip("currently does not pass") + + b, err := ioutil.ReadFile("testdata/stdlibopcodes.txt") + if err != nil { + t.Fatal(err) + } + opcodes := strings.Fields(string(b)) + for _, opcode := range opcodes { + if _, found := inst.Lookup(opcode); !found { + t.Errorf("missing instruction %s (used in stdlib asm)", opcode) + } + } +} diff --git a/internal/inst/testdata/stdlibopcodes.txt b/internal/inst/testdata/stdlibopcodes.txt new file mode 100644 index 0000000..bfc2c2b --- /dev/null +++ b/internal/inst/testdata/stdlibopcodes.txt @@ -0,0 +1,202 @@ +ADCQ +ADCXQ +ADDB +ADDL +ADDQ +ADDSD +ADOXQ +AESDEC +AESDECLAST +AESENC +AESENCLAST +AESIMC +AESKEYGENASSIST +ANDB +ANDL +ANDNPD +ANDPD +ANDQ +BSFL +BSFQ +BSRQ +BSWAPL +BSWAPQ +BTQ +BYTE +CALL +CMOVQCC +CMOVQCS +CMOVQEQ +CMOVQGT +CMOVQLT +CMOVQNE +CMPB +CMPL +CMPQ +CMPSD +CMPW +CMPXCHGL +CMPXCHGQ +COMISD +CRC32B +CRC32L +CRC32Q +CRC32W +CVTSD2SL +CVTSL2SD +CVTSQ2SD +CVTTSD2SQ +DECB +DECQ +DIVL +DIVQ +DIVSD +FUNCDATA +IMUL3Q +IMULQ +INCB +INCQ +INT +JA +JAE +JB +JBE +JC +JCC +JE +JEQ +JG +JGE +JGT +JHI +JL +JLE +JLS +JLT +JMP +JNC +JNE +JNZ +JZ +LDMXCSR +LEAL +LEAQ +MAXSD +MINSD +MOVAPD +MOVAPS +MOVB +MOVBLZX +MOVBQZX +MOVD +MOVL +MOVLQSX +MOVLQZX +MOVO +MOVOA +MOVOU +MOVQ +MOVSD +MOVUPS +MOVW +MULL +MULQ +MULSD +MULXQ +NEGQ +NOTL +NOTQ +ORB +ORL +ORPD +ORQ +PADDD +PADDL +PAND +PANDN +PCLMULQDQ +PCMPEQB +PCMPEQL +PCMPESTRI +PEXTRB +PEXTRD +PINSRB +PINSRD +PINSRQ +PINSRW +PMOVMSKB +POPCNTL +POPQ +PREFETCHNTA +PSHUFB +PSHUFD +PSHUFHW +PSHUFL +PSLLDQ +PSLLL +PSLLQ +PSRAL +PSRLDQ +PSRLL +PSRLQ +PSUBL +PUNPCKLBW +PUSHQ +PXOR +RCRQ +RORXL +RORXQ +SALQ +SARQ +SBBQ +SETEQ +SETGT +SETHI +SHLL +SHLQ +SHRL +SHRQ +SHUFPS +SQRTSD +STMXCSR +SUBL +SUBQ +SUBSD +TESTB +TESTL +TESTQ +TESTW +VADDSD +VFMADD213SD +VFNMADD231SD +VMOVDQA +VMOVDQU +VMOVNTDQ +VPADDD +VPADDQ +VPALIGNR +VPAND +VPBLENDD +VPBROADCASTB +VPCMPEQB +VPERM2F128 +VPERM2I128 +VPMOVMSKB +VPOR +VPSHUFB +VPSHUFD +VPSLLD +VPSLLQ +VPSRLD +VPSRLDQ +VPSRLQ +VPTEST +VPXOR +XADDL +XADDQ +XCHGL +XCHGQ +XORB +XORL +XORPS +XORQ diff --git a/script/stdlibopcodes b/script/stdlibopcodes new file mode 100755 index 0000000..df8147f --- /dev/null +++ b/script/stdlibopcodes @@ -0,0 +1,22 @@ +#!/bin/bash -e + +eval $(go env) + +workdir=$(mktemp -d) + +# Provide stub "go_asm.h". +include=${workdir}/include +mkdir -p ${include} +echo '#define get_tls ' > ${include}/go_asm.h + +# Preprocess all assembly files. +asm=${workdir}/all.s +find ${GOROOT}/src -name '*_amd64.s' | while read s; do + gcc -E -I${GOROOT}/pkg/include -I${include} ${s} >>${asm} +done + +# Extract instructions. +awk '/^[[:space:]]+[A-Z0-9]+[[:space:]]+/ { print $1 }' ${asm} | sort | uniq + +# Clean. +rm -rf ${workdir}