llvm-project/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp

1918 lines
70 KiB
C++
Raw Normal View History

//===- MipsDisassembler.cpp - Disassembler for Mips -------------*- 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 Mips Disassembler.
//
//===----------------------------------------------------------------------===//
#include "Mips.h"
#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
[Modules] Make Support/Debug.h modular. This requires it to not change behavior based on other files defining DEBUG_TYPE, which means it cannot define DEBUG_TYPE at all. This is actually better IMO as it forces folks to define relevant DEBUG_TYPEs for their files. However, it requires all files that currently use DEBUG(...) to define a DEBUG_TYPE if they don't already. I've updated all such files in LLVM and will do the same for other upstream projects. This still leaves one important change in how LLVM uses the DEBUG_TYPE macro going forward: we need to only define the macro *after* header files have been #include-ed. Previously, this wasn't possible because Debug.h required the macro to be pre-defined. This commit removes that. By defining DEBUG_TYPE after the includes two things are fixed: - Header files that need to provide a DEBUG_TYPE for some inline code can do so by defining the macro before their inline code and undef-ing it afterward so the macro does not escape. - We no longer have rampant ODR violations due to including headers with different DEBUG_TYPE definitions. This may be mostly an academic violation today, but with modules these types of violations are easy to check for and potentially very relevant. Where necessary to suppor headers with DEBUG_TYPE, I have moved the definitions below the includes in this commit. I plan to move the rest of the DEBUG_TYPE macros in LLVM in subsequent commits; this one is big enough. The comments in Debug.h, which were hilariously out of date already, have been updated to reflect the recommended practice going forward. llvm-svn: 206822
2014-04-22 06:55:11 +08:00
#define DEBUG_TYPE "mips-disassembler"
typedef MCDisassembler::DecodeStatus DecodeStatus;
namespace {
class MipsDisassembler : public MCDisassembler {
bool IsMicroMips;
bool IsBigEndian;
public:
MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian)
: MCDisassembler(STI, Ctx),
IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]),
IsBigEndian(IsBigEndian) {}
bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; }
bool hasMips32r6() const {
return STI.getFeatureBits()[Mips::FeatureMips32r6];
}
bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; }
bool hasCOP3() const {
// Only present in MIPS-I and MIPS-II
return !hasMips32() && !hasMips3();
}
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
// Forward declare these because the autogenerated code will reference them.
// Definitions are further down.
static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
unsigned RegNo,
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 DecodeGPRMM16MovePRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePtrRegisterClass(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeDSPRRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFCCRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFGRCCRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeACC64DSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeHI32DSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeLO32DSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMSA128BRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMSA128HRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMSA128WRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMSA128DRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCOP0RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBranchTarget(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeJumpTarget(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBranchTarget21(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
unsigned Offset,
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);
// DecodeBranchTarget10MM - Decode microMIPS branch offset, which is
// shifted left by 1 bit.
static DecodeStatus DecodeBranchTarget10MM(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,
unsigned Offset,
uint64_t Address,
const void *Decoder);
// DecodeJumpTargetMM - Decode microMIPS jump target, which is
// shifted left by 1 bit.
static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMem(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 DecodeCacheOpR6(MCInst &Inst,
unsigned Insn,
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 DecodeMemMMGPImm7Lsl2(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMImm9(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMImm16(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFMem(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 DecodeFMemCop2R6(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
unsigned Insn,
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,
const void *Decoder);
// Decode the immediate field of an LSA instruction which
// is off by one.
static DecodeStatus DecodeLSAImm(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeInsSize(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeExtSize(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
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);
static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
[mips] Rewrite MipsAsmParser and MipsOperand. Summary: Highlights: - Registers are resolved much later (by the render method). Prior to that point, GPR32's/GPR64's are GPR's regardless of register size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register size or FR mode. Numeric registers can be anything. - All registers are parsed the same way everywhere (even when handling symbol aliasing) - One consequence is that all registers can be specified numerically almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing but that can be easily resolved. - Removes the need for the hasConsumedDollar hack - Parenthesis and Bracket suffixes are handled generically - Micromips instructions are parsed directly instead of going through the standard encodings first. - rdhwr accepts all 32 registers, and the following instructions that previously xfailed now work: ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d, c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1 - Diagnostics involving registers point at the correct character (the $) - There's only one kind of immediate in MipsOperand. LSA immediates are handled by the predicate and renderer. Lowlights: - Hardcoded '$zero' in the div patterns is handled with a hack. MipsOperand::isReg() will return true for a k_RegisterIndex token with Index == 0 and getReg() will return ZERO for this case. Note that it doesn't return ZERO_64 on isGP64() targets. - I haven't cleaned up all of the now-unused functions. Some more of the generic parser could be removed too (integers and relocs for example). - insve.df needed a custom decoder to handle the implicit fourth operand that was needed to make it parse correctly. The difficulty was that the matcher expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this. Reviewers: matheusalmeida, vmedic Reviewed By: matheusalmeida Differential Revision: http://llvm-reviews.chandlerc.com/D3222 llvm-svn: 205292
2014-04-01 18:35:28 +08:00
/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't
/// handle.
template <typename InsnType>
static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
static DecodeStatus
DecodeAddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
static DecodeStatus
DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
static DecodeStatus
DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
static DecodeStatus
DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
static DecodeStatus
DecodeBgtzGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
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);
static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
namespace llvm {
extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
TheMips64elTarget;
}
static MCDisassembler *createMipsDisassembler(
const Target &T,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
return new MipsDisassembler(STI, Ctx, true);
}
static MCDisassembler *createMipselDisassembler(
const Target &T,
const MCSubtargetInfo &STI,
MCContext &Ctx) {
return new MipsDisassembler(STI, Ctx, false);
}
extern "C" void LLVMInitializeMipsDisassembler() {
// Register the disassembler.
TargetRegistry::RegisterMCDisassembler(TheMipsTarget,
createMipsDisassembler);
TargetRegistry::RegisterMCDisassembler(TheMipselTarget,
createMipselDisassembler);
TargetRegistry::RegisterMCDisassembler(TheMips64Target,
createMipsDisassembler);
TargetRegistry::RegisterMCDisassembler(TheMips64elTarget,
createMipselDisassembler);
}
#include "MipsGenDisassemblerTables.inc"
[mips] Rewrite MipsAsmParser and MipsOperand. Summary: Highlights: - Registers are resolved much later (by the render method). Prior to that point, GPR32's/GPR64's are GPR's regardless of register size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register size or FR mode. Numeric registers can be anything. - All registers are parsed the same way everywhere (even when handling symbol aliasing) - One consequence is that all registers can be specified numerically almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing but that can be easily resolved. - Removes the need for the hasConsumedDollar hack - Parenthesis and Bracket suffixes are handled generically - Micromips instructions are parsed directly instead of going through the standard encodings first. - rdhwr accepts all 32 registers, and the following instructions that previously xfailed now work: ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d, c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1 - Diagnostics involving registers point at the correct character (the $) - There's only one kind of immediate in MipsOperand. LSA immediates are handled by the predicate and renderer. Lowlights: - Hardcoded '$zero' in the div patterns is handled with a hack. MipsOperand::isReg() will return true for a k_RegisterIndex token with Index == 0 and getReg() will return ZERO for this case. Note that it doesn't return ZERO_64 on isGP64() targets. - I haven't cleaned up all of the now-unused functions. Some more of the generic parser could be removed too (integers and relocs for example). - insve.df needed a custom decoder to handle the implicit fourth operand that was needed to make it parse correctly. The difficulty was that the matcher expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this. Reviewers: matheusalmeida, vmedic Reviewed By: matheusalmeida Differential Revision: http://llvm-reviews.chandlerc.com/D3222 llvm-svn: 205229
2014-04-01 01:43:46 +08:00
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
const MipsDisassembler *Dis = static_cast<const MipsDisassembler*>(D);
const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo();
return *(RegInfo->getRegClass(RC).begin() + RegNo);
}
[mips] Rewrite MipsAsmParser and MipsOperand. Summary: Highlights: - Registers are resolved much later (by the render method). Prior to that point, GPR32's/GPR64's are GPR's regardless of register size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register size or FR mode. Numeric registers can be anything. - All registers are parsed the same way everywhere (even when handling symbol aliasing) - One consequence is that all registers can be specified numerically almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing but that can be easily resolved. - Removes the need for the hasConsumedDollar hack - Parenthesis and Bracket suffixes are handled generically - Micromips instructions are parsed directly instead of going through the standard encodings first. - rdhwr accepts all 32 registers, and the following instructions that previously xfailed now work: ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d, c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1 - Diagnostics involving registers point at the correct character (the $) - There's only one kind of immediate in MipsOperand. LSA immediates are handled by the predicate and renderer. Lowlights: - Hardcoded '$zero' in the div patterns is handled with a hack. MipsOperand::isReg() will return true for a k_RegisterIndex token with Index == 0 and getReg() will return ZERO for this case. Note that it doesn't return ZERO_64 on isGP64() targets. - I haven't cleaned up all of the now-unused functions. Some more of the generic parser could be removed too (integers and relocs for example). - insve.df needed a custom decoder to handle the implicit fourth operand that was needed to make it parse correctly. The difficulty was that the matcher expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this. Reviewers: matheusalmeida, vmedic Reviewed By: matheusalmeida Differential Revision: http://llvm-reviews.chandlerc.com/D3222 llvm-svn: 205292
2014-04-01 18:35:28 +08:00
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 *);
// The size of the n field depends on the element size
// The register class also depends on this.
InsnType tmp = fieldFromInstruction(insn, 17, 5);
unsigned NSize = 0;
DecodeFN RegDecoder = nullptr;
if ((tmp & 0x18) == 0x00) { // INSVE_B
NSize = 4;
RegDecoder = DecodeMSA128BRegisterClass;
} else if ((tmp & 0x1c) == 0x10) { // INSVE_H
NSize = 3;
RegDecoder = DecodeMSA128HRegisterClass;
} else if ((tmp & 0x1e) == 0x18) { // INSVE_W
NSize = 2;
RegDecoder = DecodeMSA128WRegisterClass;
} else if ((tmp & 0x1f) == 0x1c) { // INSVE_D
NSize = 1;
RegDecoder = DecodeMSA128DRegisterClass;
} else
llvm_unreachable("Invalid encoding");
assert(NSize != 0 && RegDecoder != nullptr);
// $wd
tmp = fieldFromInstruction(insn, 6, 5);
if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail)
return MCDisassembler::Fail;
// $wd_in
if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail)
return MCDisassembler::Fail;
// $n
tmp = fieldFromInstruction(insn, 16, NSize);
MI.addOperand(MCOperand::createImm(tmp));
[mips] Rewrite MipsAsmParser and MipsOperand. Summary: Highlights: - Registers are resolved much later (by the render method). Prior to that point, GPR32's/GPR64's are GPR's regardless of register size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register size or FR mode. Numeric registers can be anything. - All registers are parsed the same way everywhere (even when handling symbol aliasing) - One consequence is that all registers can be specified numerically almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing but that can be easily resolved. - Removes the need for the hasConsumedDollar hack - Parenthesis and Bracket suffixes are handled generically - Micromips instructions are parsed directly instead of going through the standard encodings first. - rdhwr accepts all 32 registers, and the following instructions that previously xfailed now work: ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d, c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1 - Diagnostics involving registers point at the correct character (the $) - There's only one kind of immediate in MipsOperand. LSA immediates are handled by the predicate and renderer. Lowlights: - Hardcoded '$zero' in the div patterns is handled with a hack. MipsOperand::isReg() will return true for a k_RegisterIndex token with Index == 0 and getReg() will return ZERO for this case. Note that it doesn't return ZERO_64 on isGP64() targets. - I haven't cleaned up all of the now-unused functions. Some more of the generic parser could be removed too (integers and relocs for example). - insve.df needed a custom decoder to handle the implicit fourth operand that was needed to make it parse correctly. The difficulty was that the matcher expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this. Reviewers: matheusalmeida, vmedic Reviewed By: matheusalmeida Differential Revision: http://llvm-reviews.chandlerc.com/D3222 llvm-svn: 205292
2014-04-01 18:35:28 +08:00
// $ws
tmp = fieldFromInstruction(insn, 11, 5);
if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail)
return MCDisassembler::Fail;
// $n2
MI.addOperand(MCOperand::createImm(0));
[mips] Rewrite MipsAsmParser and MipsOperand. Summary: Highlights: - Registers are resolved much later (by the render method). Prior to that point, GPR32's/GPR64's are GPR's regardless of register size. Similarly FGR32's/FGR64's/AFGR64's are FGR's regardless of register size or FR mode. Numeric registers can be anything. - All registers are parsed the same way everywhere (even when handling symbol aliasing) - One consequence is that all registers can be specified numerically almost anywhere (e.g. $fccX, $wX). The exception is symbol aliasing but that can be easily resolved. - Removes the need for the hasConsumedDollar hack - Parenthesis and Bracket suffixes are handled generically - Micromips instructions are parsed directly instead of going through the standard encodings first. - rdhwr accepts all 32 registers, and the following instructions that previously xfailed now work: ddiv, ddivu, div, divu, cvt.l.[ds], se[bh], wsbh, floor.w.[ds], c.ngl.d, c.sf.s, dsbh, dshd, madd.s, msub.s, nmadd.s, nmsub.s, swxc1 - Diagnostics involving registers point at the correct character (the $) - There's only one kind of immediate in MipsOperand. LSA immediates are handled by the predicate and renderer. Lowlights: - Hardcoded '$zero' in the div patterns is handled with a hack. MipsOperand::isReg() will return true for a k_RegisterIndex token with Index == 0 and getReg() will return ZERO for this case. Note that it doesn't return ZERO_64 on isGP64() targets. - I haven't cleaned up all of the now-unused functions. Some more of the generic parser could be removed too (integers and relocs for example). - insve.df needed a custom decoder to handle the implicit fourth operand that was needed to make it parse correctly. The difficulty was that the matcher expected a Token<'0'> but gets an Imm<0>. Adding an implicit zero solved this. Reviewers: matheusalmeida, vmedic Reviewed By: matheusalmeida Differential Revision: http://llvm-reviews.chandlerc.com/D3222 llvm-svn: 205292
2014-04-01 18:35:28 +08:00
return MCDisassembler::Success;
}
template <typename InsnType>
static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
// If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
// (otherwise we would have matched the ADDI instruction from the earlier
// ISA's instead).
//
// We have:
// 0b001000 sssss ttttt iiiiiiiiiiiiiiii
// BOVC if rs >= rt
// BEQZALC if rs == 0 && rt != 0
// BEQC if rs < rt && rs != 0
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
bool HasRs = false;
if (Rs >= Rt) {
MI.setOpcode(Mips::BOVC);
HasRs = true;
} else if (Rs != 0 && Rs < Rt) {
MI.setOpcode(Mips::BEQC);
HasRs = true;
} else
MI.setOpcode(Mips::BEQZALC);
if (HasRs)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rs)));
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rt)));
MI.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}
template <typename InsnType>
static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
// If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
// (otherwise we would have matched the ADDI instruction from the earlier
// ISA's instead).
//
// We have:
// 0b011000 sssss ttttt iiiiiiiiiiiiiiii
// BNVC if rs >= rt
// BNEZALC if rs == 0 && rt != 0
// BNEC if rs < rt && rs != 0
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
bool HasRs = false;
if (Rs >= Rt) {
MI.setOpcode(Mips::BNVC);
HasRs = true;
} else if (Rs != 0 && Rs < Rt) {
MI.setOpcode(Mips::BNEC);
HasRs = true;
} else
MI.setOpcode(Mips::BNEZALC);
if (HasRs)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rs)));
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rt)));
MI.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}
template <typename InsnType>
static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
// If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
// (otherwise we would have matched the BLEZL instruction from the earlier
// ISA's instead).
//
// We have:
// 0b010110 sssss ttttt iiiiiiiiiiiiiiii
// Invalid if rs == 0
// BLEZC if rs == 0 && rt != 0
// BGEZC if rs == rt && rt != 0
// BGEC if rs != rt && rs != 0 && rt != 0
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler::Fail;
else if (Rs == 0)
MI.setOpcode(Mips::BLEZC);
else if (Rs == Rt)
MI.setOpcode(Mips::BGEZC);
else {
HasRs = true;
MI.setOpcode(Mips::BGEC);
}
if (HasRs)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rs)));
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rt)));
MI.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}
template <typename InsnType>
static DecodeStatus DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
// If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
// (otherwise we would have matched the BGTZL instruction from the earlier
// ISA's instead).
//
// We have:
// 0b010111 sssss ttttt iiiiiiiiiiiiiiii
// Invalid if rs == 0
// BGTZC if rs == 0 && rt != 0
// BLTZC if rs == rt && rt != 0
// BLTC if rs != rt && rs != 0 && rt != 0
bool HasRs = false;
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
if (Rt == 0)
return MCDisassembler::Fail;
else if (Rs == 0)
MI.setOpcode(Mips::BGTZC);
else if (Rs == Rt)
MI.setOpcode(Mips::BLTZC);
else {
MI.setOpcode(Mips::BLTC);
HasRs = true;
}
if (HasRs)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rs)));
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rt)));
MI.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}
template <typename InsnType>
static DecodeStatus DecodeBgtzGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
// If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
// (otherwise we would have matched the BGTZ instruction from the earlier
// ISA's instead).
//
// We have:
// 0b000111 sssss ttttt iiiiiiiiiiiiiiii
// BGTZ if rt == 0
// BGTZALC if rs == 0 && rt != 0
// BLTZALC if rs != 0 && rs == rt
// BLTUC if rs != 0 && rs != rt
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
bool HasRs = false;
bool HasRt = false;
if (Rt == 0) {
MI.setOpcode(Mips::BGTZ);
HasRs = true;
} else if (Rs == 0) {
MI.setOpcode(Mips::BGTZALC);
HasRt = true;
} else if (Rs == Rt) {
MI.setOpcode(Mips::BLTZALC);
HasRs = true;
} else {
MI.setOpcode(Mips::BLTUC);
HasRs = true;
HasRt = true;
}
if (HasRs)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rs)));
if (HasRt)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rt)));
MI.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}
template <typename InsnType>
static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
// If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
// (otherwise we would have matched the BLEZL instruction from the earlier
// ISA's instead).
//
// We have:
// 0b000110 sssss ttttt iiiiiiiiiiiiiiii
// Invalid if rs == 0
// BLEZALC if rs == 0 && rt != 0
// BGEZALC if rs == rt && rt != 0
// BGEUC if rs != rt && rs != 0 && rt != 0
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler::Fail;
else if (Rs == 0)
MI.setOpcode(Mips::BLEZALC);
else if (Rs == Rt)
MI.setOpcode(Mips::BGEZALC);
else {
HasRs = true;
MI.setOpcode(Mips::BGEUC);
}
if (HasRs)
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rs)));
MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
Rt)));
MI.addOperand(MCOperand::createImm(Imm));
return MCDisassembler::Success;
}
/// 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 (Bytes.size() < 4) {
Size = 0;
return MCDisassembler::Fail;
}
// 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 {
if (IsMicroMips) {
Insn = (Bytes[2] << 0) | (Bytes[3] << 8) | (Bytes[0] << 16) |
(Bytes[1] << 24);
} else {
Insn = (Bytes[0] << 0) | (Bytes[1] << 8) | (Bytes[2] << 16) |
(Bytes[3] << 24);
}
}
return MCDisassembler::Success;
}
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;
if (IsMicroMips) {
Result = readInstruction16(Bytes, Address, Size, Insn, IsBigEndian);
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n");
// Calling the auto-generated decoder function for microMIPS32R6
// (and microMIPS64R6) 16-bit instructions.
Result = decodeInstruction(DecoderTableMicroMipsR616, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 2;
return Result;
}
}
DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n");
// Calling the auto-generated decoder function for microMIPS 16-bit
// instructions.
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;
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying MicroMips32r632 table (32-bit instructions):\n");
// Calling the auto-generated decoder function.
Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, Address,
this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
}
DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n");
// Calling the auto-generated decoder function.
Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address,
this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
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);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
}
if (hasMips32r6() && isGP64()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
}
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
}
if (hasCnMips()) {
DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
}
if (isGP64()) {
DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips6432, Instr, Insn,
Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
}
DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n");
// Calling the auto-generated decoder function.
Result =
decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI);
if (Result != MCDisassembler::Fail) {
Size = 4;
return Result;
}
return MCDisassembler::Fail;
}
static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
return MCDisassembler::Fail;
}
static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::GPR64RegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
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 DecodeGPRMM16MovePRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 7)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::GPRMM16MovePRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodePtrRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (static_cast<const MipsDisassembler *>(Decoder)->isGP64())
return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder);
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus DecodeDSPRRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
}
static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::CCRRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFCCRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 7)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::FCCRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFGRCCRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::FGRCCRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMem(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<16>(Insn & 0xffff);
unsigned Reg = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 21, 5);
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
if(Inst.getOpcode() == Mips::SC ||
Inst.getOpcode() == Mips::SCD){
Inst.addOperand(MCOperand::createReg(Reg));
}
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeCacheOp(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<16>(Insn & 0xffff);
unsigned Hint = fieldFromInstruction(Insn, 16, 5);
unsigned Base = 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 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 DecodeCacheOpR6(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = fieldFromInstruction(Insn, 7, 9);
unsigned Hint = fieldFromInstruction(Insn, 16, 5);
unsigned Base = 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));
unsigned Reg = fieldFromInstruction(Insn, 6, 5);
unsigned Base = fieldFromInstruction(Insn, 11, 5);
Reg = getReg(Decoder, Mips::MSA128BRegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
// The immediate field of an LD/ST instruction is scaled which means it must
// be multiplied (when decoding) by the size (in bytes) of the instructions'
// data format.
// .b - 1 byte
// .h - 2 bytes
// .w - 4 bytes
// .d - 8 bytes
switch(Inst.getOpcode())
{
default:
assert (0 && "Unexpected instruction");
return MCDisassembler::Fail;
break;
case Mips::LD_B:
case Mips::ST_B:
Inst.addOperand(MCOperand::createImm(Offset));
break;
case Mips::LD_H:
case Mips::ST_H:
Inst.addOperand(MCOperand::createImm(Offset * 2));
break;
case Mips::LD_W:
case Mips::ST_W:
Inst.addOperand(MCOperand::createImm(Offset * 4));
break;
case Mips::LD_D:
case Mips::ST_D:
Inst.addOperand(MCOperand::createImm(Offset * 8));
break;
}
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 DecodeMemMMGPImm7Lsl2(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
unsigned Offset = Insn & 0x7F;
unsigned Reg = fieldFromInstruction(Insn, 7, 3);
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Mips::GP));
Inst.addOperand(MCOperand::createImm(Offset << 2));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<4>(Insn & 0xf);
if (DecodeRegListOperand16(Inst, Insn, Address, Decoder)
== MCDisassembler::Fail)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createReg(Mips::SP));
Inst.addOperand(MCOperand::createImm(Offset << 2));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMemMMImm9(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<9>(Insn & 0x1ff);
unsigned Reg = fieldFromInstruction(Insn, 21, 5);
unsigned Base = fieldFromInstruction(Insn, 16, 5);
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<12>(Insn & 0x0fff);
unsigned Reg = fieldFromInstruction(Insn, 21, 5);
unsigned Base = fieldFromInstruction(Insn, 16, 5);
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
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(Base));
Inst.addOperand(MCOperand::createImm(Offset));
}
return MCDisassembler::Success;
}
static DecodeStatus DecodeMemMMImm16(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<16>(Insn & 0xffff);
unsigned Reg = fieldFromInstruction(Insn, 21, 5);
unsigned Base = fieldFromInstruction(Insn, 16, 5);
Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFMem(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<16>(Insn & 0xffff);
unsigned Reg = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 21, 5);
Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFMem2(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<16>(Insn & 0xffff);
unsigned Reg = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 21, 5);
Reg = getReg(Decoder, Mips::COP2RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFMem3(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<16>(Insn & 0xffff);
unsigned Reg = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 21, 5);
Reg = getReg(Decoder, Mips::COP3RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeFMemCop2R6(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Offset = SignExtend32<11>(Insn & 0x07ff);
unsigned Reg = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 11, 5);
Reg = getReg(Decoder, Mips::COP2RegClassID, Reg);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
Inst.addOperand(MCOperand::createReg(Reg));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int64_t Offset = SignExtend64<9>((Insn >> 7) & 0x1ff);
unsigned Rt = fieldFromInstruction(Insn, 16, 5);
unsigned Base = fieldFromInstruction(Insn, 21, 5);
Rt = getReg(Decoder, Mips::GPR32RegClassID, Rt);
Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
if(Inst.getOpcode() == Mips::SC_R6 || Inst.getOpcode() == Mips::SCD_R6){
Inst.addOperand(MCOperand::createReg(Rt));
}
Inst.addOperand(MCOperand::createReg(Rt));
Inst.addOperand(MCOperand::createReg(Base));
Inst.addOperand(MCOperand::createImm(Offset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
// Currently only hardware register 29 is supported.
if (RegNo != 29)
return MCDisassembler::Fail;
Inst.addOperand(MCOperand::createReg(Mips::HWR29));
return MCDisassembler::Success;
}
static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 30 || RegNo %2)
return MCDisassembler::Fail;
;
unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeACC64DSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo >= 4)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::ACC64DSPRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeHI32DSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo >= 4)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::HI32DSPRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeLO32DSPRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo >= 4)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::LO32DSPRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMSA128BRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::MSA128BRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMSA128HRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::MSA128HRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMSA128WRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::MSA128WRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMSA128DRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::MSA128DRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 7)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::MSACtrlRegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeCOP0RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::COP0RegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
const void *Decoder) {
if (RegNo > 31)
return MCDisassembler::Fail;
unsigned Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo);
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
static DecodeStatus DecodeBranchTarget(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
int32_t BranchOffset = (SignExtend32<16>(Offset) * 4) + 4;
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeJumpTarget(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2;
Inst.addOperand(MCOperand::createImm(JumpOffset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeBranchTarget21(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
int32_t BranchOffset = SignExtend32<21>(Offset) * 4;
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
int32_t BranchOffset = SignExtend32<26>(Offset) * 4;
Inst.addOperand(MCOperand::createImm(BranchOffset));
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 DecodeBranchTarget10MM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
int32_t BranchOffset = SignExtend32<10>(Offset) << 1;
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
int32_t BranchOffset = SignExtend32<16>(Offset) * 2;
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
}
static DecodeStatus DecodeJumpTargetMM(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 1;
Inst.addOperand(MCOperand::createImm(JumpOffset));
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,
const void *Decoder) {
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Insn)));
return MCDisassembler::Success;
}
static DecodeStatus DecodeLSAImm(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
// We add one to the immediate field as it was encoded as 'imm - 1'.
Inst.addOperand(MCOperand::createImm(Insn + 1));
return MCDisassembler::Success;
}
static DecodeStatus DecodeInsSize(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
// First we need to grab the pos(lsb) from MCInst.
int Pos = Inst.getOperand(2).getImm();
int Size = (int) Insn - Pos + 1;
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size)));
return MCDisassembler::Success;
}
static DecodeStatus DecodeExtSize(MCInst &Inst,
unsigned Insn,
uint64_t Address,
const void *Decoder) {
int Size = (int) Insn + 1;
Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size)));
return MCDisassembler::Success;
}
static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::createImm(SignExtend32<19>(Insn) * 4));
return MCDisassembler::Success;
}
static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
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 RegLst = fieldFromInstruction(Insn, 4, 2);
unsigned RegNum = RegLst & 0x3;
for (unsigned i = 0; i <= RegNum; i++)
Inst.addOperand(MCOperand::createReg(Regs[i]));
Inst.addOperand(MCOperand::createReg(Mips::RA));
return MCDisassembler::Success;
}
static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
unsigned RegPair = fieldFromInstruction(Insn, 7, 3);
switch (RegPair) {
default:
return MCDisassembler::Fail;
case 0:
Inst.addOperand(MCOperand::createReg(Mips::A1));
Inst.addOperand(MCOperand::createReg(Mips::A2));
break;
case 1:
Inst.addOperand(MCOperand::createReg(Mips::A1));
Inst.addOperand(MCOperand::createReg(Mips::A3));
break;
case 2:
Inst.addOperand(MCOperand::createReg(Mips::A2));
Inst.addOperand(MCOperand::createReg(Mips::A3));
break;
case 3:
Inst.addOperand(MCOperand::createReg(Mips::A0));
Inst.addOperand(MCOperand::createReg(Mips::S5));
break;
case 4:
Inst.addOperand(MCOperand::createReg(Mips::A0));
Inst.addOperand(MCOperand::createReg(Mips::S6));
break;
case 5:
Inst.addOperand(MCOperand::createReg(Mips::A0));
Inst.addOperand(MCOperand::createReg(Mips::A1));
break;
case 6:
Inst.addOperand(MCOperand::createReg(Mips::A0));
Inst.addOperand(MCOperand::createReg(Mips::A2));
break;
case 7:
Inst.addOperand(MCOperand::createReg(Mips::A0));
Inst.addOperand(MCOperand::createReg(Mips::A3));
break;
}
return MCDisassembler::Success;
}
static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder) {
Inst.addOperand(MCOperand::createImm(SignExtend32<25>(Insn << 2)));
return MCDisassembler::Success;
}