1 // Copyright 2014 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 ppc64asm 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "log" 11 ) 12 13 const debugDecode = false 14 15 // instFormat is a decoding rule for one specific instruction form. 16 // a uint32 instruction ins matches the rule if ins&Mask == Value 17 // DontCare bits should be zero, but the machine might not reject 18 // ones in those bits, they are mainly reserved for future expansion 19 // of the instruction set. 20 // The Args are stored in the same order as the instruction manual. 21 type instFormat struct { 22 Op Op 23 Mask uint32 24 Value uint32 25 DontCare uint32 26 Args [5]*argField 27 } 28 29 // argField indicate how to decode an argument to an instruction. 30 // First parse the value from the BitFields, shift it left by Shift 31 // bits to get the actual numerical value. 32 type argField struct { 33 Type ArgType 34 Shift uint8 35 BitFields 36 } 37 38 // Parse parses the Arg out from the given binary instruction i. 39 func (a argField) Parse(i uint32) Arg { 40 switch a.Type { 41 default: 42 return nil 43 case TypeUnknown: 44 return nil 45 case TypeReg: 46 return R0 + Reg(a.BitFields.Parse(i)) 47 case TypeCondRegBit: 48 return Cond0LT + CondReg(a.BitFields.Parse(i)) 49 case TypeCondRegField: 50 return CR0 + CondReg(a.BitFields.Parse(i)) 51 case TypeFPReg: 52 return F0 + Reg(a.BitFields.Parse(i)) 53 case TypeVecReg: 54 return V0 + Reg(a.BitFields.Parse(i)) 55 case TypeVecSReg: 56 return VS0 + Reg(a.BitFields.Parse(i)) 57 case TypeSpReg: 58 return SpReg(a.BitFields.Parse(i)) 59 case TypeImmSigned: 60 return Imm(a.BitFields.ParseSigned(i) << a.Shift) 61 case TypeImmUnsigned: 62 return Imm(a.BitFields.Parse(i) << a.Shift) 63 case TypePCRel: 64 return PCRel(a.BitFields.ParseSigned(i) << a.Shift) 65 case TypeLabel: 66 return Label(a.BitFields.ParseSigned(i) << a.Shift) 67 case TypeOffset: 68 return Offset(a.BitFields.ParseSigned(i) << a.Shift) 69 } 70 } 71 72 type ArgType int8 73 74 const ( 75 TypeUnknown ArgType = iota 76 TypePCRel // PC-relative address 77 TypeLabel // absolute address 78 TypeReg // integer register 79 TypeCondRegBit // conditional register bit (0-31) 80 TypeCondRegField // conditional register field (0-7) 81 TypeFPReg // floating point register 82 TypeVecReg // vector register 83 TypeVecSReg // VSX register 84 TypeSpReg // special register (depends on Op) 85 TypeImmSigned // signed immediate 86 TypeImmUnsigned // unsigned immediate/flag/mask, this is the catch-all type 87 TypeOffset // signed offset in load/store 88 TypeLast // must be the last one 89 ) 90 91 func (t ArgType) String() string { 92 switch t { 93 default: 94 return fmt.Sprintf("ArgType(%d)", int(t)) 95 case TypeUnknown: 96 return "Unknown" 97 case TypeReg: 98 return "Reg" 99 case TypeCondRegBit: 100 return "CondRegBit" 101 case TypeCondRegField: 102 return "CondRegField" 103 case TypeFPReg: 104 return "FPReg" 105 case TypeVecReg: 106 return "VecReg" 107 case TypeVecSReg: 108 return "VecSReg" 109 case TypeSpReg: 110 return "SpReg" 111 case TypeImmSigned: 112 return "ImmSigned" 113 case TypeImmUnsigned: 114 return "ImmUnsigned" 115 case TypePCRel: 116 return "PCRel" 117 case TypeLabel: 118 return "Label" 119 case TypeOffset: 120 return "Offset" 121 } 122 } 123 124 func (t ArgType) GoString() string { 125 s := t.String() 126 if t > 0 && t < TypeLast { 127 return "Type" + s 128 } 129 return s 130 } 131 132 var ( 133 // Errors 134 errShort = fmt.Errorf("truncated instruction") 135 errUnknown = fmt.Errorf("unknown instruction") 136 ) 137 138 var decoderCover []bool 139 140 // Decode decodes the leading bytes in src as a single instruction using 141 // byte order ord. 142 func Decode(src []byte, ord binary.ByteOrder) (inst Inst, err error) { 143 if len(src) < 4 { 144 return inst, errShort 145 } 146 if decoderCover == nil { 147 decoderCover = make([]bool, len(instFormats)) 148 } 149 inst.Len = 4 // only 4-byte instructions are supported 150 ui := ord.Uint32(src[:inst.Len]) 151 inst.Enc = ui 152 for i, iform := range instFormats { 153 if ui&iform.Mask != iform.Value { 154 continue 155 } 156 if ui&iform.DontCare != 0 { 157 if debugDecode { 158 log.Printf("Decode(%#x): unused bit is 1 for Op %s", ui, iform.Op) 159 } 160 // to match GNU objdump (libopcodes), we ignore don't care bits 161 } 162 for i, argfield := range iform.Args { 163 if argfield == nil { 164 break 165 } 166 inst.Args[i] = argfield.Parse(ui) 167 } 168 inst.Op = iform.Op 169 if debugDecode { 170 log.Printf("%#x: search entry %d", ui, i) 171 continue 172 } 173 break 174 } 175 if inst.Op == 0 { 176 return inst, errUnknown 177 } 178 return inst, nil 179 } 180