1
2
3
4
5 package ppc64asm
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "log"
11 )
12
13 const debugDecode = false
14
15 const prefixOpcode = 1
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 type instFormat struct {
32 Op Op
33 Mask uint64
34 Value uint64
35 DontCare uint64
36 Args [6]*argField
37 }
38
39
40
41
42 type argField struct {
43 Type ArgType
44 Shift uint8
45 BitFields
46 }
47
48
49 func (a argField) Parse(i [2]uint32) Arg {
50 switch a.Type {
51 default:
52 return nil
53 case TypeUnknown:
54 return nil
55 case TypeReg:
56 return R0 + Reg(a.BitFields.Parse(i))
57 case TypeCondRegBit:
58 return Cond0LT + CondReg(a.BitFields.Parse(i))
59 case TypeCondRegField:
60 return CR0 + CondReg(a.BitFields.Parse(i))
61 case TypeFPReg:
62 return F0 + Reg(a.BitFields.Parse(i))
63 case TypeVecReg:
64 return V0 + Reg(a.BitFields.Parse(i))
65 case TypeVecSReg:
66 return VS0 + Reg(a.BitFields.Parse(i))
67 case TypeVecSpReg:
68 return VS0 + Reg(a.BitFields.Parse(i))*2
69 case TypeMMAReg:
70 return A0 + Reg(a.BitFields.Parse(i))
71 case TypeSpReg:
72 return SpReg(a.BitFields.Parse(i))
73 case TypeImmSigned:
74 return Imm(a.BitFields.ParseSigned(i) << a.Shift)
75 case TypeImmUnsigned:
76 return Imm(a.BitFields.Parse(i) << a.Shift)
77 case TypePCRel:
78 return PCRel(a.BitFields.ParseSigned(i) << a.Shift)
79 case TypeLabel:
80 return Label(a.BitFields.ParseSigned(i) << a.Shift)
81 case TypeOffset:
82 return Offset(a.BitFields.ParseSigned(i) << a.Shift)
83 case TypeNegOffset:
84
85
86 off := a.BitFields.ParseSigned(i) << a.Shift
87 neg := int64(-1) << (int(a.Shift) + a.BitFields.NumBits())
88 return Offset(neg | off)
89 }
90 }
91
92 type ArgType int8
93
94 const (
95 TypeUnknown ArgType = iota
96 TypePCRel
97 TypeLabel
98 TypeReg
99 TypeCondRegBit
100 TypeCondRegField
101 TypeFPReg
102 TypeVecReg
103 TypeVecSReg
104 TypeVecSpReg
105 TypeMMAReg
106 TypeSpReg
107 TypeImmSigned
108 TypeImmUnsigned
109 TypeOffset
110 TypeNegOffset
111 TypeLast
112 )
113
114 func (t ArgType) String() string {
115 switch t {
116 default:
117 return fmt.Sprintf("ArgType(%d)", int(t))
118 case TypeUnknown:
119 return "Unknown"
120 case TypeReg:
121 return "Reg"
122 case TypeCondRegBit:
123 return "CondRegBit"
124 case TypeCondRegField:
125 return "CondRegField"
126 case TypeFPReg:
127 return "FPReg"
128 case TypeVecReg:
129 return "VecReg"
130 case TypeVecSReg:
131 return "VecSReg"
132 case TypeVecSpReg:
133 return "VecSpReg"
134 case TypeMMAReg:
135 return "MMAReg"
136 case TypeSpReg:
137 return "SpReg"
138 case TypeImmSigned:
139 return "ImmSigned"
140 case TypeImmUnsigned:
141 return "ImmUnsigned"
142 case TypePCRel:
143 return "PCRel"
144 case TypeLabel:
145 return "Label"
146 case TypeOffset:
147 return "Offset"
148 case TypeNegOffset:
149 return "NegOffset"
150 }
151 }
152
153 func (t ArgType) GoString() string {
154 s := t.String()
155 if t > 0 && t < TypeLast {
156 return "Type" + s
157 }
158 return s
159 }
160
161 var (
162
163 errShort = fmt.Errorf("truncated instruction")
164 errUnknown = fmt.Errorf("unknown instruction")
165 )
166
167 var decoderCover []bool
168
169
170
171 func Decode(src []byte, ord binary.ByteOrder) (inst Inst, err error) {
172 if len(src) < 4 {
173 return inst, errShort
174 }
175 if decoderCover == nil {
176 decoderCover = make([]bool, len(instFormats))
177 }
178 inst.Len = 4
179 ui_extn := [2]uint32{ord.Uint32(src[:inst.Len]), 0}
180 ui := uint64(ui_extn[0]) << 32
181 inst.Enc = ui_extn[0]
182 opcode := inst.Enc >> 26
183 if opcode == prefixOpcode {
184
185 inst.Len = 8
186 if len(src) < 8 {
187 return inst, errShort
188 }
189
190 ui_extn[1] = ord.Uint32(src[4:inst.Len])
191 ui |= uint64(ui_extn[1])
192 inst.SuffixEnc = ui_extn[1]
193 }
194 for i, iform := range instFormats {
195 if ui&iform.Mask != iform.Value {
196 continue
197 }
198 if ui&iform.DontCare != 0 {
199 if debugDecode {
200 log.Printf("Decode(%#x): unused bit is 1 for Op %s", ui, iform.Op)
201 }
202
203 }
204 for i, argfield := range iform.Args {
205 if argfield == nil {
206 break
207 }
208 inst.Args[i] = argfield.Parse(ui_extn)
209 }
210 inst.Op = iform.Op
211 if debugDecode {
212 log.Printf("%#x: search entry %d", ui, i)
213 continue
214 }
215 break
216 }
217 if inst.Op == 0 && inst.Enc != 0 {
218 return inst, errUnknown
219 }
220 return inst, nil
221 }
222
View as plain text