summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp')
-rw-r--r--contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp537
1 files changed, 440 insertions, 97 deletions
diff --git a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index 53fb7a1..da33f3b 100644
--- a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -20,7 +20,6 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
@@ -31,32 +30,29 @@ typedef MCDisassembler::DecodeStatus DecodeStatus;
namespace {
-/// MipsDisassemblerBase - a disasembler class for Mips.
+/// A disasembler class for Mips.
class MipsDisassemblerBase : public MCDisassembler {
public:
- /// Constructor - Initializes the disassembler.
- ///
MipsDisassemblerBase(const MCSubtargetInfo &STI, MCContext &Ctx,
- bool bigEndian) :
- MCDisassembler(STI, Ctx),
- IsN64(STI.getFeatureBits() & Mips::FeatureN64), isBigEndian(bigEndian) {}
+ bool IsBigEndian)
+ : MCDisassembler(STI, Ctx),
+ IsGP64Bit(STI.getFeatureBits() & Mips::FeatureGP64Bit),
+ IsBigEndian(IsBigEndian) {}
virtual ~MipsDisassemblerBase() {}
- bool isN64() const { return IsN64; }
+ bool isGP64Bit() const { return IsGP64Bit; }
private:
- bool IsN64;
+ bool IsGP64Bit;
protected:
- bool isBigEndian;
+ bool IsBigEndian;
};
-/// MipsDisassembler - a disasembler class for Mips32.
+/// A disasembler class for Mips32.
class MipsDisassembler : public MipsDisassemblerBase {
bool IsMicroMips;
public:
- /// Constructor - Initializes the disassembler.
- ///
MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool bigEndian)
: MipsDisassemblerBase(STI, Ctx, bigEndian) {
IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips;
@@ -75,32 +71,23 @@ public:
return !hasMips32() && !hasMips3();
}
- /// getInstruction - See MCDisassembler.
- DecodeStatus getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream,
- raw_ostream &cStream) const override;
+ DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const override;
};
-
-/// Mips64Disassembler - a disasembler class for Mips64.
+/// A disasembler class for Mips64.
class Mips64Disassembler : public MipsDisassemblerBase {
public:
- /// Constructor - Initializes the disassembler.
- ///
Mips64Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
bool bigEndian) :
MipsDisassemblerBase(STI, Ctx, bigEndian) {}
- /// getInstruction - See MCDisassembler.
- DecodeStatus getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream,
- raw_ostream &cStream) const override;
+ DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const override;
};
} // end anonymous namespace
@@ -117,6 +104,16 @@ static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
@@ -231,6 +228,13 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+// DecodeBranchTarget7MM - Decode microMIPS branch offset, which is
+// shifted left by 1 bit.
+static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder);
+
// DecodeBranchTargetMM - Decode microMIPS branch offset, which is
// shifted left by 1 bit.
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
@@ -255,9 +259,29 @@ static DecodeStatus DecodeCacheOp(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeCacheOpMM(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeSyncI(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeMemMMImm4(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -285,6 +309,26 @@ static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeLiSimm7(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeSimm4(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeSimm16(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -313,6 +357,15 @@ static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn,
static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
+static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't
/// handle.
template <typename InsnType>
@@ -349,6 +402,14 @@ static DecodeStatus
DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
namespace llvm {
extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
TheMips64elTarget;
@@ -704,43 +765,55 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
return MCDisassembler::Success;
}
- /// readInstruction - read four bytes from the MemoryObject
- /// and return 32 bit word sorted according to the given endianess
-static DecodeStatus readInstruction32(const MemoryObject &region,
- uint64_t address,
- uint64_t &size,
- uint32_t &insn,
- bool isBigEndian,
- bool IsMicroMips) {
- uint8_t Bytes[4];
+/// Read two bytes from the ArrayRef and return 16 bit halfword sorted
+/// according to the given endianess.
+static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn,
+ bool IsBigEndian) {
+ // We want to read exactly 2 Bytes of data.
+ if (Bytes.size() < 2) {
+ Size = 0;
+ return MCDisassembler::Fail;
+ }
+ if (IsBigEndian) {
+ Insn = (Bytes[0] << 8) | Bytes[1];
+ } else {
+ Insn = (Bytes[1] << 8) | Bytes[0];
+ }
+
+ return MCDisassembler::Success;
+}
+
+/// Read four bytes from the ArrayRef and return 32 bit word sorted
+/// according to the given endianess
+static DecodeStatus readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn,
+ bool IsBigEndian, bool IsMicroMips) {
// We want to read exactly 4 Bytes of data.
- if (region.readBytes(address, 4, Bytes) == -1) {
- size = 0;
+ if (Bytes.size() < 4) {
+ Size = 0;
return MCDisassembler::Fail;
}
- if (isBigEndian) {
+ // High 16 bits of a 32-bit microMIPS instruction (where the opcode is)
+ // always precede the low 16 bits in the instruction stream (that is, they
+ // are placed at lower addresses in the instruction stream).
+ //
+ // microMIPS byte ordering:
+ // Big-endian: 0 | 1 | 2 | 3
+ // Little-endian: 1 | 0 | 3 | 2
+
+ if (IsBigEndian) {
// Encoded as a big-endian 32-bit word in the stream.
- insn = (Bytes[3] << 0) |
- (Bytes[2] << 8) |
- (Bytes[1] << 16) |
- (Bytes[0] << 24);
- }
- else {
- // Encoded as a small-endian 32-bit word in the stream.
- // Little-endian byte ordering:
- // mips32r2: 4 | 3 | 2 | 1
- // microMIPS: 2 | 1 | 4 | 3
+ Insn =
+ (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24);
+ } else {
if (IsMicroMips) {
- insn = (Bytes[2] << 0) |
- (Bytes[3] << 8) |
- (Bytes[0] << 16) |
+ Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) |
(Bytes[1] << 24);
} else {
- insn = (Bytes[0] << 0) |
- (Bytes[1] << 8) |
- (Bytes[2] << 16) |
+ Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) |
(Bytes[3] << 24);
}
}
@@ -748,24 +821,33 @@ static DecodeStatus readInstruction32(const MemoryObject &region,
return MCDisassembler::Success;
}
-DecodeStatus
-MipsDisassembler::getInstruction(MCInst &instr,
- uint64_t &Size,
- const MemoryObject &Region,
- uint64_t Address,
- raw_ostream &vStream,
- raw_ostream &cStream) const {
+DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const {
uint32_t Insn;
-
- DecodeStatus Result = readInstruction32(Region, Address, Size,
- Insn, isBigEndian, IsMicroMips);
- if (Result == MCDisassembler::Fail)
- return MCDisassembler::Fail;
+ DecodeStatus Result;
if (IsMicroMips) {
- DEBUG(dbgs() << "Trying MicroMips32 table (32-bit opcodes):\n");
+ Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian);
+
+ DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n");
+ // Calling the auto-generated decoder function.
+ Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address,
+ this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 2;
+ return Result;
+ }
+
+ Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, true);
+ if (Result == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+
+ DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n");
// Calling the auto-generated decoder function.
- Result = decodeInstruction(DecoderTableMicroMips32, instr, Insn, Address,
+ Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address,
this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
@@ -774,10 +856,14 @@ MipsDisassembler::getInstruction(MCInst &instr,
return MCDisassembler::Fail;
}
+ Result = readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false);
+ if (Result == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+
if (hasCOP3()) {
DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n");
Result =
- decodeInstruction(DecoderTableCOP3_32, instr, Insn, Address, this, STI);
+ decodeInstruction(DecoderTableCOP3_32, Instr, Insn, Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
@@ -786,7 +872,7 @@ MipsDisassembler::getInstruction(MCInst &instr,
if (hasMips32r6() && isGP64()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n");
- Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, instr, Insn,
+ Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
@@ -796,7 +882,7 @@ MipsDisassembler::getInstruction(MCInst &instr,
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n");
- Result = decodeInstruction(DecoderTableMips32r6_64r632, instr, Insn,
+ Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
@@ -806,8 +892,8 @@ MipsDisassembler::getInstruction(MCInst &instr,
DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n");
// Calling the auto-generated decoder function.
- Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
- this, STI);
+ Result =
+ decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
@@ -816,30 +902,28 @@ MipsDisassembler::getInstruction(MCInst &instr,
return MCDisassembler::Fail;
}
-DecodeStatus
-Mips64Disassembler::getInstruction(MCInst &instr,
- uint64_t &Size,
- const MemoryObject &Region,
- uint64_t Address,
- raw_ostream &vStream,
- raw_ostream &cStream) const {
+DecodeStatus Mips64Disassembler::getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const {
uint32_t Insn;
- DecodeStatus Result = readInstruction32(Region, Address, Size,
- Insn, isBigEndian, false);
+ DecodeStatus Result =
+ readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false);
if (Result == MCDisassembler::Fail)
return MCDisassembler::Fail;
// Calling the auto-generated decoder function.
- Result = decodeInstruction(DecoderTableMips6432, instr, Insn, Address,
- this, STI);
+ Result =
+ decodeInstruction(DecoderTableMips6432, Instr, Insn, Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
// If we fail to decode in Mips64 decoder space we can try in Mips32
- Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
- this, STI);
+ Result =
+ decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
@@ -870,6 +954,28 @@ static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 7)
+ return MCDisassembler::Fail;
+ unsigned Reg = getReg(Decoder, Mips::GPRMM16RegClassID, RegNo);
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 7)
+ return MCDisassembler::Fail;
+ unsigned Reg = getReg(Decoder, Mips::GPRMM16ZeroRegClassID, RegNo);
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
@@ -885,7 +991,7 @@ static DecodeStatus DecodePtrRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
- if (static_cast<const MipsDisassembler *>(Decoder)->isN64())
+ if (static_cast<const MipsDisassembler *>(Decoder)->isGP64Bit())
return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder);
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
@@ -966,7 +1072,8 @@ static DecodeStatus DecodeMem(MCInst &Inst,
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
- if(Inst.getOpcode() == Mips::SC){
+ if(Inst.getOpcode() == Mips::SC ||
+ Inst.getOpcode() == Mips::SCD){
Inst.addOperand(MCOperand::CreateReg(Reg));
}
@@ -994,6 +1101,38 @@ static DecodeStatus DecodeCacheOp(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeCacheOpMM(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ int Offset = SignExtend32<12>(Insn & 0xfff);
+ unsigned Base = fieldFromInstruction(Insn, 16, 5);
+ unsigned Hint = fieldFromInstruction(Insn, 21, 5);
+
+ Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
+
+ Inst.addOperand(MCOperand::CreateReg(Base));
+ Inst.addOperand(MCOperand::CreateImm(Offset));
+ Inst.addOperand(MCOperand::CreateImm(Hint));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeSyncI(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ int Offset = SignExtend32<16>(Insn & 0xffff);
+ unsigned Base = fieldFromInstruction(Insn, 21, 5);
+
+ Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
+
+ Inst.addOperand(MCOperand::CreateReg(Base));
+ Inst.addOperand(MCOperand::CreateImm(Offset));
+
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
int Offset = SignExtend32<10>(fieldFromInstruction(Insn, 16, 10));
@@ -1040,6 +1179,74 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeMemMMImm4(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ unsigned Offset = Insn & 0xf;
+ unsigned Reg = fieldFromInstruction(Insn, 7, 3);
+ unsigned Base = fieldFromInstruction(Insn, 4, 3);
+
+ switch (Inst.getOpcode()) {
+ case Mips::LBU16_MM:
+ case Mips::LHU16_MM:
+ case Mips::LW16_MM:
+ if (DecodeGPRMM16RegisterClass(Inst, Reg, Address, Decoder)
+ == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ break;
+ case Mips::SB16_MM:
+ case Mips::SH16_MM:
+ case Mips::SW16_MM:
+ if (DecodeGPRMM16ZeroRegisterClass(Inst, Reg, Address, Decoder)
+ == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ break;
+ }
+
+ if (DecodeGPRMM16RegisterClass(Inst, Base, Address, Decoder)
+ == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+
+ switch (Inst.getOpcode()) {
+ case Mips::LBU16_MM:
+ if (Offset == 0xf)
+ Inst.addOperand(MCOperand::CreateImm(-1));
+ else
+ Inst.addOperand(MCOperand::CreateImm(Offset));
+ break;
+ case Mips::SB16_MM:
+ Inst.addOperand(MCOperand::CreateImm(Offset));
+ break;
+ case Mips::LHU16_MM:
+ case Mips::SH16_MM:
+ Inst.addOperand(MCOperand::CreateImm(Offset << 1));
+ break;
+ case Mips::LW16_MM:
+ case Mips::SW16_MM:
+ Inst.addOperand(MCOperand::CreateImm(Offset << 2));
+ break;
+ }
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ unsigned Offset = Insn & 0x1F;
+ unsigned Reg = fieldFromInstruction(Insn, 5, 5);
+
+ Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
+
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ Inst.addOperand(MCOperand::CreateReg(Mips::SP));
+ Inst.addOperand(MCOperand::CreateImm(Offset << 2));
+
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -1051,12 +1258,26 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
- if (Inst.getOpcode() == Mips::SC_MM)
+ switch (Inst.getOpcode()) {
+ case Mips::SWM32_MM:
+ case Mips::LWM32_MM:
+ if (DecodeRegListOperand(Inst, Insn, Address, Decoder)
+ == MCDisassembler::Fail)
+ return MCDisassembler::Fail;
+ Inst.addOperand(MCOperand::CreateReg(Base));
+ Inst.addOperand(MCOperand::CreateImm(Offset));
+ break;
+ case Mips::SC_MM:
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ // fallthrough
+ default:
Inst.addOperand(MCOperand::CreateReg(Reg));
+ if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM)
+ Inst.addOperand(MCOperand::CreateReg(Reg+1));
- Inst.addOperand(MCOperand::CreateReg(Reg));
- Inst.addOperand(MCOperand::CreateReg(Base));
- Inst.addOperand(MCOperand::CreateImm(Offset));
+ Inst.addOperand(MCOperand::CreateReg(Base));
+ Inst.addOperand(MCOperand::CreateImm(Offset));
+ }
return MCDisassembler::Success;
}
@@ -1326,6 +1547,15 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t BranchOffset = SignExtend32<7>(Offset) << 1;
+ Inst.addOperand(MCOperand::CreateImm(BranchOffset));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
@@ -1344,6 +1574,46 @@ static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ if (Value == 0)
+ Inst.addOperand(MCOperand::CreateImm(1));
+ else if (Value == 0x7)
+ Inst.addOperand(MCOperand::CreateImm(-1));
+ else
+ Inst.addOperand(MCOperand::CreateImm(Value << 2));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(Value << 2));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeLiSimm7(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ if (Value == 0x7F)
+ Inst.addOperand(MCOperand::CreateImm(-1));
+ else
+ Inst.addOperand(MCOperand::CreateImm(Value));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeSimm4(MCInst &Inst,
+ unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<4>(Value)));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeSimm16(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -1392,3 +1662,76 @@ static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn,
Inst.addOperand(MCOperand::CreateImm(SignExtend32<18>(Insn) * 8));
return MCDisassembler::Success;
}
+
+static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ int32_t DecodedValue;
+ switch (Insn) {
+ case 0: DecodedValue = 256; break;
+ case 1: DecodedValue = 257; break;
+ case 510: DecodedValue = -258; break;
+ case 511: DecodedValue = -257; break;
+ default: DecodedValue = SignExtend32<9>(Insn); break;
+ }
+ Inst.addOperand(MCOperand::CreateImm(DecodedValue * 4));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ // Insn must be >= 0, since it is unsigned that condition is always true.
+ assert(Insn < 16);
+ int32_t DecodedValues[] = {128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64,
+ 255, 32768, 65535};
+ Inst.addOperand(MCOperand::CreateImm(DecodedValues[Insn]));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(Insn << 2));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeRegListOperand(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5,
+ Mips::S6, Mips::FP};
+ unsigned RegNum;
+
+ unsigned RegLst = fieldFromInstruction(Insn, 21, 5);
+ // Empty register lists are not allowed.
+ if (RegLst == 0)
+ return MCDisassembler::Fail;
+
+ RegNum = RegLst & 0xf;
+ for (unsigned i = 0; i < RegNum; i++)
+ Inst.addOperand(MCOperand::CreateReg(Regs[i]));
+
+ if (RegLst & 0x10)
+ Inst.addOperand(MCOperand::CreateReg(Mips::RA));
+
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3};
+ unsigned RegNum;
+
+ unsigned RegLst = fieldFromInstruction(Insn, 4, 2);
+ // Empty register lists are not allowed.
+ if (RegLst == 0)
+ return MCDisassembler::Fail;
+
+ RegNum = RegLst & 0x3;
+ for (unsigned i = 0; i < RegNum - 1; i++)
+ Inst.addOperand(MCOperand::CreateReg(Regs[i]));
+
+ Inst.addOperand(MCOperand::CreateReg(Mips::RA));
+
+ return MCDisassembler::Success;
+}
OpenPOWER on IntegriCloud