aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@imgtec.com>2017-09-14 15:17:50 +0000
committerSimon Dardis <simon.dardis@imgtec.com>2017-09-14 15:17:50 +0000
commit6f83ae38a33b06b985597fcbb116c724ec7ca332 (patch)
tree6c5064306d5c84f3e868e72c020f8cf8d2d06c8d /llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
parent18633071a3c4538202d0727c3efbcd8e2521e6ba (diff)
downloadllvm-6f83ae38a33b06b985597fcbb116c724ec7ca332.zip
llvm-6f83ae38a33b06b985597fcbb116c724ec7ca332.tar.gz
llvm-6f83ae38a33b06b985597fcbb116c724ec7ca332.tar.bz2
[mips] Implement the 'dins' aliases.
Traditionally GAS has provided automatic selection between dins, dinsm and dinsu. Binutils also disassembles all instructions in that family as 'dins' rather than the actual instruction. Reviewers: slthakur Differential Revision: https://reviews.llvm.org/D34877 llvm-svn: 313267
Diffstat (limited to 'llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp')
-rw-r--r--llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp69
1 files changed, 61 insertions, 8 deletions
diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index 41b9657..8bd2e79 100644
--- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -519,6 +519,10 @@ 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);
+
static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
@@ -1051,6 +1055,60 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
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;
+ bool IsMicroMips = false;
+
+ switch (MI.getOpcode()) {
+ case Mips::DINS_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DINS:
+ Pos = Lsb;
+ Size = Msbd + 1 - Pos;
+ break;
+ case Mips::DINSM_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ case Mips::DINSM:
+ Pos = Lsb;
+ Size = Msbd + 33 - Pos;
+ break;
+ case Mips::DINSU_MM64R6:
+ IsMicroMips = true;
+ LLVM_FALLTHROUGH;
+ 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!");
+ }
+
+ // Although the format of the instruction is similar, rs and rt are swapped
+ // for microMIPS64R6.
+ InsnType Rs = fieldFromInstruction(Insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(Insn, 16, 5);
+ if (IsMicroMips)
+ std::swap(Rs, Rt);
+
+ MI.setOpcode(IsMicroMips ? Mips::DINS_MM64R6 : 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,
@@ -2260,15 +2318,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;
}