1//===- MipsDisassembler.cpp - Disassembler for Mips -------------*- 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// This file is part of the Mips Disassembler. 11// 12//===----------------------------------------------------------------------===// 13 14#include "Mips.h" 15#include "MipsSubtarget.h" 16#include "MipsRegisterInfo.h" 17#include "llvm/MC/EDInstInfo.h" 18#include "llvm/MC/MCDisassembler.h" 19#include "llvm/MC/MCFixedLenDisassembler.h" 20#include "llvm/Support/MemoryObject.h" 21#include "llvm/Support/TargetRegistry.h" 22#include "llvm/MC/MCSubtargetInfo.h" 23#include "llvm/MC/MCInst.h" 24#include "llvm/Support/MathExtras.h" 25 26#include "MipsGenEDInfo.inc" 27 28using namespace llvm; 29 30typedef MCDisassembler::DecodeStatus DecodeStatus; 31 32namespace { 33 34/// MipsDisassemblerBase - a disasembler class for Mips. 35class MipsDisassemblerBase : public MCDisassembler { 36public: 37 /// Constructor - Initializes the disassembler. 38 /// 39 MipsDisassemblerBase(const MCSubtargetInfo &STI, const MCRegisterInfo *Info, 40 bool bigEndian) : 41 MCDisassembler(STI), RegInfo(Info), isBigEndian(bigEndian) {} 42 43 virtual ~MipsDisassemblerBase() {} 44 45 /// getEDInfo - See MCDisassembler. 46 const EDInstInfo *getEDInfo() const; 47 48 const MCRegisterInfo *getRegInfo() const { return RegInfo; } 49 50private: 51 const MCRegisterInfo *RegInfo; 52protected: 53 bool isBigEndian; 54}; 55 56/// MipsDisassembler - a disasembler class for Mips32. 57class MipsDisassembler : public MipsDisassemblerBase { 58public: 59 /// Constructor - Initializes the disassembler. 60 /// 61 MipsDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info, 62 bool bigEndian) : 63 MipsDisassemblerBase(STI, Info, bigEndian) {} 64 65 /// getInstruction - See MCDisassembler. 66 virtual DecodeStatus getInstruction(MCInst &instr, 67 uint64_t &size, 68 const MemoryObject ®ion, 69 uint64_t address, 70 raw_ostream &vStream, 71 raw_ostream &cStream) const; 72}; 73 74 75/// Mips64Disassembler - a disasembler class for Mips64. 76class Mips64Disassembler : public MipsDisassemblerBase { 77public: 78 /// Constructor - Initializes the disassembler. 79 /// 80 Mips64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info, 81 bool bigEndian) : 82 MipsDisassemblerBase(STI, Info, bigEndian) {} 83 84 /// getInstruction - See MCDisassembler. 85 virtual DecodeStatus getInstruction(MCInst &instr, 86 uint64_t &size, 87 const MemoryObject ®ion, 88 uint64_t address, 89 raw_ostream &vStream, 90 raw_ostream &cStream) const; 91}; 92 93} // end anonymous namespace 94 95const EDInstInfo *MipsDisassemblerBase::getEDInfo() const { 96 return instInfoMips; 97} 98 99// Forward declare these because the autogenerated code will reference them. 100// Definitions are further down. 101static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst, 102 unsigned RegNo, 103 uint64_t Address, 104 const void *Decoder); 105 106static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst, 107 unsigned RegNo, 108 uint64_t Address, 109 const void *Decoder); 110 111static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, 112 unsigned RegNo, 113 uint64_t Address, 114 const void *Decoder); 115 116static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, 117 unsigned RegNo, 118 uint64_t Address, 119 const void *Decoder); 120 121static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst, 122 unsigned RegNo, 123 uint64_t Address, 124 const void *Decoder); 125 126static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst, 127 unsigned Insn, 128 uint64_t Address, 129 const void *Decoder); 130 131static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, 132 unsigned RegNo, 133 uint64_t Address, 134 const void *Decoder); 135 136static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst, 137 unsigned Insn, 138 uint64_t Address, 139 const void *Decoder); 140 141static DecodeStatus DecodeBranchTarget(MCInst &Inst, 142 unsigned Offset, 143 uint64_t Address, 144 const void *Decoder); 145 146static DecodeStatus DecodeBC1(MCInst &Inst, 147 unsigned Insn, 148 uint64_t Address, 149 const void *Decoder); 150 151 152static DecodeStatus DecodeJumpTarget(MCInst &Inst, 153 unsigned Insn, 154 uint64_t Address, 155 const void *Decoder); 156 157static DecodeStatus DecodeMem(MCInst &Inst, 158 unsigned Insn, 159 uint64_t Address, 160 const void *Decoder); 161 162static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn, 163 uint64_t Address, 164 const void *Decoder); 165 166static DecodeStatus DecodeSimm16(MCInst &Inst, 167 unsigned Insn, 168 uint64_t Address, 169 const void *Decoder); 170 171static DecodeStatus DecodeCondCode(MCInst &Inst, 172 unsigned Insn, 173 uint64_t Address, 174 const void *Decoder); 175 176static DecodeStatus DecodeInsSize(MCInst &Inst, 177 unsigned Insn, 178 uint64_t Address, 179 const void *Decoder); 180 181static DecodeStatus DecodeExtSize(MCInst &Inst, 182 unsigned Insn, 183 uint64_t Address, 184 const void *Decoder); 185 186namespace llvm { 187extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, 188 TheMips64elTarget; 189} 190 191static MCDisassembler *createMipsDisassembler( 192 const Target &T, 193 const MCSubtargetInfo &STI) { 194 return new MipsDisassembler(STI, T.createMCRegInfo(""), true); 195} 196 197static MCDisassembler *createMipselDisassembler( 198 const Target &T, 199 const MCSubtargetInfo &STI) { 200 return new MipsDisassembler(STI, T.createMCRegInfo(""), false); 201} 202 203static MCDisassembler *createMips64Disassembler( 204 const Target &T, 205 const MCSubtargetInfo &STI) { 206 return new Mips64Disassembler(STI, T.createMCRegInfo(""), true); 207} 208 209static MCDisassembler *createMips64elDisassembler( 210 const Target &T, 211 const MCSubtargetInfo &STI) { 212 return new Mips64Disassembler(STI, T.createMCRegInfo(""), false); 213} 214 215extern "C" void LLVMInitializeMipsDisassembler() { 216 // Register the disassembler. 217 TargetRegistry::RegisterMCDisassembler(TheMipsTarget, 218 createMipsDisassembler); 219 TargetRegistry::RegisterMCDisassembler(TheMipselTarget, 220 createMipselDisassembler); 221 TargetRegistry::RegisterMCDisassembler(TheMips64Target, 222 createMips64Disassembler); 223 TargetRegistry::RegisterMCDisassembler(TheMips64elTarget, 224 createMips64elDisassembler); 225} 226 227 228#include "MipsGenDisassemblerTables.inc" 229 230 /// readInstruction - read four bytes from the MemoryObject 231 /// and return 32 bit word sorted according to the given endianess 232static DecodeStatus readInstruction32(const MemoryObject ®ion, 233 uint64_t address, 234 uint64_t &size, 235 uint32_t &insn, 236 bool isBigEndian) { 237 uint8_t Bytes[4]; 238 239 // We want to read exactly 4 Bytes of data. 240 if (region.readBytes(address, 4, (uint8_t*)Bytes, NULL) == -1) { 241 size = 0; 242 return MCDisassembler::Fail; 243 } 244 245 if (isBigEndian) { 246 // Encoded as a big-endian 32-bit word in the stream. 247 insn = (Bytes[3] << 0) | 248 (Bytes[2] << 8) | 249 (Bytes[1] << 16) | 250 (Bytes[0] << 24); 251 } 252 else { 253 // Encoded as a small-endian 32-bit word in the stream. 254 insn = (Bytes[0] << 0) | 255 (Bytes[1] << 8) | 256 (Bytes[2] << 16) | 257 (Bytes[3] << 24); 258 } 259 260 return MCDisassembler::Success; 261} 262 263DecodeStatus 264MipsDisassembler::getInstruction(MCInst &instr, 265 uint64_t &Size, 266 const MemoryObject &Region, 267 uint64_t Address, 268 raw_ostream &vStream, 269 raw_ostream &cStream) const { 270 uint32_t Insn; 271 272 DecodeStatus Result = readInstruction32(Region, Address, Size, 273 Insn, isBigEndian); 274 if (Result == MCDisassembler::Fail) 275 return MCDisassembler::Fail; 276 277 // Calling the auto-generated decoder function. 278 Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address, 279 this, STI); 280 if (Result != MCDisassembler::Fail) { 281 Size = 4; 282 return Result; 283 } 284 285 return MCDisassembler::Fail; 286} 287 288DecodeStatus 289Mips64Disassembler::getInstruction(MCInst &instr, 290 uint64_t &Size, 291 const MemoryObject &Region, 292 uint64_t Address, 293 raw_ostream &vStream, 294 raw_ostream &cStream) const { 295 uint32_t Insn; 296 297 DecodeStatus Result = readInstruction32(Region, Address, Size, 298 Insn, isBigEndian); 299 if (Result == MCDisassembler::Fail) 300 return MCDisassembler::Fail; 301 302 // Calling the auto-generated decoder function. 303 Result = decodeInstruction(DecoderTableMips6432, instr, Insn, Address, 304 this, STI); 305 if (Result != MCDisassembler::Fail) { 306 Size = 4; 307 return Result; 308 } 309 // If we fail to decode in Mips64 decoder space we can try in Mips32 310 Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address, 311 this, STI); 312 if (Result != MCDisassembler::Fail) { 313 Size = 4; 314 return Result; 315 } 316 317 return MCDisassembler::Fail; 318} 319 320static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { 321 const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D); 322 return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo); 323} 324 325static DecodeStatus DecodeCPU64RegsRegisterClass(MCInst &Inst, 326 unsigned RegNo, 327 uint64_t Address, 328 const void *Decoder) { 329 330 if (RegNo > 31) 331 return MCDisassembler::Fail; 332 333 unsigned Reg = getReg(Decoder, Mips::CPU64RegsRegClassID, RegNo); 334 Inst.addOperand(MCOperand::CreateReg(Reg)); 335 return MCDisassembler::Success; 336} 337 338static DecodeStatus DecodeCPURegsRegisterClass(MCInst &Inst, 339 unsigned RegNo, 340 uint64_t Address, 341 const void *Decoder) { 342 if (RegNo > 31) 343 return MCDisassembler::Fail; 344 unsigned Reg = getReg(Decoder, Mips::CPURegsRegClassID, RegNo); 345 Inst.addOperand(MCOperand::CreateReg(Reg)); 346 return MCDisassembler::Success; 347} 348 349static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, 350 unsigned RegNo, 351 uint64_t Address, 352 const void *Decoder) { 353 if (RegNo > 31) 354 return MCDisassembler::Fail; 355 356 unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo); 357 Inst.addOperand(MCOperand::CreateReg(Reg)); 358 return MCDisassembler::Success; 359} 360 361static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, 362 unsigned RegNo, 363 uint64_t Address, 364 const void *Decoder) { 365 if (RegNo > 31) 366 return MCDisassembler::Fail; 367 368 unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo); 369 Inst.addOperand(MCOperand::CreateReg(Reg)); 370 return MCDisassembler::Success; 371} 372 373static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst, 374 unsigned RegNo, 375 uint64_t Address, 376 const void *Decoder) { 377 Inst.addOperand(MCOperand::CreateReg(RegNo)); 378 return MCDisassembler::Success; 379} 380 381static DecodeStatus DecodeMem(MCInst &Inst, 382 unsigned Insn, 383 uint64_t Address, 384 const void *Decoder) { 385 int Offset = SignExtend32<16>(Insn & 0xffff); 386 unsigned Reg = fieldFromInstruction(Insn, 16, 5); 387 unsigned Base = fieldFromInstruction(Insn, 21, 5); 388 389 Reg = getReg(Decoder, Mips::CPURegsRegClassID, Reg); 390 Base = getReg(Decoder, Mips::CPURegsRegClassID, Base); 391 392 if(Inst.getOpcode() == Mips::SC){ 393 Inst.addOperand(MCOperand::CreateReg(Reg)); 394 } 395 396 Inst.addOperand(MCOperand::CreateReg(Reg)); 397 Inst.addOperand(MCOperand::CreateReg(Base)); 398 Inst.addOperand(MCOperand::CreateImm(Offset)); 399 400 return MCDisassembler::Success; 401} 402 403static DecodeStatus DecodeFMem(MCInst &Inst, 404 unsigned Insn, 405 uint64_t Address, 406 const void *Decoder) { 407 int Offset = SignExtend32<16>(Insn & 0xffff); 408 unsigned Reg = fieldFromInstruction(Insn, 16, 5); 409 unsigned Base = fieldFromInstruction(Insn, 21, 5); 410 411 Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); 412 Base = getReg(Decoder, Mips::CPURegsRegClassID, Base); 413 414 Inst.addOperand(MCOperand::CreateReg(Reg)); 415 Inst.addOperand(MCOperand::CreateReg(Base)); 416 Inst.addOperand(MCOperand::CreateImm(Offset)); 417 418 return MCDisassembler::Success; 419} 420 421 422static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst, 423 unsigned RegNo, 424 uint64_t Address, 425 const void *Decoder) { 426 // Currently only hardware register 29 is supported. 427 if (RegNo != 29) 428 return MCDisassembler::Fail; 429 Inst.addOperand(MCOperand::CreateReg(Mips::HWR29)); 430 return MCDisassembler::Success; 431} 432 433static DecodeStatus DecodeCondCode(MCInst &Inst, 434 unsigned Insn, 435 uint64_t Address, 436 const void *Decoder) { 437 int CondCode = Insn & 0xf; 438 Inst.addOperand(MCOperand::CreateImm(CondCode)); 439 return MCDisassembler::Success; 440} 441 442static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, 443 unsigned RegNo, 444 uint64_t Address, 445 const void *Decoder) { 446 if (RegNo > 30 || RegNo %2) 447 return MCDisassembler::Fail; 448 449 ; 450 unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2); 451 Inst.addOperand(MCOperand::CreateReg(Reg)); 452 return MCDisassembler::Success; 453} 454 455static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst, 456 unsigned RegNo, 457 uint64_t Address, 458 const void *Decoder) { 459 //Currently only hardware register 29 is supported 460 if (RegNo != 29) 461 return MCDisassembler::Fail; 462 Inst.addOperand(MCOperand::CreateReg(Mips::HWR29_64)); 463 return MCDisassembler::Success; 464} 465 466static DecodeStatus DecodeBranchTarget(MCInst &Inst, 467 unsigned Offset, 468 uint64_t Address, 469 const void *Decoder) { 470 unsigned BranchOffset = Offset & 0xffff; 471 BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4; 472 Inst.addOperand(MCOperand::CreateImm(BranchOffset)); 473 return MCDisassembler::Success; 474} 475 476static DecodeStatus DecodeBC1(MCInst &Inst, 477 unsigned Insn, 478 uint64_t Address, 479 const void *Decoder) { 480 unsigned BranchOffset = Insn & 0xffff; 481 BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4; 482 Inst.addOperand(MCOperand::CreateImm(BranchOffset)); 483 return MCDisassembler::Success; 484} 485 486static DecodeStatus DecodeJumpTarget(MCInst &Inst, 487 unsigned Insn, 488 uint64_t Address, 489 const void *Decoder) { 490 491 unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2; 492 Inst.addOperand(MCOperand::CreateImm(JumpOffset)); 493 return MCDisassembler::Success; 494} 495 496 497static DecodeStatus DecodeSimm16(MCInst &Inst, 498 unsigned Insn, 499 uint64_t Address, 500 const void *Decoder) { 501 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Insn))); 502 return MCDisassembler::Success; 503} 504 505static DecodeStatus DecodeInsSize(MCInst &Inst, 506 unsigned Insn, 507 uint64_t Address, 508 const void *Decoder) { 509 // First we need to grab the pos(lsb) from MCInst. 510 int Pos = Inst.getOperand(2).getImm(); 511 int Size = (int) Insn - Pos + 1; 512 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size))); 513 return MCDisassembler::Success; 514} 515 516static DecodeStatus DecodeExtSize(MCInst &Inst, 517 unsigned Insn, 518 uint64_t Address, 519 const void *Decoder) { 520 int Size = (int) Insn + 1; 521 Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size))); 522 return MCDisassembler::Success; 523} 524