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