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