capstone/arch/Mips/MipsDisassembler.c

3427 lines
102 KiB
C

/* Capstone Disassembly Engine, http://www.capstone-engine.org */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
/* Rot127 <unisono@quyllur.org> 2022-2023 */
/* Automatically translated source file from LLVM. */
/* LLVM-commit: <commit> */
/* LLVM-tag: <tag> */
/* Only small edits allowed. */
/* For multiple similar edits, please create a Patch for the translator. */
/* Capstone's C++ file translator: */
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
//===- MipsDisassembler.cpp - Disassembler for Mips -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is part of the Mips Disassembler.
//
//===----------------------------------------------------------------------===//
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <capstone/platform.h>
#include "../../MCInst.h"
#include "../../MathExtras.h"
#include "../../MCInstPrinter.h"
#include "../../MCDisassembler.h"
#include "../../MCRegisterInfo.h"
#include "../../MCFixedLenDisassembler.h"
#include "../../cs_priv.h"
#include "../../utils.h"
#define GET_SUBTARGETINFO_ENUM
#include "MipsGenSubtargetInfo.inc"
#define GET_INSTRINFO_ENUM
#include "MipsGenInstrInfo.inc"
#define GET_REGINFO_ENUM
#include "MipsGenRegisterInfo.inc"
#define CONCAT(a, b) CONCAT_(a, b)
#define CONCAT_(a, b) a##_##b
#define DEBUG_TYPE "mips-disassembler"
bool Mips_getFeatureBits(unsigned int mode, unsigned int feature)
{
switch(feature) {
case Mips_FeatureGP64Bit:
return mode & (CS_MODE_MIPS3 | CS_MODE_MIPS4 |
CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureFP64Bit:
return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS3 |
CS_MODE_MIPS4 | CS_MODE_MIPS5 |
CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 |
CS_MODE_MIPS32R5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureNaN2008:
return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS64R6);
case Mips_FeatureAbs2008:
return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS64R6);
case Mips_FeatureMips1:
return mode & (CS_MODE_MIPS1 | CS_MODE_MIPS2 |
CS_MODE_MIPS32 | CS_MODE_MIPS32R2 |
CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 |
CS_MODE_MIPS32R6 | CS_MODE_MIPS3 |
CS_MODE_MIPS4 | CS_MODE_MIPS5 |
CS_MODE_MIPS64 | CS_MODE_MIPS64R2 |
CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 |
CS_MODE_MIPS64R6 | CS_MODE_OCTEON |
CS_MODE_OCTEONP);
case Mips_FeatureMips2:
return mode & (CS_MODE_MIPS2 | CS_MODE_MIPS32 |
CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 |
CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 |
CS_MODE_MIPS3 | CS_MODE_MIPS4 |
CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips3_32:
return mode & (CS_MODE_MIPS32 | CS_MODE_MIPS32R2 |
CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 |
CS_MODE_MIPS32R6 | CS_MODE_MIPS3 |
CS_MODE_MIPS4 | CS_MODE_MIPS5 |
CS_MODE_MIPS64 | CS_MODE_MIPS64R2 |
CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 |
CS_MODE_MIPS64R6 | CS_MODE_OCTEON |
CS_MODE_OCTEONP);
case Mips_FeatureMips3_32r2:
return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 |
CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 |
CS_MODE_MIPS3 | CS_MODE_MIPS4 |
CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips3:
return mode & (CS_MODE_MIPS3 | CS_MODE_MIPS4 |
CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips4_32:
return mode & (CS_MODE_MIPS32 | CS_MODE_MIPS32R2 |
CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 |
CS_MODE_MIPS32R6 | CS_MODE_MIPS4 |
CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips4_32r2:
return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 |
CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 |
CS_MODE_MIPS4 | CS_MODE_MIPS5 |
CS_MODE_MIPS64 | CS_MODE_MIPS64R2 |
CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 |
CS_MODE_MIPS64R6 | CS_MODE_OCTEON |
CS_MODE_OCTEONP);
case Mips_FeatureMips4:
return mode & (CS_MODE_MIPS4 | CS_MODE_MIPS5 |
CS_MODE_MIPS64 | CS_MODE_MIPS64R2 |
CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 |
CS_MODE_MIPS64R6 | CS_MODE_OCTEON |
CS_MODE_OCTEONP);
case Mips_FeatureMips5_32r2:
return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 |
CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 |
CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips5:
return mode & (CS_MODE_MIPS5 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips32:
return mode & (CS_MODE_MIPS32 | CS_MODE_MIPS32R2 |
CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 |
CS_MODE_MIPS32R6 | CS_MODE_MIPS64 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips32r2:
return mode & (CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 |
CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 |
CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips32r3:
return mode & (CS_MODE_MIPS32R3 | CS_MODE_MIPS32R5 |
CS_MODE_MIPS32R6 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6);
case Mips_FeatureMips32r5:
return mode & (CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6);
case Mips_FeatureMips32r6:
return mode & (CS_MODE_MIPS32R6 | CS_MODE_MIPS64R6);
case Mips_FeatureMips64:
return mode & (CS_MODE_MIPS64 | CS_MODE_MIPS64R2 |
CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 |
CS_MODE_MIPS64R6 | CS_MODE_OCTEON |
CS_MODE_OCTEONP);
case Mips_FeatureMips64r2:
return mode & (CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 |
CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 |
CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureMips64r3:
return mode & (CS_MODE_MIPS64R3 | CS_MODE_MIPS64R5 |
CS_MODE_MIPS64R6);
case Mips_FeatureMips64r5:
return mode & (CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6);
case Mips_FeatureMips64r6:
return mode & CS_MODE_MIPS64R6;
case Mips_FeatureMips16:
return mode & CS_MODE_MIPS16;
case Mips_FeatureMicroMips:
return mode & CS_MODE_MICRO;
case Mips_FeatureNanoMips:
return mode & (CS_MODE_NANOMIPS | CS_MODE_NMS1 |
CS_MODE_I7200);
case Mips_FeatureNMS1:
return mode & CS_MODE_NMS1;
case Mips_FeatureTLB:
return mode & CS_MODE_I7200;
case Mips_FeatureCnMips:
return mode & (CS_MODE_OCTEON | CS_MODE_OCTEONP);
case Mips_FeatureCnMipsP:
return mode & CS_MODE_OCTEONP;
case Mips_FeaturePTR64Bit:
return mode & CS_MODE_MIPS_PTR64;
case Mips_FeatureSoftFloat:
return mode & CS_MODE_MIPS_NOFLOAT;
case Mips_FeatureI7200:
return mode & CS_MODE_I7200;
// optional features always enabled
case Mips_FeatureDSP: // Mips DSP ASE
return true;
case Mips_FeatureDSPR2: // Mips DSP-R2 ASE
return true;
case Mips_FeatureDSPR3: // Mips DSP-R3 ASE
return true;
case Mips_FeatureMips3D: // Mips 3D ASE
return true;
case Mips_FeatureMSA: // Mips MSA ASE
return true;
case Mips_FeatureEVA: { // Mips EVA ASE
if (mode & CS_MODE_NANOMIPS) {
return mode & CS_MODE_I7200;
}
return true;
}
case Mips_FeatureCRC: // Mips R6 CRC ASE
return true;
case Mips_FeatureVirt: // Mips Virtualization ASE
return true;
case Mips_FeatureGINV: // Mips Global Invalidate ASE
return true;
case Mips_FeatureMT: { // Mips MT ASE
if (mode & CS_MODE_NANOMIPS) {
return mode & CS_MODE_I7200;
}
return true;
}
default:
return false;
}
}
static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes,
size_t BytesLen, uint64_t Address, SStream *CStream);
// 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 DecodeGPRNM3RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM4RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNMRARegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM3ZRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM4ZRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM32NZRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM2R1RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeGPRNM1R1RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePtrRegisterClass(MCInst *Inst, uint32_t 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, uint32_t 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 DecodeCOP0SelRegisterClass(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 DecodeBranchTarget1SImm16(MCInst *Inst, unsigned Offset,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeJumpTarget(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeBranchTarget21(MCInst *Inst, unsigned Offset,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeBranchTarget21MM(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);
// DecodeBranchTarget26MM - Decode microMIPS branch offset, which is
// shifted left by 1 bit.
static DecodeStatus DecodeBranchTarget26MM(MCInst *Inst, unsigned Offset,
uint64_t Address,
const void *Decoder);
// DecodeBranchTargetMM - Decode nanoMIPS branch offset, which is
// shifted left by 1 bit.
#define DECLARE_DecodeBranchTargetNM(bits) \
static DecodeStatus CONCAT(DecodeBranchTargetNM, bits)( \
MCInst * Inst, unsigned Offset, uint64_t Address, \
const void *Decoder);
DECLARE_DecodeBranchTargetNM(10);
DECLARE_DecodeBranchTargetNM(7);
DECLARE_DecodeBranchTargetNM(21);
DECLARE_DecodeBranchTargetNM(25);
DECLARE_DecodeBranchTargetNM(14);
DECLARE_DecodeBranchTargetNM(11);
DECLARE_DecodeBranchTargetNM(5);
// DecodeJumpTargetMM - Decode microMIPS jump target, which is
// shifted left by 1 bit.
static DecodeStatus DecodeJumpTargetMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
// DecodeJumpTargetXMM - Decode microMIPS jump and link exchange target,
// which is shifted left by 2 bit.
static DecodeStatus DecodeJumpTargetXMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMem(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
#define DECLARE_DecodeMemNM(Offbits, isSigned, rt) \
static DecodeStatus CONCAT(DecodeMemNM, \
CONCAT(Offbits, CONCAT(isSigned, rt)))( \
MCInst * Inst, uint32_t Insn, uint64_t Address, \
const void *Decoder);
DECLARE_DecodeMemNM(6, 0, Mips_GPRNM3RegClassID);
DECLARE_DecodeMemNM(7, 0, Mips_GPRNMSPRegClassID);
DECLARE_DecodeMemNM(9, 0, Mips_GPRNMGPRegClassID);
DECLARE_DecodeMemNM(2, 0, Mips_GPRNM3RegClassID);
DECLARE_DecodeMemNM(3, 0, Mips_GPRNM3RegClassID);
DECLARE_DecodeMemNM(21, 0, Mips_GPRNMGPRegClassID);
DECLARE_DecodeMemNM(18, 0, Mips_GPRNMGPRegClassID);
DECLARE_DecodeMemNM(12, 0, Mips_GPRNM32RegClassID);
DECLARE_DecodeMemNM(9, 1, Mips_GPRNM32RegClassID);
static DecodeStatus DecodeMemZeroNM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
#define DECLARE_DecodeMemNMRX(rt) \
static DecodeStatus CONCAT(DecodeMemNMRX, \
rt)(MCInst * Inst, uint32_t Insn, \
uint64_t Address, const void *Decoder);
DECLARE_DecodeMemNMRX(Mips_GPRNM3RegClassID);
DECLARE_DecodeMemNMRX(Mips_GPRNM32RegClassID);
static DecodeStatus DecodeMemNM4x4(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemEVA(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeLoadByte15(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCacheOp(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCacheOpMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodePrefeOpMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSyncI(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeSyncI_MM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSynciR6(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMSA128Mem(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemMMImm4(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMemMMImm9(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemMMImm12(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMemMMImm16(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeFMem(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFMemMMR2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeFMem2(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFMem3(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeFMemCop2R6(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeFMemCop2MMR6(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSpecial3LlSc(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeAddiur2Simm7(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeLi16Imm(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodePOOL16BEncodedField(MCInst *Inst, unsigned Value,
uint64_t Address,
const void *Decoder);
#define DECLARE_DecodeUImmWithOffsetAndScale(Bits, Offset, Scale) \
static DecodeStatus CONCAT(DecodeUImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, Scale)))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder);
DECLARE_DecodeUImmWithOffsetAndScale(5, 0, 4);
DECLARE_DecodeUImmWithOffsetAndScale(6, 0, 4);
DECLARE_DecodeUImmWithOffsetAndScale(2, 1, 1);
DECLARE_DecodeUImmWithOffsetAndScale(5, 1, 1);
DECLARE_DecodeUImmWithOffsetAndScale(8, 0, 1);
DECLARE_DecodeUImmWithOffsetAndScale(18, 0, 1);
DECLARE_DecodeUImmWithOffsetAndScale(21, 0, 1);
#define DEFINE_DecodeUImmWithOffset(Bits, Offset) \
static DecodeStatus CONCAT(DecodeUImmWithOffset, \
CONCAT(Bits, Offset))(MCInst * Inst, \
unsigned Value, \
uint64_t Address, \
const void *Decoder) \
{ \
return CONCAT(DecodeUImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, 1)))( \
Inst, Value, Address, Decoder); \
}
DEFINE_DecodeUImmWithOffset(5, 1);
DEFINE_DecodeUImmWithOffset(2, 1);
#define DECLARE_DecodeSImmWithOffsetAndScale(Bits, Offset, ScaleBy) \
static DecodeStatus CONCAT( \
DecodeSImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, ScaleBy)))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder);
#define DECLARE_DecodeSImmWithOffsetAndScale_2(Bits, Offset) DECLARE_DecodeSImmWithOffsetAndScale(Bits, Offset, 1)
#define DECLARE_DecodeSImmWithOffsetAndScale_3(Bits) DECLARE_DecodeSImmWithOffsetAndScale(Bits, 0, 1)
DECLARE_DecodeSImmWithOffsetAndScale_3(16);
DECLARE_DecodeSImmWithOffsetAndScale_3(10);
DECLARE_DecodeSImmWithOffsetAndScale_3(4);
DECLARE_DecodeSImmWithOffsetAndScale_3(6);
DECLARE_DecodeSImmWithOffsetAndScale_3(32);
static DecodeStatus DecodeInsSize(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeImmM1To126(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeUImm4Mask(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeUImm3Shift(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeNMRegListOperand(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeNMRegList16Operand(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeNegImm12(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
#define DECLARE_DecodeSImmWithReg(Bits, Offset, Scale, RegNum) \
static DecodeStatus CONCAT( \
DecodeSImmWithReg, \
CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder);
DECLARE_DecodeSImmWithReg(32, 0, 1, Mips_GP_NM);
#define DECLARE_DecodeUImmWithReg(Bits, Offset, Scale, RegNum) \
static DecodeStatus CONCAT( \
DecodeUImmWithReg, \
CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder);
DECLARE_DecodeUImmWithReg(8, 0, 1, Mips_SP_NM);
DECLARE_DecodeUImmWithReg(21, 0, 1, Mips_GP_NM);
DECLARE_DecodeUImmWithReg(18, 0, 1, Mips_GP_NM);
static DecodeStatus DecodeSImm32s12(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
#define DECLARE_DecodeAddressPCRelNM(Bits) \
static DecodeStatus CONCAT(DecodeAddressPCRelNM, Bits)( \
MCInst * Inst, uint32_t Insn, uint64_t Address, \
const void *Decoder);
DECLARE_DecodeAddressPCRelNM(22);
DECLARE_DecodeAddressPCRelNM(32);
static DecodeStatus DecodeBranchConflictNM(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeSimm19Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSimm18Lsl3(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSimm9SP(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeANDI16Imm(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeSimm23Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't
/// handle.
static DecodeStatus DecodeINSVE_DF(MCInst *MI, uint32_t insn, uint64_t Address,
const void *Decoder);
/*
static DecodeStatus DecodeDAHIDATIMMR6(MCInst *MI, uint32_t insn,
uint64_t Address, const void *Decoder);
*/
static DecodeStatus DecodeDAHIDATI(MCInst *MI, uint32_t insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeAddiGroupBranch(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeDaddiGroupBranch(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePOP65GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodePOP75GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBlezlGroupBranch(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBgtzlGroupBranch(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBgtzGroupBranch(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBlezGroupBranch(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeDINS(MCInst *MI, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeDEXT(MCInst *MI, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeCRC(MCInst *MI, uint32_t Insn, uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeRegListOperand(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeRegListOperand16(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeMovePRegPair(MCInst *Inst, unsigned RegPair,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMovePOperands(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeFIXMEInstruction(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
#include "MipsGenDisassemblerTables.inc"
static unsigned getReg(const MCInst *Inst, unsigned RC, unsigned RegNo)
{
const MCRegisterClass* c = MCRegisterInfo_getRegClass(Inst->MRI, RC);
return MCRegisterClass_getRegister(c, RegNo);
}
typedef DecodeStatus (*DecodeFN)(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder);
static DecodeStatus DecodeINSVE_DF(MCInst *MI, uint32_t insn, uint64_t Address,
const void *Decoder)
{
// The size of the n field depends on the element size
// The register class also depends on this.
uint32_t tmp = fieldFromInstruction_4(insn, 17, 5);
unsigned NSize = 0;
DecodeFN RegDecoder = NULL;
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
CS_ASSERT_RET_VAL(0 && "Invalid encoding", MCDisassembler_Fail);
// $wd
tmp = fieldFromInstruction_4(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_4(insn, 16, NSize);
MCOperand_CreateImm0(MI, (tmp));
// $ws
tmp = fieldFromInstruction_4(insn, 11, 5);
if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler_Fail)
return MCDisassembler_Fail;
// $n2
MCOperand_CreateImm0(MI, (0));
return MCDisassembler_Success;
}
/*
static DecodeStatus DecodeDAHIDATIMMR6(MCInst *MI, uint32_t insn,
uint64_t Address, const void *Decoder)
{
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
uint32_t Imm = fieldFromInstruction_4(insn, 0, 16);
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
*/
static DecodeStatus DecodeDAHIDATI(MCInst *MI, uint32_t insn, uint64_t Address,
const void *Decoder)
{
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Imm = fieldFromInstruction_4(insn, 0, 16);
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeAddiGroupBranch(MCInst *MI, uint32_t 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
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rs >= Rt) {
MCInst_setOpcode(MI, (Mips_BOVC));
HasRs = true;
} else if (Rs != 0 && Rs < Rt) {
MCInst_setOpcode(MI, (Mips_BEQC));
HasRs = true;
} else
MCInst_setOpcode(MI, (Mips_BEQZALC));
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder)
{
uint32_t Rt = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm = 0;
if (Rs >= Rt) {
MCInst_setOpcode(MI, (Mips_BOVC_MMR6));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
} else if (Rs != 0 && Rs < Rt) {
MCInst_setOpcode(MI, (Mips_BEQC_MMR6));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
4 +
4;
} else {
MCInst_setOpcode(MI, (Mips_BEQZALC_MMR6));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
}
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeDaddiGroupBranch(MCInst *MI, uint32_t 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
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rs >= Rt) {
MCInst_setOpcode(MI, (Mips_BNVC));
HasRs = true;
} else if (Rs != 0 && Rs < Rt) {
MCInst_setOpcode(MI, (Mips_BNEC));
HasRs = true;
} else
MCInst_setOpcode(MI, (Mips_BNEZALC));
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder)
{
uint32_t Rt = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm = 0;
if (Rs >= Rt) {
MCInst_setOpcode(MI, (Mips_BNVC_MMR6));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
} else if (Rs != 0 && Rs < Rt) {
MCInst_setOpcode(MI, (Mips_BNEC_MMR6));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
4 +
4;
} else {
MCInst_setOpcode(MI, (Mips_BNEZALC_MMR6));
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
}
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodePOP65GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder)
{
// We have:
// 0b110101 ttttt sssss iiiiiiiiiiiiiiii
// Invalid if rt == 0
// BGTZC_MMR6 if rs == 0 && rt != 0
// BLTZC_MMR6 if rs == rt && rt != 0
// BLTC_MMR6 if rs != rt && rs != 0 && rt != 0
uint32_t Rt = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0)
MCInst_setOpcode(MI, (Mips_BGTZC_MMR6));
else if (Rs == Rt)
MCInst_setOpcode(MI, (Mips_BLTZC_MMR6));
else {
MCInst_setOpcode(MI, (Mips_BLTC_MMR6));
HasRs = true;
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodePOP75GroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder)
{
// We have:
// 0b111101 ttttt sssss iiiiiiiiiiiiiiii
// Invalid if rt == 0
// BLEZC_MMR6 if rs == 0 && rt != 0
// BGEZC_MMR6 if rs == rt && rt != 0
// BGEC_MMR6 if rs != rt && rs != 0 && rt != 0
uint32_t Rt = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0)
MCInst_setOpcode(MI, (Mips_BLEZC_MMR6));
else if (Rs == Rt)
MCInst_setOpcode(MI, (Mips_BGEZC_MMR6));
else {
HasRs = true;
MCInst_setOpcode(MI, (Mips_BGEC_MMR6));
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBlezlGroupBranch(MCInst *MI, uint32_t 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
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0)
MCInst_setOpcode(MI, (Mips_BLEZC));
else if (Rs == Rt)
MCInst_setOpcode(MI, (Mips_BGEZC));
else {
HasRs = true;
MCInst_setOpcode(MI, (Mips_BGEC));
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBgtzlGroupBranch(MCInst *MI, uint32_t 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;
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0)
MCInst_setOpcode(MI, (Mips_BGTZC));
else if (Rs == Rt)
MCInst_setOpcode(MI, (Mips_BLTZC));
else {
MCInst_setOpcode(MI, (Mips_BLTC));
HasRs = true;
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBgtzGroupBranch(MCInst *MI, uint32_t 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
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
bool HasRt = false;
if (Rt == 0) {
MCInst_setOpcode(MI, (Mips_BGTZ));
HasRs = true;
} else if (Rs == 0) {
MCInst_setOpcode(MI, (Mips_BGTZALC));
HasRt = true;
} else if (Rs == Rt) {
MCInst_setOpcode(MI, (Mips_BLTZALC));
HasRs = true;
} else {
MCInst_setOpcode(MI, (Mips_BLTUC));
HasRs = true;
HasRt = true;
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
if (HasRt)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBlezGroupBranch(MCInst *MI, uint32_t 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
uint32_t Rs = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(insn, 16, 5);
int64_t Imm =
SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0)
MCInst_setOpcode(MI, (Mips_BLEZALC));
else if (Rs == Rt)
MCInst_setOpcode(MI, (Mips_BGEZALC));
else {
HasRs = true;
MCInst_setOpcode(MI, (Mips_BGEUC));
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
// Override the generated disassembler to produce DEXT all the time. This is
// for feature / behaviour parity with binutils.
static DecodeStatus DecodeDEXT(MCInst *MI, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
unsigned Msbd = fieldFromInstruction_4(Insn, 11, 5);
unsigned Lsb = fieldFromInstruction_4(Insn, 6, 5);
unsigned Size = 0;
unsigned Pos = 0;
switch (MCInst_getOpcode(MI)) {
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:
CS_ASSERT_RET_VAL(0 && "Unknown DEXT instruction!", MCDisassembler_Fail);
}
MCInst_setOpcode(MI, (Mips_DEXT));
uint32_t Rs = fieldFromInstruction_4(Insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(Insn, 16, 5);
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rt)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs)));
MCOperand_CreateImm0(MI, (Pos));
MCOperand_CreateImm0(MI, (Size));
return MCDisassembler_Success;
}
// Override the generated disassembler to produce DINS all the time. This is
// for feature / behaviour parity with binutils.
static DecodeStatus DecodeDINS(MCInst *MI, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
unsigned Msbd = fieldFromInstruction_4(Insn, 11, 5);
unsigned Lsb = fieldFromInstruction_4(Insn, 6, 5);
unsigned Size = 0;
unsigned Pos = 0;
switch (MCInst_getOpcode(MI)) {
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:
CS_ASSERT_RET_VAL(0 && "Unknown DINS instruction!", MCDisassembler_Fail);
}
uint32_t Rs = fieldFromInstruction_4(Insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(Insn, 16, 5);
MCInst_setOpcode(MI, (Mips_DINS));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rt)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR64RegClassID, Rs)));
MCOperand_CreateImm0(MI, (Pos));
MCOperand_CreateImm0(MI, (Size));
return MCDisassembler_Success;
}
// Auto-generated decoder wouldn't add the third operand for CRC32*.
static DecodeStatus DecodeCRC(MCInst *MI, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
uint32_t Rs = fieldFromInstruction_4(Insn, 21, 5);
uint32_t Rt = fieldFromInstruction_4(Insn, 16, 5);
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
return MCDisassembler_Success;
}
/// Read two bytes from the ArrayRef and return 16 bit halfword sorted
/// according to the given endianness.
static DecodeStatus readInstruction16(const uint8_t *Bytes, size_t BytesLen,
uint64_t Address, uint64_t *Size,
uint64_t *Insn, bool IsBigEndian)
{
// We want to read exactly 2 Bytes of data.
if (BytesLen < 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 endianness.
static DecodeStatus readInstruction32(const uint8_t *Bytes, size_t BytesLen,
uint64_t Address, uint64_t *Size,
uint64_t *Insn, bool IsBigEndian,
bool IsMicroMips)
{
// We want to read exactly 4 Bytes of data.
if (BytesLen < 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) |
((unsigned)Bytes[0] << 24);
} else {
if (IsMicroMips) {
*Insn = (Bytes[2] << 0) | (Bytes[3] << 8) |
(Bytes[0] << 16) | ((unsigned)Bytes[1] << 24);
} else {
*Insn = (Bytes[0] << 0) | (Bytes[1] << 8) |
(Bytes[2] << 16) | ((unsigned)Bytes[3] << 24);
}
}
return MCDisassembler_Success;
}
/// Read 6 bytes from the ArrayRef and return in a 64-bit bit word sorted
/// according to the given endianness and encoding byte-order.
static DecodeStatus readInstruction48(const uint8_t *Bytes, size_t BytesLen,
uint64_t Address, uint64_t *Size,
uint64_t *Insn, bool IsBigEndian,
bool IsNanoMips)
{
// We want to read exactly 6 Bytes of little-endian data in nanoMIPS mode.
if (BytesLen < 6 || IsBigEndian || !IsNanoMips) {
*Size = 0;
return MCDisassembler_Fail;
}
// High 16 bits of a 32-bit nanoMIPS 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).
//
// nanoMIPS byte ordering:
// Little-endian: 1 | 0 | 3 | 2 | 5 | 4
*Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
*Insn = ((*Insn << 32) | (Bytes[4] << 0) | (Bytes[5] << 8) |
(Bytes[2] << 16) | ((unsigned)Bytes[3] << 24));
return MCDisassembler_Success;
}
static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes,
size_t BytesLen, uint64_t Address, SStream *CStream)
{
uint64_t Insn;
DecodeStatus Result;
*Size = 0;
cs_mode mode = Instr->csh->mode;
bool IsBigEndian = mode & CS_MODE_BIG_ENDIAN;
bool IsMicroMips = Mips_getFeatureBits(mode, Mips_FeatureMicroMips);
bool IsNanoMips = Mips_getFeatureBits(mode, Mips_FeatureNanoMips);
bool IsMips32r6 = Mips_getFeatureBits(mode, Mips_FeatureMips32r6);
bool IsMips2 = Mips_getFeatureBits(mode, Mips_FeatureMips2);
bool IsMips16 = Mips_getFeatureBits(mode, Mips_FeatureMips16);
bool IsCnMips = Mips_getFeatureBits(mode, Mips_FeatureCnMips);
bool IsCnMipsP = Mips_getFeatureBits(mode, Mips_FeatureCnMipsP);
bool IsFP64 = Mips_getFeatureBits(mode, Mips_FeatureFP64Bit);
bool IsGP64 = Mips_getFeatureBits(mode, Mips_FeatureGP64Bit);
bool IsPTR64 = Mips_getFeatureBits(mode, Mips_FeaturePTR64Bit);
// Only present in MIPS-I and MIPS-II
bool HasCOP3 = !Mips_getFeatureBits(mode, Mips_FeatureMips32) &&
!Mips_getFeatureBits(mode, Mips_FeatureMips3);
if (IsNanoMips) {
uint64_t Insn2;
Result = readInstruction48(Bytes, BytesLen, Address, Size,
&Insn2, IsBigEndian, IsNanoMips);
if (Result != MCDisassembler_Fail) {
// Calling the auto-generated decoder function.
Result = decodeInstruction_8(DecoderTableNanoMips48,
Instr, Insn2, Address, NULL);
if (Result != MCDisassembler_Fail) {
*Size = 6;
return Result;
}
}
Result = readInstruction32(Bytes, BytesLen, Address, Size,
&Insn, IsBigEndian, IsNanoMips);
if (Result != MCDisassembler_Fail) {
// Calling the auto-generated decoder function.
Result = decodeInstruction_4(DecoderTableNanoMips32,
Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
}
Result = readInstruction16(Bytes, BytesLen, Address, Size,
&Insn, IsBigEndian);
if (Result != MCDisassembler_Fail) {
Result = decodeInstruction_2(DecoderTableNanoMips_Conflict_Space16,
Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 2;
return Result;
}
// Calling the auto-generated decoder function for NanoMips
// 16-bit instructions.
Result = decodeInstruction_2(DecoderTableNanoMips16,
Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 2;
return Result;
}
}
// This is an invalid instruction. Claim that the Size is 2 bytes. Since
// nanoMIPS instructions have a minimum alignment of 2, the next 2 bytes
// could form a valid instruction.
*Size = 2;
return MCDisassembler_Fail;
}
if (IsMicroMips) {
Result = readInstruction16(Bytes, BytesLen, Address, Size,
&Insn, IsBigEndian);
if (Result == MCDisassembler_Fail)
return MCDisassembler_Fail;
if (IsMips32r6) {
// Calling the auto-generated decoder function for microMIPS32R6
// 16-bit instructions.
Result = decodeInstruction_2(DecoderTableMicroMipsR616,
Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 2;
return Result;
}
}
// Calling the auto-generated decoder function for microMIPS 16-bit
// instructions.
Result = decodeInstruction_2(DecoderTableMicroMips16, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail) {
*Size = 2;
return Result;
}
Result = readInstruction32(Bytes, BytesLen, Address, Size,
&Insn, IsBigEndian, IsMicroMips);
if (Result == MCDisassembler_Fail)
return MCDisassembler_Fail;
if (IsMips32r6) {
// Calling the auto-generated decoder function.
Result = decodeInstruction_4(DecoderTableMicroMipsR6_Ambiguous32,
Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
Result = decodeInstruction_4(DecoderTableMicroMipsR632,
Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
}
// Calling the auto-generated decoder function.
Result = decodeInstruction_4(DecoderTableMicroMips32, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
Result = decodeInstruction_4(DecoderTableMicroMipsDSP32, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
if (IsFP64) {
Result =
decodeInstruction_4(DecoderTableMicroMipsFP6432,
Instr, Insn, Address, NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
}
// This is an invalid instruction. Claim that the Size is 2 bytes. Since
// microMIPS instructions have a minimum alignment of 2, the next 2 bytes
// could form a valid instruction. The two bytes we rejected as an
// instruction could have actually beeen an inline constant pool that is
// unconditionally branched over.
*Size = 2;
return MCDisassembler_Fail;
}
if (IsMips16) {
Result = readInstruction32(Bytes, BytesLen, Address, Size,
&Insn, IsBigEndian, IsMicroMips);
if (Result != MCDisassembler_Fail) {
Result = decodeInstruction_4(DecoderTable32, Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail) {
*Size = 4;
return Result;
}
}
Result = readInstruction16(Bytes, BytesLen, Address, Size,
&Insn, IsBigEndian);
if (Result == MCDisassembler_Fail) {
return MCDisassembler_Fail;
}
*Size = 2;
return decodeInstruction_2(DecoderTable16, Instr, Insn, Address, NULL);
}
// Attempt to read the instruction so that we can attempt to decode it. If
// the buffer is not 4 bytes long, let the higher level logic figure out
// what to do with a size of zero and MCDisassembler::Fail.
Result = readInstruction32(Bytes, BytesLen, Address, Size, &Insn, IsBigEndian,
IsMicroMips);
if (Result == MCDisassembler_Fail)
return MCDisassembler_Fail;
// The only instruction size for standard encoded MIPS.
*Size = 4;
if (HasCOP3) {
Result = decodeInstruction_4(DecoderTableCOP3_32, Instr, Insn,
Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsMips32r6 && IsGP64) {
Result = decodeInstruction_4(DecoderTableMips32r6_64r6_GP6432,
Instr, Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsMips32r6 && IsPTR64) {
Result = decodeInstruction_4(DecoderTableMips32r6_64r6_PTR6432,
Instr, Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsMips32r6) {
Result = decodeInstruction_4(DecoderTableMips32r6_64r6_Ambiguous32, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
Result = decodeInstruction_4(DecoderTableMips32r6_64r6_BranchZero32, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
Result = decodeInstruction_4(DecoderTableMips32r6_64r632, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsMips2 && IsPTR64) {
Result = decodeInstruction_4(DecoderTableMips32_64_PTR6432,
Instr, Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsCnMips) {
Result = decodeInstruction_4(DecoderTableCnMips32, Instr, Insn,
Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsCnMipsP) {
Result = decodeInstruction_4(DecoderTableCnMipsP32, Instr, Insn,
Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsGP64) {
Result = decodeInstruction_4(DecoderTableMips6432, Instr, Insn,
Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
if (IsFP64) {
Result = decodeInstruction_4(DecoderTableMipsFP6432, Instr,
Insn, Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
}
Result = decodeInstruction_4(DecoderTableMipsDSP32, Instr, Insn,
Address, NULL);
if (Result != MCDisassembler_Fail)
return Result;
// Calling the auto-generated decoder function.
Result = decodeInstruction_4(DecoderTableMips32, Instr, Insn, Address,
NULL);
if (Result != MCDisassembler_Fail)
return Result;
return MCDisassembler_Fail;
}
static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 7)
return MCDisassembler_Fail;
if (RegNo < 2)
RegNo += 16;
unsigned Reg = getReg(Inst, Mips_GPR32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPR64RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return MCDisassembler_Fail;
unsigned Reg = getReg(Inst, Mips_GPR64RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_GPRMM16RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_GPRMM16ZeroRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_GPRMM16MovePRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_GPR32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM3RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 7)
return MCDisassembler_Fail;
RegNo |= ((RegNo & 0x4) ^ 0x4) << 2;
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNMRARegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
MCOperand_CreateReg0(Inst, (Mips_RA_NM));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM3ZRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 7)
return MCDisassembler_Fail;
if (RegNo != 0)
RegNo |= ((RegNo & 0x4) ^ 0x4) << 2;
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM4RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return MCDisassembler_Fail;
RegNo &= ~0x8;
RegNo += (RegNo < 4 ? 8 : 0);
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM4ZRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return MCDisassembler_Fail;
RegNo &= ~0x8;
if (RegNo == 3)
RegNo = 0;
else
RegNo += (RegNo < 3 ? 8 : 0);
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM32NZRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo == 0)
return MCDisassembler_Fail;
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM32RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return MCDisassembler_Fail;
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM2R1RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo > 31)
return MCDisassembler_Fail;
RegNo += 4;
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Reg + 1));
return MCDisassembler_Success;
}
static DecodeStatus DecodeGPRNM1R1RegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (RegNo != 0 && RegNo != 1)
return MCDisassembler_Fail;
RegNo += 4;
unsigned Reg = getReg(Inst, Mips_GPRNM32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodePtrRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
if (Mips_getFeatureBits(Inst->csh->mode, Mips_FeatureGP64Bit))
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(Inst, Mips_FGR64RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_FGR32RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_CCRRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_FCCRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_FGRCCRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMem(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Reg = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
if (MCInst_getOpcode(Inst) == Mips_SC ||
MCInst_getOpcode(Inst) == Mips_SCD)
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
#define DEFINE_DecodeMemNM(Offbits, isSigned, rt) \
static DecodeStatus CONCAT(DecodeMemNM, \
CONCAT(Offbits, CONCAT(isSigned, rt)))( \
MCInst * Inst, uint32_t Insn, uint64_t Address, \
const void *Decoder) \
{ \
int Offset = (Insn & ((1 << Offbits) - 1)); \
if (isSigned) \
Offset = SignExtend32((Offset), Offbits); \
unsigned Base; \
\
switch (rt) { \
case Mips_GPRNMGPRegClassID: \
case Mips_GPRNMSPRegClassID: \
Base = 0; \
break; \
case Mips_GPRNM3RegClassID: \
Base = fieldFromInstruction_4(Insn, Offbits, 3); \
break; \
case Mips_GPRNM4RegClassID: \
case Mips_GPRNM4ZRegClassID: \
\
break; \
default: \
Base = fieldFromInstruction_4(Insn, Offbits, 5); \
} \
Base = getReg(Inst, rt, Base); \
\
MCOperand_CreateReg0(Inst, (Base)); \
MCOperand_CreateImm0(Inst, (Offset)); \
\
return MCDisassembler_Success; \
}
DEFINE_DecodeMemNM(6, 0, Mips_GPRNM3RegClassID);
DEFINE_DecodeMemNM(7, 0, Mips_GPRNMSPRegClassID);
DEFINE_DecodeMemNM(9, 0, Mips_GPRNMGPRegClassID);
DEFINE_DecodeMemNM(2, 0, Mips_GPRNM3RegClassID);
DEFINE_DecodeMemNM(3, 0, Mips_GPRNM3RegClassID);
DEFINE_DecodeMemNM(21, 0, Mips_GPRNMGPRegClassID);
DEFINE_DecodeMemNM(18, 0, Mips_GPRNMGPRegClassID);
DEFINE_DecodeMemNM(12, 0, Mips_GPRNM32RegClassID);
DEFINE_DecodeMemNM(9, 1, Mips_GPRNM32RegClassID);
static DecodeStatus DecodeMemZeroNM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned Base;
Base = fieldFromInstruction_4(Insn, 0, 5);
Base = getReg(Inst, Mips_GPRNM32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
return MCDisassembler_Success;
}
#define DEFINE_DecodeMemNMRX(RegClass) \
static DecodeStatus CONCAT(DecodeMemNMRX, RegClass)( \
MCInst * Inst, uint32_t Insn, uint64_t Address, \
const void *Decoder) \
{ \
unsigned Offset; \
unsigned Base; \
Offset = fieldFromInstruction_4(Insn, 0, 5); \
Base = fieldFromInstruction_4(Insn, 5, 5); \
\
Base = getReg(Inst, RegClass, Base); \
Offset = getReg(Inst, RegClass, Offset); \
MCOperand_CreateReg0(Inst, (Base)); \
MCOperand_CreateReg0(Inst, (Offset)); \
\
return MCDisassembler_Success; \
}
DEFINE_DecodeMemNMRX(Mips_GPRNM3RegClassID);
DEFINE_DecodeMemNMRX(Mips_GPRNM32RegClassID);
static DecodeStatus DecodeMemNM4x4(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = fieldFromInstruction_4(Insn, 0, 4);
unsigned Base;
Base = getReg(Inst, Mips_GPRNM32RegClassID,
fieldFromInstruction_4(Insn, 4, 5) & ~0x8);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemEVA(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn >> 7), 9);
unsigned Reg = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
if (MCInst_getOpcode(Inst) == Mips_SCE)
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
#include "MipsCP0RegisterMap.h"
static DecodeStatus DecodeCOP0SelRegisterClass(MCInst *Inst, unsigned RegNo,
uint64_t Address,
const void *Decoder)
{
int Reg = COP0Map_getEncIndexMap(RegNo);
if (Reg != -1) {
Reg = getReg(Inst, Mips_COP0SelRegClassID, Reg);
MCOperand_CreateReg0(Inst, (Reg));
} else {
// Not a named register encoding - print numeric register and select value
switch (MCInst_getOpcode(Inst)) {
case Mips_MFC0Sel_NM:
MCInst_setOpcode(Inst, (Mips_MFC0_NM));
break;
case Mips_MFHC0Sel_NM:
MCInst_setOpcode(Inst, (Mips_MFHC0_NM));
break;
case Mips_MTC0Sel_NM:
MCInst_setOpcode(Inst, (Mips_MTC0_NM));
break;
case Mips_MTHC0Sel_NM:
MCInst_setOpcode(Inst, (Mips_MTHC0_NM));
break;
default:
CS_ASSERT_RET_VAL(0 && "Unknown instruction!", MCDisassembler_Fail);
}
Reg = getReg(Inst, Mips_COP0RegClassID, RegNo >> 5);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateImm0(Inst, (RegNo & 0x1f));
}
return MCDisassembler_Success;
}
static DecodeStatus DecodeLoadByte15(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
unsigned Reg = fieldFromInstruction_4(Insn, 21, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeCacheOp(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Hint = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
MCOperand_CreateImm0(Inst, (Hint));
return MCDisassembler_Success;
}
static DecodeStatus DecodeCacheOpMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xfff), 12);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
unsigned Hint = fieldFromInstruction_4(Insn, 21, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
MCOperand_CreateImm0(Inst, (Hint));
return MCDisassembler_Success;
}
static DecodeStatus DecodePrefeOpMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0x1ff), 9);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
unsigned Hint = fieldFromInstruction_4(Insn, 21, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
MCOperand_CreateImm0(Inst, (Hint));
return MCDisassembler_Success;
}
static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn >> 7), 9);
unsigned Hint = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
MCOperand_CreateImm0(Inst, (Hint));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSyncI(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSyncI_MM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSynciR6(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Immediate = SignExtend32((Insn & 0xffff), 16);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Immediate));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMSA128Mem(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((fieldFromInstruction_4(Insn, 16, 10)), 10);
unsigned Reg = fieldFromInstruction_4(Insn, 6, 5);
unsigned Base = fieldFromInstruction_4(Insn, 11, 5);
Reg = getReg(Inst, Mips_MSA128BRegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (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 (MCInst_getOpcode(Inst)) {
default:
return MCDisassembler_Fail;
break;
case Mips_LD_B:
case Mips_ST_B:
MCOperand_CreateImm0(Inst, (Offset));
break;
case Mips_LD_H:
case Mips_ST_H:
MCOperand_CreateImm0(Inst, (Offset * 2));
break;
case Mips_LD_W:
case Mips_ST_W:
MCOperand_CreateImm0(Inst, (Offset * 4));
break;
case Mips_LD_D:
case Mips_ST_D:
MCOperand_CreateImm0(Inst, (Offset * 8));
break;
}
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMImm4(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned Offset = Insn & 0xf;
unsigned Reg = fieldFromInstruction_4(Insn, 7, 3);
unsigned Base = fieldFromInstruction_4(Insn, 4, 3);
switch (MCInst_getOpcode(Inst)) {
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_SB16_MMR6:
case Mips_SH16_MM:
case Mips_SH16_MMR6:
case Mips_SW16_MM:
case Mips_SW16_MMR6:
if (DecodeGPRMM16ZeroRegisterClass(
Inst, Reg, Address, Decoder) == MCDisassembler_Fail)
return MCDisassembler_Fail;
break;
}
if (DecodeGPRMM16RegisterClass(Inst, Base, Address, Decoder) ==
MCDisassembler_Fail)
return MCDisassembler_Fail;
switch (MCInst_getOpcode(Inst)) {
case Mips_LBU16_MM:
if (Offset == 0xf)
MCOperand_CreateImm0(Inst, (-1));
else
MCOperand_CreateImm0(Inst, (Offset));
break;
case Mips_SB16_MM:
case Mips_SB16_MMR6:
MCOperand_CreateImm0(Inst, (Offset));
break;
case Mips_LHU16_MM:
case Mips_SH16_MM:
case Mips_SH16_MMR6:
MCOperand_CreateImm0(Inst, (Offset << 1));
break;
case Mips_LW16_MM:
case Mips_SW16_MM:
case Mips_SW16_MMR6:
MCOperand_CreateImm0(Inst, (Offset << 2));
break;
}
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned Offset = Insn & 0x1F;
unsigned Reg = fieldFromInstruction_4(Insn, 5, 5);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Mips_SP));
MCOperand_CreateImm0(Inst, (Offset << 2));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned Offset = Insn & 0x7F;
unsigned Reg = fieldFromInstruction_4(Insn, 7, 3);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Mips_GP));
MCOperand_CreateImm0(Inst, (Offset << 2));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
int Offset;
switch (MCInst_getOpcode(Inst)) {
case Mips_LWM16_MMR6:
case Mips_SWM16_MMR6:
Offset = fieldFromInstruction_4(Insn, 4, 4);
break;
default:
Offset = SignExtend32((Insn & 0xf), 4);
break;
}
if (DecodeRegListOperand16(Inst, Insn, Address, Decoder) ==
MCDisassembler_Fail)
return MCDisassembler_Fail;
MCOperand_CreateReg0(Inst, (Mips_SP));
MCOperand_CreateImm0(Inst, (Offset << 2));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMImm9(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0x1ff), 9);
unsigned Reg = fieldFromInstruction_4(Insn, 21, 5);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
if (MCInst_getOpcode(Inst) == Mips_SCE_MM ||
MCInst_getOpcode(Inst) == Mips_SC_MMR6)
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMImm12(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0x0fff), 12);
unsigned Reg = fieldFromInstruction_4(Insn, 21, 5);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
switch (MCInst_getOpcode(Inst)) {
case Mips_SWM32_MM:
case Mips_LWM32_MM:
if (DecodeRegListOperand(Inst, Insn, Address, Decoder) ==
MCDisassembler_Fail)
return MCDisassembler_Fail;
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
break;
case Mips_SC_MM:
MCOperand_CreateReg0(Inst, (Reg));
// fall through
default:
MCOperand_CreateReg0(Inst, (Reg));
if (MCInst_getOpcode(Inst) == Mips_LWP_MM ||
MCInst_getOpcode(Inst) == Mips_SWP_MM)
MCOperand_CreateReg0(Inst, (Reg + 1));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
}
return MCDisassembler_Success;
}
static DecodeStatus DecodeMemMMImm16(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Reg = fieldFromInstruction_4(Insn, 21, 5);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
Reg = getReg(Inst, Mips_GPR32RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeFMem(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Reg = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Reg = getReg(Inst, Mips_FGR64RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeFMemMMR2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
// This function is the same as DecodeFMem but with the Reg and Base fields
// swapped according to microMIPS spec.
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
unsigned Reg = fieldFromInstruction_4(Insn, 21, 5);
Reg = getReg(Inst, Mips_FGR64RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeFMem2(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Reg = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Reg = getReg(Inst, Mips_COP2RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeFMem3(MCInst *Inst, uint32_t Insn, uint64_t Address,
const void *Decoder)
{
int Offset = SignExtend32((Insn & 0xffff), 16);
unsigned Reg = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Reg = getReg(Inst, Mips_COP3RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeFMemCop2R6(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0x07ff), 11);
unsigned Reg = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 11, 5);
Reg = getReg(Inst, Mips_COP2RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeFMemCop2MMR6(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Offset = SignExtend32((Insn & 0x07ff), 11);
unsigned Reg = fieldFromInstruction_4(Insn, 21, 5);
unsigned Base = fieldFromInstruction_4(Insn, 16, 5);
Reg = getReg(Inst, Mips_COP2RegClassID, Reg);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
MCOperand_CreateReg0(Inst, (Reg));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (Offset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSpecial3LlSc(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int64_t Offset = SignExtend64(((Insn >> 7) & 0x1ff), 9);
unsigned Rt = fieldFromInstruction_4(Insn, 16, 5);
unsigned Base = fieldFromInstruction_4(Insn, 21, 5);
Rt = getReg(Inst, Mips_GPR32RegClassID, Rt);
Base = getReg(Inst, Mips_GPR32RegClassID, Base);
if (MCInst_getOpcode(Inst) == Mips_SC_R6 ||
MCInst_getOpcode(Inst) == Mips_SCD_R6) {
MCOperand_CreateReg0(Inst, (Rt));
}
MCOperand_CreateReg0(Inst, (Rt));
MCOperand_CreateReg0(Inst, (Base));
MCOperand_CreateImm0(Inst, (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;
MCOperand_CreateReg0(Inst, (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(Inst, Mips_AFGR64RegClassID, RegNo / 2);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_ACC64DSPRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_HI32DSPRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_LO32DSPRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_MSA128BRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_MSA128HRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_MSA128WRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_MSA128DRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_MSACtrlRegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_COP0RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (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(Inst, Mips_COP2RegClassID, RegNo);
MCOperand_CreateReg0(Inst, (Reg));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget(MCInst *Inst, unsigned Offset,
uint64_t Address, const void *Decoder)
{
int32_t BranchOffset = (SignExtend32((Offset), 16) * 4) + 4;
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget1SImm16(MCInst *Inst, unsigned Offset,
uint64_t Address,
const void *Decoder)
{
int32_t BranchOffset = (SignExtend32((Offset), 16) * 2);
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeJumpTarget(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned JumpOffset = fieldFromInstruction_4(Insn, 0, 26) << 2;
MCOperand_CreateImm0(Inst, (JumpOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget21(MCInst *Inst, unsigned Offset,
uint64_t Address, const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset), 21) * 4 + 4;
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget21MM(MCInst *Inst, unsigned Offset,
uint64_t Address,
const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset), 21) * 4 + 4;
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget26(MCInst *Inst, unsigned Offset,
uint64_t Address, const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset), 26) * 4 + 4;
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget7MM(MCInst *Inst, unsigned Offset,
uint64_t Address, const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset << 1), 8);
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget10MM(MCInst *Inst, unsigned Offset,
uint64_t Address,
const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset << 1), 11);
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTargetMM(MCInst *Inst, unsigned Offset,
uint64_t Address, const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset), 16) * 2 + 4;
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBranchTarget26MM(MCInst *Inst, unsigned Offset,
uint64_t Address,
const void *Decoder)
{
int32_t BranchOffset = SignExtend32((Offset << 1), 27);
MCOperand_CreateImm0(Inst, (BranchOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeJumpTargetMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned JumpOffset = fieldFromInstruction_4(Insn, 0, 26) << 1;
MCOperand_CreateImm0(Inst, (JumpOffset));
return MCDisassembler_Success;
}
#define DEFINE_DecodeBranchTargetNM(Bits) \
static DecodeStatus CONCAT(DecodeBranchTargetNM, Bits)( \
MCInst * Inst, unsigned Offset, uint64_t Address, \
const void *Decoder) \
{ \
uint32_t InsnSize = (Bits <= 10) ? 2 : 4; \
int32_t BranchOffset = \
SignExtend32((Offset), Bits + 1) + InsnSize; \
\
MCOperand_CreateImm0(Inst, (BranchOffset)); \
return MCDisassembler_Success; \
}
DEFINE_DecodeBranchTargetNM(10);
DEFINE_DecodeBranchTargetNM(7);
DEFINE_DecodeBranchTargetNM(21);
DEFINE_DecodeBranchTargetNM(25);
DEFINE_DecodeBranchTargetNM(14);
DEFINE_DecodeBranchTargetNM(11);
DEFINE_DecodeBranchTargetNM(5);
static DecodeStatus DecodeJumpTargetXMM(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned JumpOffset = fieldFromInstruction_4(Insn, 0, 26) << 2;
MCOperand_CreateImm0(Inst, (JumpOffset));
return MCDisassembler_Success;
}
static DecodeStatus DecodeAddiur2Simm7(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder)
{
if (Value == 0)
MCOperand_CreateImm0(Inst, (1));
else if (Value == 0x7)
MCOperand_CreateImm0(Inst, (-1));
else
MCOperand_CreateImm0(Inst, (Value << 2));
return MCDisassembler_Success;
}
static DecodeStatus DecodeLi16Imm(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder)
{
if (Value == 0x7F)
MCOperand_CreateImm0(Inst, (-1));
else
MCOperand_CreateImm0(Inst, (Value));
return MCDisassembler_Success;
}
static DecodeStatus DecodePOOL16BEncodedField(MCInst *Inst, unsigned Value,
uint64_t Address,
const void *Decoder)
{
MCOperand_CreateImm0(Inst, (Value == 0x0 ? 8 : Value));
return MCDisassembler_Success;
}
#define DEFINE_DecodeUImmWithOffsetAndScale(Bits, Offset, Scale) \
static DecodeStatus CONCAT(DecodeUImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, Scale)))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder) \
{ \
Value &= ((1 << Bits) - 1); \
Value *= Scale; \
MCOperand_CreateImm0(Inst, (Value + Offset)); \
return MCDisassembler_Success; \
}
DEFINE_DecodeUImmWithOffsetAndScale(5, 0, 4);
DEFINE_DecodeUImmWithOffsetAndScale(6, 0, 4);
DEFINE_DecodeUImmWithOffsetAndScale(2, 1, 1);
DEFINE_DecodeUImmWithOffsetAndScale(5, 1, 1);
DEFINE_DecodeUImmWithOffsetAndScale(8, 0, 1);
DEFINE_DecodeUImmWithOffsetAndScale(18, 0, 1);
DEFINE_DecodeUImmWithOffsetAndScale(21, 0, 1);
#define DEFINE_DecodeSImmWithOffsetAndScale(Bits, Offset, ScaleBy) \
static DecodeStatus CONCAT(DecodeSImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, ScaleBy)))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder) \
{ \
int32_t Imm = SignExtend32((Value), Bits) * ScaleBy; \
MCOperand_CreateImm0(Inst, (Imm + Offset)); \
return MCDisassembler_Success; \
}
#define DEFINE_DecodeSImmWithOffsetAndScale_2(Bits, Offset) DEFINE_DecodeSImmWithOffsetAndScale(Bits, Offset, 1)
#define DEFINE_DecodeSImmWithOffsetAndScale_3(Bits) DEFINE_DecodeSImmWithOffsetAndScale(Bits, 0, 1)
DEFINE_DecodeSImmWithOffsetAndScale_3(16);
DEFINE_DecodeSImmWithOffsetAndScale_3(10);
DEFINE_DecodeSImmWithOffsetAndScale_3(4);
DEFINE_DecodeSImmWithOffsetAndScale_3(6);
DEFINE_DecodeSImmWithOffsetAndScale_3(32);
static DecodeStatus DecodeInsSize(MCInst *Inst, uint32_t Insn, 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 = MCOperand_getImm(MCInst_getOperand(Inst, (2)));
int Size = (int)Insn - Pos + 1;
MCOperand_CreateImm0(Inst, (SignExtend32((Size), 16)));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSimm19Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
MCOperand_CreateImm0(Inst, (SignExtend32((Insn), 19) * 4));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSimm18Lsl3(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
MCOperand_CreateImm0(Inst, (SignExtend32((Insn), 18) * 8));
return MCDisassembler_Success;
}
static DecodeStatus DecodeSimm9SP(MCInst *Inst, uint32_t 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((Insn), 9);
break;
}
MCOperand_CreateImm0(Inst, (DecodedValue * 4));
return MCDisassembler_Success;
}
static DecodeStatus DecodeANDI16Imm(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
// Insn must be >= 0, since it is unsigned that condition is always true.
int32_t DecodedValues[] = { 128, 1, 2, 3, 4, 7, 8, 15,
16, 31, 32, 63, 64, 255, 32768, 65535 };
MCOperand_CreateImm0(Inst, (DecodedValues[Insn]));
return MCDisassembler_Success;
}
static DecodeStatus DecodeRegListOperand(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned Regs[] = { Mips_S0, Mips_S1, Mips_S2, Mips_S3, Mips_S4,
Mips_S5, Mips_S6, Mips_S7, Mips_FP };
unsigned RegNum;
unsigned RegLst = fieldFromInstruction_4(Insn, 21, 5);
// Empty register lists are not allowed.
if (RegLst == 0)
return MCDisassembler_Fail;
RegNum = RegLst & 0xf;
// RegLst values 10-15, and 26-31 are reserved.
if (RegNum > 9)
return MCDisassembler_Fail;
for (unsigned i = 0; i < RegNum; i++)
MCOperand_CreateReg0(Inst, (Regs[i]));
if (RegLst & 0x10)
MCOperand_CreateReg0(Inst, (Mips_RA));
return MCDisassembler_Success;
}
static DecodeStatus DecodeRegListOperand16(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
unsigned Regs[] = { Mips_S0, Mips_S1, Mips_S2, Mips_S3 };
unsigned RegLst;
switch (MCInst_getOpcode(Inst)) {
default:
RegLst = fieldFromInstruction_4(Insn, 4, 2);
break;
case Mips_LWM16_MMR6:
case Mips_SWM16_MMR6:
RegLst = fieldFromInstruction_4(Insn, 8, 2);
break;
}
unsigned RegNum = RegLst & 0x3;
for (unsigned i = 0; i <= RegNum; i++)
MCOperand_CreateReg0(Inst, (Regs[i]));
MCOperand_CreateReg0(Inst, (Mips_RA));
return MCDisassembler_Success;
}
static DecodeStatus DecodeMovePOperands(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
unsigned RegPair = fieldFromInstruction_4(Insn, 7, 3);
if (DecodeMovePRegPair(Inst, RegPair, Address, Decoder) ==
MCDisassembler_Fail)
return MCDisassembler_Fail;
unsigned RegRs;
if (Inst->csh->mode & CS_MODE_MIPS32R6)
RegRs = fieldFromInstruction_4(Insn, 0, 2) |
(fieldFromInstruction_4(Insn, 3, 1) << 2);
else
RegRs = fieldFromInstruction_4(Insn, 1, 3);
if (DecodeGPRMM16MovePRegisterClass(Inst, RegRs, Address, Decoder) ==
MCDisassembler_Fail)
return MCDisassembler_Fail;
unsigned RegRt = fieldFromInstruction_4(Insn, 4, 3);
if (DecodeGPRMM16MovePRegisterClass(Inst, RegRt, Address, Decoder) ==
MCDisassembler_Fail)
return MCDisassembler_Fail;
return MCDisassembler_Success;
}
static DecodeStatus DecodeMovePRegPair(MCInst *Inst, unsigned RegPair,
uint64_t Address, const void *Decoder)
{
switch (RegPair) {
default:
return MCDisassembler_Fail;
case 0:
MCOperand_CreateReg0(Inst, (Mips_A1));
MCOperand_CreateReg0(Inst, (Mips_A2));
break;
case 1:
MCOperand_CreateReg0(Inst, (Mips_A1));
MCOperand_CreateReg0(Inst, (Mips_A3));
break;
case 2:
MCOperand_CreateReg0(Inst, (Mips_A2));
MCOperand_CreateReg0(Inst, (Mips_A3));
break;
case 3:
MCOperand_CreateReg0(Inst, (Mips_A0));
MCOperand_CreateReg0(Inst, (Mips_S5));
break;
case 4:
MCOperand_CreateReg0(Inst, (Mips_A0));
MCOperand_CreateReg0(Inst, (Mips_S6));
break;
case 5:
MCOperand_CreateReg0(Inst, (Mips_A0));
MCOperand_CreateReg0(Inst, (Mips_A1));
break;
case 6:
MCOperand_CreateReg0(Inst, (Mips_A0));
MCOperand_CreateReg0(Inst, (Mips_A2));
break;
case 7:
MCOperand_CreateReg0(Inst, (Mips_A0));
MCOperand_CreateReg0(Inst, (Mips_A3));
break;
}
return MCDisassembler_Success;
}
static DecodeStatus DecodeSimm23Lsl2(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
MCOperand_CreateImm0(Inst, (SignExtend32((Insn << 2), 25)));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder)
{
// We have:
// 0b000111 ttttt sssss iiiiiiiiiiiiiiii
// Invalid if rt == 0
// BGTZALC_MMR6 if rs == 0 && rt != 0
// BLTZALC_MMR6 if rs != 0 && rs == rt
// BLTUC_MMR6 if rs != 0 && rs != rt
uint32_t Rt = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
uint32_t Imm = 0;
bool HasRs = false;
bool HasRt = false;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0) {
MCInst_setOpcode(MI, (Mips_BGTZALC_MMR6));
HasRt = true;
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
} else if (Rs == Rt) {
MCInst_setOpcode(MI, (Mips_BLTZALC_MMR6));
HasRs = true;
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
} else {
MCInst_setOpcode(MI, (Mips_BLTUC_MMR6));
HasRs = true;
HasRt = true;
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
4 +
4;
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
if (HasRt)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst *MI, uint32_t insn,
uint64_t Address,
const void *Decoder)
{
// We have:
// 0b000110 ttttt sssss iiiiiiiiiiiiiiii
// Invalid if rt == 0
// BLEZALC_MMR6 if rs == 0 && rt != 0
// BGEZALC_MMR6 if rs == rt && rt != 0
// BGEUC_MMR6 if rs != rt && rs != 0 && rt != 0
uint32_t Rt = fieldFromInstruction_4(insn, 21, 5);
uint32_t Rs = fieldFromInstruction_4(insn, 16, 5);
uint32_t Imm = 0;
bool HasRs = false;
if (Rt == 0)
return MCDisassembler_Fail;
else if (Rs == 0) {
MCInst_setOpcode(MI, (Mips_BLEZALC_MMR6));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
} else if (Rs == Rt) {
MCInst_setOpcode(MI, (Mips_BGEZALC_MMR6));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
2 +
4;
} else {
HasRs = true;
MCInst_setOpcode(MI, (Mips_BGEUC_MMR6));
Imm = SignExtend64(fieldFromInstruction_4(insn, 0, 16), 16) *
4 +
4;
}
if (HasRs)
MCOperand_CreateReg0(
MI, (getReg(MI, Mips_GPR32RegClassID, Rs)));
MCOperand_CreateReg0(MI, (getReg(MI, Mips_GPR32RegClassID, Rt)));
MCOperand_CreateImm0(MI, (Imm));
return MCDisassembler_Success;
}
// This instruction does not have a working decoder, and needs to be
// fixed. This "fixme" function was introduced to keep the backend compiling,
// while making changes to tablegen code.
static DecodeStatus DecodeFIXMEInstruction(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
return MCDisassembler_Fail;
}
static DecodeStatus DecodeImmM1To126(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder)
{
if (Value == 127)
MCOperand_CreateImm0(Inst, (-1));
else
MCOperand_CreateImm0(Inst, (Value));
return MCDisassembler_Success;
}
static DecodeStatus DecodeUImm4Mask(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder)
{
if (Value == 12)
MCOperand_CreateImm0(Inst, (0xff));
else if (Value == 13)
MCOperand_CreateImm0(Inst, (0xffff));
else
MCOperand_CreateImm0(Inst, (Value));
return MCDisassembler_Success;
}
static DecodeStatus DecodeUImm3Shift(MCInst *Inst, unsigned Value,
uint64_t Address, const void *Decoder)
{
if (Value == 0)
MCOperand_CreateImm0(Inst, (8));
else
MCOperand_CreateImm0(Inst, (Value));
return MCDisassembler_Success;
}
static DecodeStatus DecodeNMRegListOperand(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
unsigned RegStart = fieldFromInstruction_4(Insn, 5, 5);
unsigned RegCount = fieldFromInstruction_4(Insn, 1, 4);
unsigned GP_bit = fieldFromInstruction_4(Insn, 0, 1);
unsigned i;
unsigned RegNo;
MCOperand_CreateReg0(
Inst, (getReg(Inst, Mips_GPRNM32RegClassID, RegStart)));
for (i = RegStart + 1; i < RegStart + RegCount; i++) {
if (i == RegStart + RegCount - 1 && GP_bit)
RegNo = 28;
else if (i > 31)
RegNo = 16 + (i % 32); // $ra+1 wraps to $s0
else
RegNo = i;
MCOperand_CreateReg0(
Inst, (getReg(Inst, Mips_GPRNM32RegClassID, RegNo)));
}
return MCDisassembler_Success;
}
static DecodeStatus DecodeNMRegList16Operand(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
unsigned RegStart = 30 + fieldFromInstruction_4(Insn, 4, 1);
unsigned RegCount = fieldFromInstruction_4(Insn, 0, 4);
// Re-encode the parameters for 32-bit instruction operand
// and call it's decoder
return DecodeNMRegListOperand(Inst, (RegStart << 5) | (RegCount << 1),
Address, Decoder);
}
static DecodeStatus DecodeNegImm12(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
int Imm = fieldFromInstruction_4(Insn, 0, 12);
MCOperand_CreateImm0(Inst, (-Imm));
return MCDisassembler_Success;
}
#define DEFINE_DecodeSImmWithReg(Bits, Offset, Scale, RegNum) \
static DecodeStatus CONCAT( \
DecodeSImmWithReg, \
CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder) \
{ \
MCOperand_CreateReg0(Inst, (RegNum)); \
return CONCAT(DecodeSImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, Scale)))( \
Inst, Value, Address, Decoder); \
}
DEFINE_DecodeSImmWithReg(32, 0, 1, Mips_GP_NM);
#define DEFINE_DecodeUImmWithReg(Bits, Offset, Scale, RegNum) \
static DecodeStatus CONCAT( \
DecodeUImmWithReg, \
CONCAT(Bits, CONCAT(Offset, CONCAT(Scale, RegNum))))( \
MCInst * Inst, unsigned Value, uint64_t Address, \
const void *Decoder) \
{ \
MCOperand_CreateReg0(Inst, (RegNum)); \
return CONCAT(DecodeUImmWithOffsetAndScale, \
CONCAT(Bits, CONCAT(Offset, Scale)))( \
Inst, Value, Address, Decoder); \
}
DEFINE_DecodeUImmWithReg(8, 0, 1, Mips_SP_NM);
DEFINE_DecodeUImmWithReg(21, 0, 1, Mips_GP_NM);
DEFINE_DecodeUImmWithReg(18, 0, 1, Mips_GP_NM);
static DecodeStatus DecodeSImm32s12(MCInst *Inst, uint32_t Insn,
uint64_t Address, const void *Decoder)
{
uint64_t Imm = ((uint64_t)Insn) << 12;
MCOperand_CreateImm0(Inst, (Imm));
return MCDisassembler_Success;
}
#define DEFINE_DecodeAddressPCRelNM(Bits) \
static DecodeStatus CONCAT(DecodeAddressPCRelNM, Bits)( \
MCInst * Inst, unsigned Offset, uint64_t Address, \
const void *Decoder) \
{ \
uint32_t InsnSize = Bits == 32 ? 6 : 4; \
int32_t BranchOffset = \
SignExtend32((Offset), Bits) + InsnSize; \
\
MCOperand_CreateImm0(Inst, (BranchOffset)); \
return MCDisassembler_Success; \
}
DEFINE_DecodeAddressPCRelNM(22);
DEFINE_DecodeAddressPCRelNM(32);
static DecodeStatus DecodeBranchConflictNM(MCInst *Inst, uint32_t Insn,
uint64_t Address,
const void *Decoder)
{
unsigned Rt = fieldFromInstruction_4(Insn, 7, 3);
unsigned Rs = fieldFromInstruction_4(Insn, 4, 3);
unsigned Offset = fieldFromInstruction_4(Insn, 0, 4) << 1;
if (Rs < Rt)
MCInst_setOpcode(Inst, (Mips_BEQC16_NM));
else
MCInst_setOpcode(Inst, (Mips_BNEC16_NM));
if (DecodeGPRNM3RegisterClass(Inst, Rt, Address, Decoder) ==
MCDisassembler_Success &&
DecodeGPRNM3RegisterClass(Inst, Rs, Address, Decoder) ==
MCDisassembler_Success)
return CONCAT(DecodeBranchTargetNM, 5)(Inst, Offset, Address,
Decoder);
else
return MCDisassembler_Fail;
}
DecodeStatus Mips_LLVM_getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes,
size_t BytesLen, uint64_t Address, SStream *CStream)
{
return getInstruction(Instr, Size, Bytes, BytesLen, Address, CStream);
}