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
5package ppc64asm
6
7import (
8	"bytes"
9	"fmt"
10)
11
12type Inst struct {
13	Op   Op     // Opcode mnemonic
14	Enc  uint32 // Raw encoding bits
15	Len  int    // Length of encoding in bytes.
16	Args Args   // Instruction arguments, in Power ISA manual order.
17}
18
19func (i Inst) String() string {
20	var buf bytes.Buffer
21	buf.WriteString(i.Op.String())
22	for j, arg := range i.Args {
23		if arg == nil {
24			break
25		}
26		if j == 0 {
27			buf.WriteString(" ")
28		} else {
29			buf.WriteString(", ")
30		}
31		buf.WriteString(arg.String())
32	}
33	return buf.String()
34}
35
36// An Op is an instruction operation.
37type Op uint16
38
39func (o Op) String() string {
40	if int(o) >= len(opstr) || opstr[o] == "" {
41		return fmt.Sprintf("Op(%d)", int(o))
42	}
43	return opstr[o]
44}
45
46// An Arg is a single instruction argument, one of these types: Reg, CondReg, SpReg, Imm, PCRel, Label, or Offset.
47type Arg interface {
48	IsArg()
49	String() string
50}
51
52// An Args holds the instruction arguments.
53// If an instruction has fewer than 4 arguments,
54// the final elements in the array are nil.
55type Args [5]Arg
56
57// A Reg is a single register. The zero value means R0, not the absence of a register.
58// It also includes special registers.
59type Reg uint16
60
61const (
62	_ Reg = iota
63	R0
64	R1
65	R2
66	R3
67	R4
68	R5
69	R6
70	R7
71	R8
72	R9
73	R10
74	R11
75	R12
76	R13
77	R14
78	R15
79	R16
80	R17
81	R18
82	R19
83	R20
84	R21
85	R22
86	R23
87	R24
88	R25
89	R26
90	R27
91	R28
92	R29
93	R30
94	R31
95	F0
96	F1
97	F2
98	F3
99	F4
100	F5
101	F6
102	F7
103	F8
104	F9
105	F10
106	F11
107	F12
108	F13
109	F14
110	F15
111	F16
112	F17
113	F18
114	F19
115	F20
116	F21
117	F22
118	F23
119	F24
120	F25
121	F26
122	F27
123	F28
124	F29
125	F30
126	F31
127	V0 // VSX extension, F0 is V0[0:63].
128	V1
129	V2
130	V3
131	V4
132	V5
133	V6
134	V7
135	V8
136	V9
137	V10
138	V11
139	V12
140	V13
141	V14
142	V15
143	V16
144	V17
145	V18
146	V19
147	V20
148	V21
149	V22
150	V23
151	V24
152	V25
153	V26
154	V27
155	V28
156	V29
157	V30
158	V31
159	VS0
160	VS1
161	VS2
162	VS3
163	VS4
164	VS5
165	VS6
166	VS7
167	VS8
168	VS9
169	VS10
170	VS11
171	VS12
172	VS13
173	VS14
174	VS15
175	VS16
176	VS17
177	VS18
178	VS19
179	VS20
180	VS21
181	VS22
182	VS23
183	VS24
184	VS25
185	VS26
186	VS27
187	VS28
188	VS29
189	VS30
190	VS31
191	VS32
192	VS33
193	VS34
194	VS35
195	VS36
196	VS37
197	VS38
198	VS39
199	VS40
200	VS41
201	VS42
202	VS43
203	VS44
204	VS45
205	VS46
206	VS47
207	VS48
208	VS49
209	VS50
210	VS51
211	VS52
212	VS53
213	VS54
214	VS55
215	VS56
216	VS57
217	VS58
218	VS59
219	VS60
220	VS61
221	VS62
222	VS63
223)
224
225func (Reg) IsArg() {}
226func (r Reg) String() string {
227	switch {
228	case R0 <= r && r <= R31:
229		return fmt.Sprintf("r%d", int(r-R0))
230	case F0 <= r && r <= F31:
231		return fmt.Sprintf("f%d", int(r-F0))
232	case V0 <= r && r <= V31:
233		return fmt.Sprintf("v%d", int(r-V0))
234	case VS0 <= r && r <= VS63:
235		return fmt.Sprintf("vs%d", int(r-VS0))
236	default:
237		return fmt.Sprintf("Reg(%d)", int(r))
238	}
239}
240
241// CondReg is a bit or field in the conditon register.
242type CondReg int8
243
244const (
245	_ CondReg = iota
246	// Condition Regster bits
247	Cond0LT
248	Cond0GT
249	Cond0EQ
250	Cond0SO
251	Cond1LT
252	Cond1GT
253	Cond1EQ
254	Cond1SO
255	Cond2LT
256	Cond2GT
257	Cond2EQ
258	Cond2SO
259	Cond3LT
260	Cond3GT
261	Cond3EQ
262	Cond3SO
263	Cond4LT
264	Cond4GT
265	Cond4EQ
266	Cond4SO
267	Cond5LT
268	Cond5GT
269	Cond5EQ
270	Cond5SO
271	Cond6LT
272	Cond6GT
273	Cond6EQ
274	Cond6SO
275	Cond7LT
276	Cond7GT
277	Cond7EQ
278	Cond7SO
279	// Condition Register Fields
280	CR0
281	CR1
282	CR2
283	CR3
284	CR4
285	CR5
286	CR6
287	CR7
288)
289
290func (CondReg) IsArg() {}
291func (c CondReg) String() string {
292	switch {
293	default:
294		return fmt.Sprintf("CondReg(%d)", int(c))
295	case c >= CR0:
296		return fmt.Sprintf("CR%d", int(c-CR0))
297	case c >= Cond0LT && c < CR0:
298		return fmt.Sprintf("Cond%d%s", int((c-Cond0LT)/4), [4]string{"LT", "GT", "EQ", "SO"}[(c-Cond0LT)%4])
299	}
300}
301
302// SpReg is a special register, its meaning depends on Op.
303type SpReg uint16
304
305const (
306	SpRegZero SpReg = 0
307)
308
309func (SpReg) IsArg() {}
310func (s SpReg) String() string {
311	return fmt.Sprintf("SpReg(%d)", int(s))
312}
313
314// PCRel is a PC-relative offset, used only in branch instructions.
315type PCRel int32
316
317func (PCRel) IsArg() {}
318func (r PCRel) String() string {
319	return fmt.Sprintf("PC%+#x", int32(r))
320}
321
322// A Label is a code (text) address, used only in absolute branch instructions.
323type Label uint32
324
325func (Label) IsArg() {}
326func (l Label) String() string {
327	return fmt.Sprintf("%#x", uint32(l))
328}
329
330// Imm represents an immediate number.
331type Imm int32
332
333func (Imm) IsArg() {}
334func (i Imm) String() string {
335	return fmt.Sprintf("%d", int32(i))
336}
337
338// Offset represents a memory offset immediate.
339type Offset int32
340
341func (Offset) IsArg() {}
342func (o Offset) String() string {
343	return fmt.Sprintf("%+d", int32(o))
344}
345