golang.org/x/arch@v0.17.0/ppc64/ppc64asm/decode.go (about) 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 "sort" 12 "sync" 13 ) 14 15 const debugDecode = false 16 17 const prefixOpcode = 1 18 19 // instFormat is a decoding rule for one specific instruction form. 20 // an instruction ins matches the rule if ins&Mask == Value 21 // DontCare bits should be zero, but the machine might not reject 22 // ones in those bits, they are mainly reserved for future expansion 23 // of the instruction set. 24 // The Args are stored in the same order as the instruction manual. 25 // 26 // Prefixed instructions are stored as: 27 // 28 // prefix << 32 | suffix, 29 // 30 // Regular instructions are: 31 // 32 // inst << 32 33 type instFormat struct { 34 Op Op 35 Mask uint64 36 Value uint64 37 DontCare uint64 38 Args [6]*argField 39 } 40 41 // argField indicate how to decode an argument to an instruction. 42 // First parse the value from the BitFields, shift it left by Shift 43 // bits to get the actual numerical value. 44 type argField struct { 45 Type ArgType 46 Shift uint8 47 BitFields 48 } 49 50 // Parse parses the Arg out from the given binary instruction i. 51 func (a argField) Parse(i [2]uint32) Arg { 52 switch a.Type { 53 default: 54 return nil 55 case TypeUnknown: 56 return nil 57 case TypeReg: 58 return R0 + Reg(a.BitFields.Parse(i)) 59 case TypeCondRegBit: 60 return Cond0LT + CondReg(a.BitFields.Parse(i)) 61 case TypeCondRegField: 62 return CR0 + CondReg(a.BitFields.Parse(i)) 63 case TypeFPReg: 64 return F0 + Reg(a.BitFields.Parse(i)) 65 case TypeVecReg: 66 return V0 + Reg(a.BitFields.Parse(i)) 67 case TypeVecSReg: 68 return VS0 + Reg(a.BitFields.Parse(i)) 69 case TypeVecSpReg: 70 return VS0 + Reg(a.BitFields.Parse(i))*2 71 case TypeMMAReg: 72 return A0 + Reg(a.BitFields.Parse(i)) 73 case TypeSpReg: 74 return SpReg(a.BitFields.Parse(i)) 75 case TypeImmSigned: 76 return Imm(a.BitFields.ParseSigned(i) << a.Shift) 77 case TypeImmUnsigned: 78 return Imm(a.BitFields.Parse(i) << a.Shift) 79 case TypePCRel: 80 return PCRel(a.BitFields.ParseSigned(i) << a.Shift) 81 case TypeLabel: 82 return Label(a.BitFields.ParseSigned(i) << a.Shift) 83 case TypeOffset: 84 return Offset(a.BitFields.ParseSigned(i) << a.Shift) 85 case TypeNegOffset: 86 // An oddball encoding of offset for hashchk and similar. 87 // e.g hashchk offset is 0b1111111000000000 | DX << 8 | D << 3 88 off := a.BitFields.ParseSigned(i) << a.Shift 89 neg := int64(-1) << (int(a.Shift) + a.BitFields.NumBits()) 90 return Offset(neg | off) 91 } 92 } 93 94 type ArgType int8 95 96 const ( 97 TypeUnknown ArgType = iota 98 TypePCRel // PC-relative address 99 TypeLabel // absolute address 100 TypeReg // integer register 101 TypeCondRegBit // conditional register bit (0-31) 102 TypeCondRegField // conditional register field (0-7) 103 TypeFPReg // floating point register 104 TypeVecReg // vector register 105 TypeVecSReg // VSX register 106 TypeVecSpReg // VSX register pair (even only encoding) 107 TypeMMAReg // MMA register 108 TypeSpReg // special register (depends on Op) 109 TypeImmSigned // signed immediate 110 TypeImmUnsigned // unsigned immediate/flag/mask, this is the catch-all type 111 TypeOffset // signed offset in load/store 112 TypeNegOffset // A negative 16 bit value 0b1111111xxxxx000 encoded as 0bxxxxx (e.g in the hashchk instruction) 113 TypeLast // must be the last one 114 ) 115 116 type InstMaskMap struct { 117 mask uint64 118 insn map[uint64]*instFormat 119 } 120 121 // Note, plxv/pstxv have a 5 bit opcode in the second instruction word. Only match the most significant 5 of 6 bits of the second primary opcode. 122 const lookupOpcodeMask = uint64(0xFC000000F8000000) 123 124 // Three level lookup for any instruction: 125 // 1. Primary opcode map to a list of secondary opcode maps. 126 // 2. A list of opcodes with distinct masks, sorted by largest to smallest mask. 127 // 3. A map to a specific opcodes with a given mask. 128 var getLookupMap = sync.OnceValue(func() map[uint64][]InstMaskMap { 129 lMap := make(map[uint64][]InstMaskMap) 130 for idx, _ := range instFormats { 131 i := &instFormats[idx] 132 pop := i.Value & lookupOpcodeMask 133 var me *InstMaskMap 134 masks := lMap[pop] 135 for im, m := range masks { 136 if m.mask == i.Mask { 137 me = &masks[im] 138 break 139 } 140 } 141 if me == nil { 142 me = &InstMaskMap{i.Mask, map[uint64]*instFormat{}} 143 masks = append(masks, *me) 144 } 145 me.insn[i.Value] = i 146 lMap[pop] = masks 147 } 148 // Reverse sort masks to ensure extended mnemonics match before more generic forms of an opcode (e.x nop over ori 0,0,0) 149 for _, v := range lMap { 150 sort.Slice(v, func(i, j int) bool { 151 return v[i].mask > v[j].mask 152 }) 153 } 154 return lMap 155 }) 156 157 func (t ArgType) String() string { 158 switch t { 159 default: 160 return fmt.Sprintf("ArgType(%d)", int(t)) 161 case TypeUnknown: 162 return "Unknown" 163 case TypeReg: 164 return "Reg" 165 case TypeCondRegBit: 166 return "CondRegBit" 167 case TypeCondRegField: 168 return "CondRegField" 169 case TypeFPReg: 170 return "FPReg" 171 case TypeVecReg: 172 return "VecReg" 173 case TypeVecSReg: 174 return "VecSReg" 175 case TypeVecSpReg: 176 return "VecSpReg" 177 case TypeMMAReg: 178 return "MMAReg" 179 case TypeSpReg: 180 return "SpReg" 181 case TypeImmSigned: 182 return "ImmSigned" 183 case TypeImmUnsigned: 184 return "ImmUnsigned" 185 case TypePCRel: 186 return "PCRel" 187 case TypeLabel: 188 return "Label" 189 case TypeOffset: 190 return "Offset" 191 case TypeNegOffset: 192 return "NegOffset" 193 } 194 } 195 196 func (t ArgType) GoString() string { 197 s := t.String() 198 if t > 0 && t < TypeLast { 199 return "Type" + s 200 } 201 return s 202 } 203 204 var ( 205 // Errors 206 errShort = fmt.Errorf("truncated instruction") 207 errUnknown = fmt.Errorf("unknown instruction") 208 ) 209 210 var decoderCover []bool 211 212 // Decode decodes the leading bytes in src as a single instruction using 213 // byte order ord. 214 func Decode(src []byte, ord binary.ByteOrder) (inst Inst, err error) { 215 if len(src) < 4 { 216 return inst, errShort 217 } 218 if decoderCover == nil { 219 decoderCover = make([]bool, len(instFormats)) 220 } 221 inst.Len = 4 222 ui_extn := [2]uint32{ord.Uint32(src[:inst.Len]), 0} 223 ui := uint64(ui_extn[0]) << 32 224 inst.Enc = ui_extn[0] 225 opcode := inst.Enc >> 26 226 if opcode == prefixOpcode { 227 // This is a prefixed instruction 228 inst.Len = 8 229 if len(src) < 8 { 230 return inst, errShort 231 } 232 // Merge the suffixed word. 233 ui_extn[1] = ord.Uint32(src[4:inst.Len]) 234 ui |= uint64(ui_extn[1]) 235 inst.SuffixEnc = ui_extn[1] 236 } 237 238 fmts := getLookupMap()[ui&lookupOpcodeMask] 239 for i, masks := range fmts { 240 if _, fnd := masks.insn[masks.mask&ui]; !fnd { 241 continue 242 } 243 iform := masks.insn[masks.mask&ui] 244 if ui&iform.DontCare != 0 { 245 if debugDecode { 246 log.Printf("Decode(%#x): unused bit is 1 for Op %s", ui, iform.Op) 247 } 248 // to match GNU objdump (libopcodes), we ignore don't care bits 249 } 250 for i, argfield := range iform.Args { 251 if argfield == nil { 252 break 253 } 254 inst.Args[i] = argfield.Parse(ui_extn) 255 } 256 inst.Op = iform.Op 257 if debugDecode { 258 log.Printf("%#x: search entry %d", ui, i) 259 continue 260 } 261 break 262 } 263 if inst.Op == 0 && inst.Enc != 0 { 264 return inst, errUnknown 265 } 266 return inst, nil 267 }