1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package x86csv provides means to work with "x86.csv". 6 // Only latest version of "x86.csv" format is supported. 7 // 8 // Terminology: 9 // given "OPCODE [ARGS...]" line; 10 // Opcode - instruction name/mnemonic/class. 11 // Args - instruction operands. 12 // Syntax - Opcode with Args. 13 package x86csv 14 15 import ( 16 "strings" 17 ) 18 19 // An Inst describes single x86 instruction encoding form. 20 type Inst struct { 21 // Intel syntax (example: "SHR r/m32, imm8"). 22 Intel string 23 24 // Go assembler syntax (example: "SHRL imm8, r/m32"). 25 Go string 26 27 // GNU binutils syntax (example: "shrl imm8, r/m32"). 28 GNU string 29 30 // Binary encoding (example: "C1 /4 ib"). 31 Encoding string 32 33 // Validity in 32bit mode ("V", "I" or "N.E."). 34 Mode32 string 35 36 // Validity in 64bit mode ("V", "I", "N.E.", "N.P.", "N.I." or "N.S."). 37 Mode64 string 38 39 // CPUID feature flags required (comma-separated). 40 CPUID string 41 42 // Hints about instruction (comma-separated). 43 // See "x86spec" package to see detailed overview of possible 44 // tags and their meaning. 45 Tags string 46 47 // Read/write action of the instruction on its arguments, in Intel order. 48 // For example, "rw,r" denotes that "SHR r/m32, imm8" reads and writes 49 // its first argument but only reads its second argument. 50 Action string 51 52 // Whether Intel syntax has encoding forms distinguished only by 53 // operand size, like most arithmetic instructions ("" or "Y"). 54 Multisize string 55 56 // DataSize is the size of the data operation in bits ("8" for MOVB, "16" for MOVW, and so on). 57 DataSize string 58 } 59 60 // IntelOpcode returns the opcode in the Intel syntax. 61 func (inst *Inst) IntelOpcode() string { return instOpcode(inst.Intel) } 62 63 // GoOpcode returns the opcode in Go (Plan9) syntax. 64 func (inst *Inst) GoOpcode() string { return instOpcode(inst.Go) } 65 66 // GNUOpcode returns the opcode in GNU binutils (mostly AT&T) syntax. 67 func (inst *Inst) GNUOpcode() string { return instOpcode(inst.GNU) } 68 69 // IntelArgs returns the arguments in the Intel syntax. 70 func (inst *Inst) IntelArgs() []string { return instArgs(inst.Intel) } 71 72 // GoArgs returns the arguments in Go (Plan9) syntax. 73 func (inst *Inst) GoArgs() []string { return instArgs(inst.Go) } 74 75 // GNUArgs returns the arguments in GNU binutils (mostly AT&T) syntax. 76 func (inst *Inst) GNUArgs() []string { return instArgs(inst.GNU) } 77 78 // HasTag reports whether inst tag list contains the specified tag. 79 func (inst *Inst) HasTag(tag string) bool { 80 i := strings.Index(inst.Tags, tag) 81 if i == -1 { 82 return false 83 } 84 leftOK := i == 0 || 85 (inst.Tags[i-1] == ',') 86 rigthOK := i+len(tag) == len(inst.Tags) || 87 (inst.Tags[i+len(tag)] == ',') 88 return leftOK && rigthOK 89 } 90 91 // instOpcode returns the opcode from an instruction syntax. 92 func instOpcode(syntax string) string { 93 i := strings.Index(syntax, " ") 94 if i == -1 { 95 return syntax 96 } 97 return syntax[:i] 98 } 99 100 // instArgs returns the arguments from an instruction syntax. 101 func instArgs(syntax string) []string { 102 i := strings.Index(syntax, " ") 103 if i < 0 { 104 return nil 105 } 106 args := strings.Split(syntax[i+1:], ",") 107 for i := range args { 108 args[i] = strings.TrimSpace(args[i]) 109 } 110 return args 111 } 112