llvm-6502/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp
2010-11-13 05:48:21 +00:00

649 lines
20 KiB
C++

//===- MBlazeDisassembler.cpp - Disassembler for MicroBlaze ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is part of the MBlaze Disassembler. It contains code to translate
// the data produced by the decoder into MCInsts.
//
//===----------------------------------------------------------------------===//
#include "MBlaze.h"
#include "MBlazeInstrInfo.h"
#include "MBlazeDisassembler.h"
#include "llvm/MC/EDInstInfo.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/raw_ostream.h"
// #include "MBlazeGenDecoderTables.inc"
// #include "MBlazeGenRegisterNames.inc"
#include "MBlazeGenInstrInfo.inc"
#include "MBlazeGenEDInfo.inc"
using namespace llvm;
const unsigned UNSUPPORTED = -1;
static unsigned mblazeBinary2Opcode[] = {
MBlaze::ADD, MBlaze::RSUB, MBlaze::ADDC, MBlaze::RSUBC, //00,01,02,03
MBlaze::ADDK, MBlaze::RSUBK, MBlaze::ADDKC, MBlaze::RSUBKC, //04,05,06,07
MBlaze::ADDI, MBlaze::RSUBI, MBlaze::ADDIC, MBlaze::RSUBIC, //08,09,0A,0B
MBlaze::ADDIK, MBlaze::RSUBIK, MBlaze::ADDIKC, MBlaze::RSUBIKC, //0C,0D,0E,0F
MBlaze::MUL, MBlaze::BSRL, MBlaze::IDIV, MBlaze::GETD, //10,11,12,13
UNSUPPORTED, UNSUPPORTED, MBlaze::FADD, UNSUPPORTED, //14,15,16,17
MBlaze::MULI, MBlaze::BSRLI, UNSUPPORTED, MBlaze::GET, //18,19,1A,1B
UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, //1C,1D,1E,1F
MBlaze::OR, MBlaze::AND, MBlaze::XOR, MBlaze::ANDN, //20,21,22,23
MBlaze::SEXT8, MBlaze::MFS, MBlaze::BR, MBlaze::BEQ, //24,25,26,27
MBlaze::ORI, MBlaze::ANDI, MBlaze::XORI, MBlaze::ANDNI, //28,29,2A,2B
MBlaze::IMM, MBlaze::RTSD, MBlaze::BRI, MBlaze::BEQI, //2C,2D,2E,2F
MBlaze::LBU, MBlaze::LHU, MBlaze::LW, UNSUPPORTED, //30,31,32,33
MBlaze::SB, MBlaze::SH, MBlaze::SW, UNSUPPORTED, //34,35,36,37
MBlaze::LBUI, MBlaze::LHUI, MBlaze::LWI, UNSUPPORTED, //38,39,3A,3B
MBlaze::SBI, MBlaze::SHI, MBlaze::SWI, UNSUPPORTED, //3C,3D,3E,3F
};
static unsigned getRD(uint32_t insn) {
return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>21)&0x1F);
}
static unsigned getRA(uint32_t insn) {
return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F);
}
static unsigned getRB(uint32_t insn) {
return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F);
}
static int64_t getRS(uint32_t insn) {
int16_t val = (insn & 0x3FFF);
return val;
}
static int64_t getIMM(uint32_t insn) {
int16_t val = (insn & 0xFFFF);
return val;
}
static int64_t getSHT(uint32_t insn) {
int16_t val = (insn & 0x1F);
return val;
}
static unsigned getFLAGS(int32_t insn) {
return (insn & 0x7FF);
}
static int64_t getFSL(uint32_t insn) {
int16_t val = (insn & 0xF);
return val;
}
static unsigned decodeMUL(uint32_t insn) {
switch (getFLAGS(insn)) {
default: return UNSUPPORTED;
case 0: return MBlaze::MUL;
case 1: return MBlaze::MULH;
case 2: return MBlaze::MULHSU;
case 3: return MBlaze::MULHU;
}
}
static unsigned decodeSEXT(uint32_t insn) {
switch (insn&0x7FF) {
default: return UNSUPPORTED;
case 0x60: return MBlaze::SEXT8;
case 0x68: return MBlaze::WIC;
case 0x64: return MBlaze::WDC;
case 0x66: return MBlaze::WDCC;
case 0x74: return MBlaze::WDCF;
case 0x61: return MBlaze::SEXT16;
case 0x41: return MBlaze::SRL;
case 0x21: return MBlaze::SRC;
case 0x01: return MBlaze::SRA;
}
}
static unsigned decodeBEQ(uint32_t insn) {
switch ((insn>>21)&0x1F) {
default: return UNSUPPORTED;
case 0x00: return MBlaze::BEQ;
case 0x10: return MBlaze::BEQD;
case 0x05: return MBlaze::BGE;
case 0x15: return MBlaze::BGED;
case 0x04: return MBlaze::BGT;
case 0x14: return MBlaze::BGTD;
case 0x03: return MBlaze::BLE;
case 0x13: return MBlaze::BLED;
case 0x02: return MBlaze::BLT;
case 0x12: return MBlaze::BLTD;
case 0x01: return MBlaze::BNE;
case 0x11: return MBlaze::BNED;
}
}
static unsigned decodeBEQI(uint32_t insn) {
switch ((insn>>21)&0x1F) {
default: return UNSUPPORTED;
case 0x00: return MBlaze::BEQI;
case 0x10: return MBlaze::BEQID;
case 0x05: return MBlaze::BGEI;
case 0x15: return MBlaze::BGEID;
case 0x04: return MBlaze::BGTI;
case 0x14: return MBlaze::BGTID;
case 0x03: return MBlaze::BLEI;
case 0x13: return MBlaze::BLEID;
case 0x02: return MBlaze::BLTI;
case 0x12: return MBlaze::BLTID;
case 0x01: return MBlaze::BNEI;
case 0x11: return MBlaze::BNEID;
}
}
static unsigned decodeBR(uint32_t insn) {
switch ((insn>>16)&0x1F) {
default: return UNSUPPORTED;
case 0x00: return MBlaze::BR;
case 0x08: return MBlaze::BRA;
case 0x0C: return MBlaze::BRK;
case 0x10: return MBlaze::BRD;
case 0x14: return MBlaze::BRLD;
case 0x18: return MBlaze::BRAD;
case 0x1C: return MBlaze::BRALD;
}
}
static unsigned decodeBRI(uint32_t insn) {
switch ((insn>>16)&0x1F) {
default: return UNSUPPORTED;
case 0x00: return MBlaze::BRI;
case 0x08: return MBlaze::BRAI;
case 0x0C: return MBlaze::BRKI;
case 0x10: return MBlaze::BRID;
case 0x14: return MBlaze::BRLID;
case 0x18: return MBlaze::BRAID;
case 0x1C: return MBlaze::BRALID;
}
}
static unsigned decodeBSRL(uint32_t insn) {
switch ((insn>>9)&0x3) {
default: return UNSUPPORTED;
case 0x2: return MBlaze::BSLL;
case 0x1: return MBlaze::BSRA;
case 0x0: return MBlaze::BSRL;
}
}
static unsigned decodeBSRLI(uint32_t insn) {
switch ((insn>>9)&0x3) {
default: return UNSUPPORTED;
case 0x2: return MBlaze::BSLLI;
case 0x1: return MBlaze::BSRAI;
case 0x0: return MBlaze::BSRLI;
}
}
static unsigned decodeRSUBK(uint32_t insn) {
switch (getFLAGS(insn)) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::RSUBK;
case 0x1: return MBlaze::CMP;
case 0x3: return MBlaze::CMPU;
}
}
static unsigned decodeFADD(uint32_t insn) {
switch (getFLAGS(insn)) {
default: return UNSUPPORTED;
case 0x000: return MBlaze::FADD;
case 0x080: return MBlaze::FRSUB;
case 0x100: return MBlaze::FMUL;
case 0x180: return MBlaze::FDIV;
case 0x200: return MBlaze::FCMP_UN;
case 0x210: return MBlaze::FCMP_LT;
case 0x220: return MBlaze::FCMP_EQ;
case 0x230: return MBlaze::FCMP_LE;
case 0x240: return MBlaze::FCMP_GT;
case 0x250: return MBlaze::FCMP_NE;
case 0x260: return MBlaze::FCMP_GE;
case 0x280: return MBlaze::FLT;
case 0x300: return MBlaze::FINT;
case 0x380: return MBlaze::FSQRT;
}
}
static unsigned decodeGET(uint32_t insn) {
switch ((insn>>10)&0x3F) {
default: return UNSUPPORTED;
case 0x00: return MBlaze::GET;
case 0x01: return MBlaze::EGET;
case 0x02: return MBlaze::AGET;
case 0x03: return MBlaze::EAGET;
case 0x04: return MBlaze::TGET;
case 0x05: return MBlaze::TEGET;
case 0x06: return MBlaze::TAGET;
case 0x07: return MBlaze::TEAGET;
case 0x08: return MBlaze::CGET;
case 0x09: return MBlaze::ECGET;
case 0x0A: return MBlaze::CAGET;
case 0x0B: return MBlaze::ECAGET;
case 0x0C: return MBlaze::TCGET;
case 0x0D: return MBlaze::TECGET;
case 0x0E: return MBlaze::TCAGET;
case 0x0F: return MBlaze::TECAGET;
case 0x10: return MBlaze::NGET;
case 0x11: return MBlaze::NEGET;
case 0x12: return MBlaze::NAGET;
case 0x13: return MBlaze::NEAGET;
case 0x14: return MBlaze::TNGET;
case 0x15: return MBlaze::TNEGET;
case 0x16: return MBlaze::TNAGET;
case 0x17: return MBlaze::TNEAGET;
case 0x18: return MBlaze::NCGET;
case 0x19: return MBlaze::NECGET;
case 0x1A: return MBlaze::NCAGET;
case 0x1B: return MBlaze::NECAGET;
case 0x1C: return MBlaze::TNCGET;
case 0x1D: return MBlaze::TNECGET;
case 0x1E: return MBlaze::TNCAGET;
case 0x1F: return MBlaze::TNECAGET;
case 0x20: return MBlaze::PUT;
case 0x22: return MBlaze::APUT;
case 0x24: return MBlaze::TPUT;
case 0x26: return MBlaze::TAPUT;
case 0x28: return MBlaze::CPUT;
case 0x2A: return MBlaze::CAPUT;
case 0x2C: return MBlaze::TCPUT;
case 0x2E: return MBlaze::TCAPUT;
case 0x30: return MBlaze::NPUT;
case 0x32: return MBlaze::NAPUT;
case 0x34: return MBlaze::TNPUT;
case 0x36: return MBlaze::TNAPUT;
case 0x38: return MBlaze::NCPUT;
case 0x3A: return MBlaze::NCAPUT;
case 0x3C: return MBlaze::TNCPUT;
case 0x3E: return MBlaze::TNCAPUT;
}
}
static unsigned decodeGETD(uint32_t insn) {
switch ((insn>>5)&0x3F) {
default: return UNSUPPORTED;
case 0x00: return MBlaze::GETD;
case 0x01: return MBlaze::EGETD;
case 0x02: return MBlaze::AGETD;
case 0x03: return MBlaze::EAGETD;
case 0x04: return MBlaze::TGETD;
case 0x05: return MBlaze::TEGETD;
case 0x06: return MBlaze::TAGETD;
case 0x07: return MBlaze::TEAGETD;
case 0x08: return MBlaze::CGETD;
case 0x09: return MBlaze::ECGETD;
case 0x0A: return MBlaze::CAGETD;
case 0x0B: return MBlaze::ECAGETD;
case 0x0C: return MBlaze::TCGETD;
case 0x0D: return MBlaze::TECGETD;
case 0x0E: return MBlaze::TCAGETD;
case 0x0F: return MBlaze::TECAGETD;
case 0x10: return MBlaze::NGETD;
case 0x11: return MBlaze::NEGETD;
case 0x12: return MBlaze::NAGETD;
case 0x13: return MBlaze::NEAGETD;
case 0x14: return MBlaze::TNGETD;
case 0x15: return MBlaze::TNEGETD;
case 0x16: return MBlaze::TNAGETD;
case 0x17: return MBlaze::TNEAGETD;
case 0x18: return MBlaze::NCGETD;
case 0x19: return MBlaze::NECGETD;
case 0x1A: return MBlaze::NCAGETD;
case 0x1B: return MBlaze::NECAGETD;
case 0x1C: return MBlaze::TNCGETD;
case 0x1D: return MBlaze::TNECGETD;
case 0x1E: return MBlaze::TNCAGETD;
case 0x1F: return MBlaze::TNECAGETD;
case 0x20: return MBlaze::PUTD;
case 0x22: return MBlaze::APUTD;
case 0x24: return MBlaze::TPUTD;
case 0x26: return MBlaze::TAPUTD;
case 0x28: return MBlaze::CPUTD;
case 0x2A: return MBlaze::CAPUTD;
case 0x2C: return MBlaze::TCPUTD;
case 0x2E: return MBlaze::TCAPUTD;
case 0x30: return MBlaze::NPUTD;
case 0x32: return MBlaze::NAPUTD;
case 0x34: return MBlaze::TNPUTD;
case 0x36: return MBlaze::TNAPUTD;
case 0x38: return MBlaze::NCPUTD;
case 0x3A: return MBlaze::NCAPUTD;
case 0x3C: return MBlaze::TNCPUTD;
case 0x3E: return MBlaze::TNCAPUTD;
}
}
static unsigned decodeIDIV(uint32_t insn) {
switch (insn&0x3) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::IDIV;
case 0x2: return MBlaze::IDIVU;
}
}
static unsigned decodeLBU(uint32_t insn) {
switch ((insn>>9)&0x1) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::LBU;
case 0x1: return MBlaze::LBUR;
}
}
static unsigned decodeLHU(uint32_t insn) {
switch ((insn>>9)&0x1) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::LHU;
case 0x1: return MBlaze::LHUR;
}
}
static unsigned decodeLW(uint32_t insn) {
switch ((insn>>9)&0x3) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::LW;
case 0x1: return MBlaze::LWR;
case 0x2: return MBlaze::LWX;
}
}
static unsigned decodeSB(uint32_t insn) {
switch ((insn>>9)&0x1) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::SB;
case 0x1: return MBlaze::SBR;
}
}
static unsigned decodeSH(uint32_t insn) {
switch ((insn>>9)&0x1) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::SH;
case 0x1: return MBlaze::SHR;
}
}
static unsigned decodeSW(uint32_t insn) {
switch ((insn>>9)&0x3) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::SW;
case 0x1: return MBlaze::SWR;
case 0x2: return MBlaze::SWX;
}
}
static unsigned decodeMFS(uint32_t insn) {
switch ((insn>>15)&0x1) {
default: return UNSUPPORTED;
case 0x0:
switch ((insn>>16)&0x1) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::MSRSET;
case 0x1: return MBlaze::MSRCLR;
}
case 0x1:
switch ((insn>>14)&0x1) {
default: return UNSUPPORTED;
case 0x0: return MBlaze::MFS;
case 0x1: return MBlaze::MTS;
}
}
}
static unsigned decodeOR(uint32_t insn) {
switch (getFLAGS(insn)) {
default: return UNSUPPORTED;
case 0x000: return MBlaze::OR;
case 0x400: return MBlaze::PCMPBF;
}
}
static unsigned decodeXOR(uint32_t insn) {
switch (getFLAGS(insn)) {
default: return UNSUPPORTED;
case 0x000: return MBlaze::XOR;
case 0x400: return MBlaze::PCMPEQ;
}
}
static unsigned decodeANDN(uint32_t insn) {
switch (getFLAGS(insn)) {
default: return UNSUPPORTED;
case 0x000: return MBlaze::ANDN;
case 0x400: return MBlaze::PCMPNE;
}
}
static unsigned decodeRTSD(uint32_t insn) {
switch ((insn>>21)&0x1F) {
default: return UNSUPPORTED;
case 0x10: return MBlaze::RTSD;
case 0x11: return MBlaze::RTID;
case 0x12: return MBlaze::RTBD;
case 0x14: return MBlaze::RTED;
}
}
static unsigned getOPCODE(uint32_t insn) {
unsigned opcode = mblazeBinary2Opcode[ (insn>>26)&0x3F ];
switch (opcode) {
case MBlaze::MUL: return decodeMUL(insn);
case MBlaze::SEXT8: return decodeSEXT(insn);
case MBlaze::BEQ: return decodeBEQ(insn);
case MBlaze::BEQI: return decodeBEQI(insn);
case MBlaze::BR: return decodeBR(insn);
case MBlaze::BRI: return decodeBRI(insn);
case MBlaze::BSRL: return decodeBSRL(insn);
case MBlaze::BSRLI: return decodeBSRLI(insn);
case MBlaze::RSUBK: return decodeRSUBK(insn);
case MBlaze::FADD: return decodeFADD(insn);
case MBlaze::GET: return decodeGET(insn);
case MBlaze::GETD: return decodeGETD(insn);
case MBlaze::IDIV: return decodeIDIV(insn);
case MBlaze::LBU: return decodeLBU(insn);
case MBlaze::LHU: return decodeLHU(insn);
case MBlaze::LW: return decodeLW(insn);
case MBlaze::SB: return decodeSB(insn);
case MBlaze::SH: return decodeSH(insn);
case MBlaze::SW: return decodeSW(insn);
case MBlaze::MFS: return decodeMFS(insn);
case MBlaze::OR: return decodeOR(insn);
case MBlaze::XOR: return decodeXOR(insn);
case MBlaze::ANDN: return decodeANDN(insn);
case MBlaze::RTSD: return decodeRTSD(insn);
default: return opcode;
}
}
EDInstInfo *MBlazeDisassembler::getEDInfo() const {
return instInfoMBlaze;
}
//
// Public interface for the disassembler
//
bool MBlazeDisassembler::getInstruction(MCInst &instr,
uint64_t &size,
const MemoryObject &region,
uint64_t address,
raw_ostream &vStream) const {
// The machine instruction.
uint32_t insn;
uint8_t bytes[4];
// We always consume 4 bytes of data
size = 4;
// We want to read exactly 4 bytes of data.
if (region.readBytes(address, 4, (uint8_t*)bytes, NULL) == -1)
return false;
// Encoded as a big-endian 32-bit word in the stream.
insn = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<< 8) | (bytes[3]<<0);
// Get the MCInst opcode from the binary instruction and make sure
// that it is a valid instruction.
unsigned opcode = getOPCODE(insn);
if (opcode == UNSUPPORTED)
return false;
instr.setOpcode(opcode);
uint64_t tsFlags = MBlazeInsts[opcode].TSFlags;
switch ((tsFlags & MBlazeII::FormMask)) {
default: llvm_unreachable("unknown instruction encoding");
case MBlazeII::FRRRR:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateReg(getRB(insn)));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
break;
case MBlazeII::FRRR:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
instr.addOperand(MCOperand::CreateReg(getRB(insn)));
break;
case MBlazeII::FRI:
switch (opcode) {
default: llvm_unreachable("unknown instruction encoding");
case MBlaze::MFS:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
break;
case MBlaze::MTS:
instr.addOperand(MCOperand::CreateImm(insn&0x3FFF));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
break;
case MBlaze::MSRSET:
case MBlaze::MSRCLR:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateImm(insn&0x7FFF));
break;
}
break;
case MBlazeII::FRRI:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
switch (opcode) {
default:
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
break;
case MBlaze::BSRLI:
case MBlaze::BSRAI:
case MBlaze::BSLLI:
instr.addOperand(MCOperand::CreateImm(insn&0x1F));
break;
}
break;
case MBlazeII::FCRR:
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
instr.addOperand(MCOperand::CreateReg(getRB(insn)));
break;
case MBlazeII::FCRI:
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
break;
case MBlazeII::FRCR:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateReg(getRB(insn)));
break;
case MBlazeII::FRCI:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
break;
case MBlazeII::FCCR:
instr.addOperand(MCOperand::CreateReg(getRB(insn)));
break;
case MBlazeII::FCCI:
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
break;
case MBlazeII::FRRCI:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
instr.addOperand(MCOperand::CreateImm(getSHT(insn)));
break;
case MBlazeII::FRRC:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
break;
case MBlazeII::FRCX:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
break;
case MBlazeII::FRCS:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateImm(getRS(insn)));
break;
case MBlazeII::FCRCS:
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
instr.addOperand(MCOperand::CreateImm(getRS(insn)));
break;
case MBlazeII::FCRCX:
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
break;
case MBlazeII::FCX:
instr.addOperand(MCOperand::CreateImm(getFSL(insn)));
break;
case MBlazeII::FCR:
instr.addOperand(MCOperand::CreateReg(getRB(insn)));
break;
case MBlazeII::FRIR:
instr.addOperand(MCOperand::CreateReg(getRD(insn)));
instr.addOperand(MCOperand::CreateImm(getIMM(insn)));
instr.addOperand(MCOperand::CreateReg(getRA(insn)));
break;
}
return true;
}
static MCDisassembler *createMBlazeDisassembler(const Target &T) {
return new MBlazeDisassembler;
}
extern "C" void LLVMInitializeMBlazeDisassembler() {
// Register the disassembler.
TargetRegistry::RegisterMCDisassembler(TheMBlazeTarget,
createMBlazeDisassembler);
}