PPCDisassembler.c revision b8a57fe285e684a7ae8475a2641f4013aed85621
1//===------ PPCDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10/* Capstone Disassembler Engine */
11/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
12
13#include <stdio.h>	// DEBUG
14#include <stdlib.h>
15
16#include "../../cs_priv.h"
17
18#include "../../SubtargetFeature.h"
19#include "../../MCInst.h"
20#include "../../MCInstrDesc.h"
21#include "../../MCFixedLenDisassembler.h"
22#include "../../MCRegisterInfo.h"
23#include "../../MCDisassembler.h"
24#include "../../MathExtras.h"
25
26#define GET_REGINFO_ENUM
27#include "PPCGenRegisterInfo.inc"
28
29
30// FIXME: These can be generated by TableGen from the existing register
31// encoding values!
32
33static const unsigned CRRegs[] = {
34	PPC_CR0, PPC_CR1, PPC_CR2, PPC_CR3,
35	PPC_CR4, PPC_CR5, PPC_CR6, PPC_CR7
36};
37
38static const unsigned CRBITRegs[] = {
39	PPC_CR0LT, PPC_CR0GT, PPC_CR0EQ, PPC_CR0UN,
40	PPC_CR1LT, PPC_CR1GT, PPC_CR1EQ, PPC_CR1UN,
41	PPC_CR2LT, PPC_CR2GT, PPC_CR2EQ, PPC_CR2UN,
42	PPC_CR3LT, PPC_CR3GT, PPC_CR3EQ, PPC_CR3UN,
43	PPC_CR4LT, PPC_CR4GT, PPC_CR4EQ, PPC_CR4UN,
44	PPC_CR5LT, PPC_CR5GT, PPC_CR5EQ, PPC_CR5UN,
45	PPC_CR6LT, PPC_CR6GT, PPC_CR6EQ, PPC_CR6UN,
46	PPC_CR7LT, PPC_CR7GT, PPC_CR7EQ, PPC_CR7UN
47};
48
49static const unsigned FRegs[] = {
50	PPC_F0, PPC_F1, PPC_F2, PPC_F3,
51	PPC_F4, PPC_F5, PPC_F6, PPC_F7,
52	PPC_F8, PPC_F9, PPC_F10, PPC_F11,
53	PPC_F12, PPC_F13, PPC_F14, PPC_F15,
54	PPC_F16, PPC_F17, PPC_F18, PPC_F19,
55	PPC_F20, PPC_F21, PPC_F22, PPC_F23,
56	PPC_F24, PPC_F25, PPC_F26, PPC_F27,
57	PPC_F28, PPC_F29, PPC_F30, PPC_F31
58};
59
60static const unsigned VRegs[] = {
61	PPC_V0, PPC_V1, PPC_V2, PPC_V3,
62	PPC_V4, PPC_V5, PPC_V6, PPC_V7,
63	PPC_V8, PPC_V9, PPC_V10, PPC_V11,
64	PPC_V12, PPC_V13, PPC_V14, PPC_V15,
65	PPC_V16, PPC_V17, PPC_V18, PPC_V19,
66	PPC_V20, PPC_V21, PPC_V22, PPC_V23,
67	PPC_V24, PPC_V25, PPC_V26, PPC_V27,
68	PPC_V28, PPC_V29, PPC_V30, PPC_V31
69};
70
71static const unsigned GPRegs[] = {
72	PPC_R0, PPC_R1, PPC_R2, PPC_R3,
73	PPC_R4, PPC_R5, PPC_R6, PPC_R7,
74	PPC_R8, PPC_R9, PPC_R10, PPC_R11,
75	PPC_R12, PPC_R13, PPC_R14, PPC_R15,
76	PPC_R16, PPC_R17, PPC_R18, PPC_R19,
77	PPC_R20, PPC_R21, PPC_R22, PPC_R23,
78	PPC_R24, PPC_R25, PPC_R26, PPC_R27,
79	PPC_R28, PPC_R29, PPC_R30, PPC_R31
80};
81
82static const unsigned GP0Regs[] = {
83	PPC_ZERO, PPC_R1, PPC_R2, PPC_R3,
84	PPC_R4, PPC_R5, PPC_R6, PPC_R7,
85	PPC_R8, PPC_R9, PPC_R10, PPC_R11,
86	PPC_R12, PPC_R13, PPC_R14, PPC_R15,
87	PPC_R16, PPC_R17, PPC_R18, PPC_R19,
88	PPC_R20, PPC_R21, PPC_R22, PPC_R23,
89	PPC_R24, PPC_R25, PPC_R26, PPC_R27,
90	PPC_R28, PPC_R29, PPC_R30, PPC_R31
91};
92
93static const unsigned G8Regs[] = {
94	PPC_X0, PPC_X1, PPC_X2, PPC_X3,
95	PPC_X4, PPC_X5, PPC_X6, PPC_X7,
96	PPC_X8, PPC_X9, PPC_X10, PPC_X11,
97	PPC_X12, PPC_X13, PPC_X14, PPC_X15,
98	PPC_X16, PPC_X17, PPC_X18, PPC_X19,
99	PPC_X20, PPC_X21, PPC_X22, PPC_X23,
100	PPC_X24, PPC_X25, PPC_X26, PPC_X27,
101	PPC_X28, PPC_X29, PPC_X30, PPC_X31
102};
103
104static uint64_t getFeatureBits(int feature)
105{
106	// enable all features
107	return (uint64_t)-1;
108}
109
110static DecodeStatus decodeRegisterClass(MCInst *Inst, uint64_t RegNo,
111		const unsigned *Regs)
112{
113	// assert(RegNo < N && "Invalid register number");
114	MCInst_addOperand(Inst, MCOperand_CreateReg(Regs[RegNo]));
115	return MCDisassembler_Success;
116}
117
118static DecodeStatus DecodeCRRCRegisterClass(MCInst *Inst, uint64_t RegNo,
119		uint64_t Address,
120		const void *Decoder)
121{
122	return decodeRegisterClass(Inst, RegNo, CRRegs);
123}
124
125static DecodeStatus DecodeCRBITRCRegisterClass(MCInst *Inst, uint64_t RegNo,
126		uint64_t Address,
127		const void *Decoder)
128{
129	return decodeRegisterClass(Inst, RegNo, CRBITRegs);
130}
131
132static DecodeStatus DecodeF4RCRegisterClass(MCInst *Inst, uint64_t RegNo,
133		uint64_t Address,
134		const void *Decoder)
135{
136	return decodeRegisterClass(Inst, RegNo, FRegs);
137}
138
139static DecodeStatus DecodeF8RCRegisterClass(MCInst *Inst, uint64_t RegNo,
140		uint64_t Address,
141		const void *Decoder)
142{
143	return decodeRegisterClass(Inst, RegNo, FRegs);
144}
145
146static DecodeStatus DecodeVRRCRegisterClass(MCInst *Inst, uint64_t RegNo,
147		uint64_t Address,
148		const void *Decoder)
149{
150	return decodeRegisterClass(Inst, RegNo, VRegs);
151}
152
153static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint64_t RegNo,
154		uint64_t Address,
155		const void *Decoder)
156{
157	return decodeRegisterClass(Inst, RegNo, GPRegs);
158}
159
160static DecodeStatus DecodeGPRC_NOR0RegisterClass(MCInst *Inst, uint64_t RegNo,
161		uint64_t Address,
162		const void *Decoder)
163{
164	return decodeRegisterClass(Inst, RegNo, GP0Regs);
165}
166
167static DecodeStatus DecodeG8RCRegisterClass(MCInst *Inst, uint64_t RegNo,
168		uint64_t Address,
169		const void *Decoder)
170{
171	return decodeRegisterClass(Inst, RegNo, G8Regs);
172}
173
174#define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass
175#define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass
176
177static DecodeStatus decodeUImmOperand(MCInst *Inst, uint64_t Imm,
178		int64_t Address, const void *Decoder, unsigned N)
179{
180	//assert(isUInt<N>(Imm) && "Invalid immediate");
181	MCInst_addOperand(Inst, MCOperand_CreateImm(Imm));
182	return MCDisassembler_Success;
183}
184
185static DecodeStatus decodeSImmOperand(MCInst *Inst, uint64_t Imm,
186		int64_t Address, const void *Decoder, unsigned N)
187{
188	// assert(isUInt<N>(Imm) && "Invalid immediate");
189	MCInst_addOperand(Inst, MCOperand_CreateImm(SignExtend64(Imm, N)));
190	return MCDisassembler_Success;
191}
192
193
194#define GET_INSTRINFO_ENUM
195#include "PPCGenInstrInfo.inc"
196
197static DecodeStatus decodeMemRIOperands(MCInst *Inst, uint64_t Imm,
198		int64_t Address, const void *Decoder)
199{
200	// Decode the memri field (imm, reg), which has the low 16-bits as the
201	// displacement and the next 5 bits as the register #.
202
203	uint64_t Base = Imm >> 16;
204	uint64_t Disp = Imm & 0xFFFF;
205
206	// assert(Base < 32 && "Invalid base register");
207
208	switch (MCInst_getOpcode(Inst)) {
209		default: break;
210		case PPC_LBZU:
211		case PPC_LHAU:
212		case PPC_LHZU:
213		case PPC_LWZU:
214		case PPC_LFSU:
215		case PPC_LFDU:
216				 // Add the tied output operand.
217				 MCInst_addOperand(Inst, MCOperand_CreateReg(GP0Regs[Base]));
218				 break;
219		case PPC_STBU:
220		case PPC_STHU:
221		case PPC_STWU:
222		case PPC_STFSU:
223		case PPC_STFDU:
224				 MCInst_insert(Inst, 0, MCOperand_CreateReg(GP0Regs[Base]));
225				 break;
226	}
227
228	MCInst_addOperand(Inst, MCOperand_CreateImm(SignExtend64(Disp, 16)));
229	MCInst_addOperand(Inst, MCOperand_CreateReg(GP0Regs[Base]));
230	return MCDisassembler_Success;
231}
232
233static DecodeStatus decodeMemRIXOperands(MCInst *Inst, uint64_t Imm,
234		int64_t Address, const void *Decoder)
235{
236	// Decode the memrix field (imm, reg), which has the low 14-bits as the
237	// displacement and the next 5 bits as the register #.
238
239	uint64_t Base = Imm >> 14;
240	uint64_t Disp = Imm & 0x3FFF;
241
242	// assert(Base < 32 && "Invalid base register");
243
244	if (MCInst_getOpcode(Inst) == PPC_LDU)
245		// Add the tied output operand.
246		MCInst_addOperand(Inst, MCOperand_CreateReg(GP0Regs[Base]));
247	else if (MCInst_getOpcode(Inst) == PPC_STDU)
248		MCInst_insert(Inst, 0, MCOperand_CreateReg(GP0Regs[Base]));
249
250	MCInst_addOperand(Inst, MCOperand_CreateImm(SignExtend64(Disp << 2, 16)));
251	MCInst_addOperand(Inst, MCOperand_CreateReg(GP0Regs[Base]));
252	return MCDisassembler_Success;
253}
254
255static DecodeStatus decodeCRBitMOperand(MCInst *Inst, uint64_t Imm,
256		int64_t Address, const void *Decoder)
257{
258	// The cr bit encoding is 0x80 >> cr_reg_num.
259
260	unsigned Zeros = CountTrailingZeros_64(Imm);
261	// assert(Zeros < 8 && "Invalid CR bit value");
262
263	MCInst_addOperand(Inst, MCOperand_CreateReg(CRRegs[7 - Zeros]));
264	return MCDisassembler_Success;
265}
266
267#include "PPCGenDisassemblerTables.inc"
268
269static DecodeStatus getInstruction(MCInst *MI,
270		const uint8_t *code, size_t code_len,
271		uint16_t *Size,
272		uint64_t Address, MCRegisterInfo *MRI)
273{
274	// Get the four bytes of the instruction.
275	if (code_len < 4) {
276		// not enough data
277		*Size = 0;
278		return MCDisassembler_Fail;
279	}
280
281	// The instruction is big-endian encoded.
282	uint32_t insn;
283	if (MI->csh->mode & CS_MODE_BIG_ENDIAN)
284		insn = (code[0] << 24) | (code[1] << 16) |
285			(code[2] <<  8) | (code[3] <<  0);
286	else
287		insn = (code[3] << 24) | (code[2] << 16) |
288			(code[1] <<  8) | (code[0] <<  0);
289
290	DecodeStatus result = decodeInstruction_4(DecoderTable32, MI, insn, Address, 4);
291	if (result != MCDisassembler_Fail) {
292		*Size = 4;
293		return result;
294	}
295
296	// report error
297	MCInst_clear(MI);
298	*Size = 0;
299	return MCDisassembler_Fail;
300}
301
302bool PPC_getInstruction(csh ud, unsigned char *code, size_t code_len, MCInst *instr, uint16_t *size, uint64_t address, void *info)
303{
304	DecodeStatus status = getInstruction(instr,
305			code, code_len,
306			size,
307			address, (MCRegisterInfo *)info);
308
309	return status == MCDisassembler_Success;
310}
311
312#define GET_REGINFO_MC_DESC
313#include "PPCGenRegisterInfo.inc"
314void PPC_init(MCRegisterInfo *MRI)
315{
316	/*
317	   InitMCRegisterInfo( PPCRegDesc, 182, RA, PC,
318	   		PPCMCRegisterClasses, 15,
319	   		PPCRegUnitRoots,
320	   		138,
321	   		PPCRegDiffLists,
322	   		PPCRegStrings,
323	   		PPCSubRegIdxLists,
324	   		6,
325	   		PPCSubRegIdxRanges,
326	   		PPCRegEncodingTable);
327	*/
328
329	MCRegisterInfo_InitMCRegisterInfo(MRI, PPCRegDesc, 182,
330			0, 0,
331			PPCMCRegisterClasses, 15,
332			0, 0,
333			PPCRegDiffLists,
334			0,
335			PPCSubRegIdxLists, 6,
336			0);
337}
338