1
2
3
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
20
21
22
23
24
25
26
27
28
29
30
31
32
33 type instFormat struct {
34 Op Op
35 Mask uint64
36 Value uint64
37 DontCare uint64
38 Args [6]*argField
39 }
40
41
42
43
44 type argField struct {
45 Type ArgType
46 Shift uint8
47 BitFields
48 }
49
50
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
87
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
99 TypeLabel
100 TypeReg
101 TypeCondRegBit
102 TypeCondRegField
103 TypeFPReg
104 TypeVecReg
105 TypeVecSReg
106 TypeVecSpReg
107 TypeMMAReg
108 TypeSpReg
109 TypeImmSigned
110 TypeImmUnsigned
111 TypeOffset
112 TypeNegOffset
113 TypeLast
114 )
115
116 type InstMaskMap struct {
117 mask uint64
118 insn map[uint64]*instFormat
119 }
120
121
122 const lookupOpcodeMask = uint64(0xFC000000F8000000)
123
124
125
126
127
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
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
206 errShort = fmt.Errorf("truncated instruction")
207 errUnknown = fmt.Errorf("unknown instruction")
208 )
209
210 var decoderCover []bool
211
212
213
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
228 inst.Len = 8
229 if len(src) < 8 {
230 return inst, errShort
231 }
232
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
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 }
268
View as plain text