summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/Target/Mips/Disassembler/MipsDisassembler.cpp
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'lib/Target/Mips/Disassembler/MipsDisassembler.cpp')
-rw-r--r--lib/Target/Mips/Disassembler/MipsDisassembler.cpp152
1 files changed, 119 insertions, 33 deletions
diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index b0b994323036..ef0f08b49850 100644
--- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "Mips.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/MC/MCContext.h"
@@ -32,7 +33,7 @@ using namespace llvm;
#define DEBUG_TYPE "mips-disassembler"
-typedef MCDisassembler::DecodeStatus DecodeStatus;
+using DecodeStatus = MCDisassembler::DecodeStatus;
namespace {
@@ -286,10 +287,8 @@ static DecodeStatus DecodeLoadByte15(MCInst &Inst,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeCacheOp(MCInst &Inst,
- unsigned Insn,
- uint64_t Address,
- const void *Decoder);
+static DecodeStatus DecodeCacheOp(MCInst &Inst, unsigned Insn, uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst &Inst,
unsigned Insn,
@@ -367,17 +366,14 @@ static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const void *Decoder);
+static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address,
+ const void *Decoder);
-static DecodeStatus DecodeFMem3(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const void *Decoder);
+static DecodeStatus DecodeFMem3(MCInst &Inst, unsigned Insn, uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, unsigned Insn,
- uint64_t Address,
- const void *Decoder);
+ uint64_t Address, const void *Decoder);
static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn,
uint64_t Address,
@@ -523,6 +519,14 @@ static DecodeStatus
DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
+template <typename InsnType>
+static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
@@ -531,7 +535,7 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn,
+static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair,
uint64_t Address,
const void *Decoder);
@@ -581,7 +585,8 @@ static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
template <typename InsnType>
static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder) {
- typedef DecodeStatus (*DecodeFN)(MCInst &, unsigned, uint64_t, const void *);
+ using DecodeFN = DecodeStatus (*)(MCInst &, unsigned, uint64_t, const void *);
+
// The size of the n field depends on the element size
// The register class also depends on this.
InsnType tmp = fieldFromInstruction(insn, 17, 5);
@@ -1054,6 +1059,86 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
return MCDisassembler::Success;
}
+// Override the generated disassembler to produce DEXT all the time. This is
+// for feature / behaviour parity with binutils.
+template <typename InsnType>
+static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned Msbd = fieldFromInstruction(Insn, 11, 5);
+ unsigned Lsb = fieldFromInstruction(Insn, 6, 5);
+ unsigned Size = 0;
+ unsigned Pos = 0;
+
+ switch (MI.getOpcode()) {
+ case Mips::DEXT:
+ Pos = Lsb;
+ Size = Msbd + 1;
+ break;
+ case Mips::DEXTM:
+ Pos = Lsb;
+ Size = Msbd + 1 + 32;
+ break;
+ case Mips::DEXTU:
+ Pos = Lsb + 32;
+ Size = Msbd + 1;
+ break;
+ default:
+ llvm_unreachable("Unknown DEXT instruction!");
+ }
+
+ MI.setOpcode(Mips::DEXT);
+
+ InsnType Rs = fieldFromInstruction(Insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(Insn, 16, 5);
+
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs)));
+ MI.addOperand(MCOperand::createImm(Pos));
+ MI.addOperand(MCOperand::createImm(Size));
+
+ return MCDisassembler::Success;
+}
+
+// Override the generated disassembler to produce DINS all the time. This is
+// for feature / behaviour parity with binutils.
+template <typename InsnType>
+static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned Msbd = fieldFromInstruction(Insn, 11, 5);
+ unsigned Lsb = fieldFromInstruction(Insn, 6, 5);
+ unsigned Size = 0;
+ unsigned Pos = 0;
+
+ switch (MI.getOpcode()) {
+ case Mips::DINS:
+ Pos = Lsb;
+ Size = Msbd + 1 - Pos;
+ break;
+ case Mips::DINSM:
+ Pos = Lsb;
+ Size = Msbd + 33 - Pos;
+ break;
+ case Mips::DINSU:
+ Pos = Lsb + 32;
+ // mbsd = pos + size - 33
+ // mbsd - pos + 33 = size
+ Size = Msbd + 33 - Pos;
+ break;
+ default:
+ llvm_unreachable("Unknown DINS instruction!");
+ }
+
+ InsnType Rs = fieldFromInstruction(Insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(Insn, 16, 5);
+
+ MI.setOpcode(Mips::DINS);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rt)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR64RegClassID, Rs)));
+ MI.addOperand(MCOperand::createImm(Pos));
+ MI.addOperand(MCOperand::createImm(Size));
+
+ return MCDisassembler::Success;
+}
/// Read two bytes from the ArrayRef and return 16 bit halfword sorted
/// according to the given endianness.
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
@@ -1127,7 +1212,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n");
// Calling the auto-generated decoder function for microMIPS32R6
- // (and microMIPS64R6) 16-bit instructions.
+ // 16-bit instructions.
Result = decodeInstruction(DecoderTableMicroMipsR616, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
@@ -1170,9 +1255,9 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
return Result;
}
- if (hasMips32r6() && isFP64()) {
- DEBUG(dbgs() << "Trying MicroMips32r6FP64 table (32-bit opcodes):\n");
- Result = decodeInstruction(DecoderTableMicroMips32r6FP6432, Instr, Insn,
+ if (isFP64()) {
+ DEBUG(dbgs() << "Trying MicroMipsFP64 table (32-bit opcodes):\n");
+ Result = decodeInstruction(DecoderTableMicroMipsFP6432, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
@@ -1255,6 +1340,14 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
return Result;
}
+ if (isFP64()) {
+ DEBUG(dbgs() << "Trying MipsFP64 (64 bit FPU) table (32-bit opcodes):\n");
+ Result = decodeInstruction(DecoderTableMipsFP6432, Instr, Insn,
+ Address, this, STI);
+ if (Result != MCDisassembler::Fail)
+ return Result;
+ }
+
DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n");
// Calling the auto-generated decoder function.
Result =
@@ -2165,7 +2258,7 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- int32_t BranchOffset = SignExtend32<7>(Offset) << 1;
+ int32_t BranchOffset = SignExtend32<8>(Offset << 1);
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
}
@@ -2174,7 +2267,7 @@ static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- int32_t BranchOffset = SignExtend32<10>(Offset) << 1;
+ int32_t BranchOffset = SignExtend32<11>(Offset << 1);
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
}
@@ -2192,7 +2285,7 @@ static DecodeStatus DecodeBranchTarget26MM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- int32_t BranchOffset = SignExtend32<26>(Offset) << 1;
+ int32_t BranchOffset = SignExtend32<27>(Offset << 1);
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
@@ -2263,15 +2356,10 @@ static DecodeStatus DecodeInsSize(MCInst &Inst,
uint64_t Address,
const void *Decoder) {
// First we need to grab the pos(lsb) from MCInst.
+ // This function only handles the 32 bit variants of ins, as dins
+ // variants are handled differently.
int Pos = Inst.getOperand(2).getImm();
- if (Inst.getOpcode() == Mips::DINSU)
- Pos += 32;
- int Size;
- if (Inst.getOpcode() == Mips::DINSM ||
- Inst.getOpcode() == Mips::DINSU)
- Size = (int) Insn - Pos + 33;
- else
- Size = (int) Insn - Pos + 1;
+ int Size = (int) Insn - Pos + 1;
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size)));
return MCDisassembler::Success;
}
@@ -2365,10 +2453,8 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn,
+static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair,
uint64_t Address, const void *Decoder) {
- unsigned RegPair = fieldFromInstruction(Insn, 7, 3);
-
switch (RegPair) {
default:
return MCDisassembler::Fail;