diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/Target/Mips/Disassembler/MipsDisassembler.cpp | |
parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) |
Notes
Diffstat (limited to 'lib/Target/Mips/Disassembler/MipsDisassembler.cpp')
-rw-r--r-- | lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 152 |
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; |