You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
497 lines
13 KiB
497 lines
13 KiB
//===------ SparcDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===// |
|
// |
|
// The LLVM Compiler Infrastructure |
|
// |
|
// This file is distributed under the University of Illinois Open Source |
|
// License. See LICENSE.TXT for details. |
|
// |
|
//===----------------------------------------------------------------------===// |
|
|
|
/* Capstone Disassembly Engine */ |
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */ |
|
|
|
#ifdef CAPSTONE_HAS_SPARC |
|
|
|
#include <stdio.h> // DEBUG |
|
#include <stdlib.h> |
|
#include <string.h> |
|
|
|
#include "../../cs_priv.h" |
|
|
|
#include "../../MCInst.h" |
|
#include "../../MCInstrDesc.h" |
|
#include "../../MCFixedLenDisassembler.h" |
|
#include "../../MCRegisterInfo.h" |
|
#include "../../MCDisassembler.h" |
|
#include "../../MathExtras.h" |
|
|
|
|
|
#define GET_REGINFO_MC_DESC |
|
#define GET_REGINFO_ENUM |
|
#include "SparcGenRegisterInfo.inc" |
|
static const unsigned IntRegDecoderTable[] = { |
|
SP_G0, SP_G1, SP_G2, SP_G3, |
|
SP_G4, SP_G5, SP_G6, SP_G7, |
|
SP_O0, SP_O1, SP_O2, SP_O3, |
|
SP_O4, SP_O5, SP_O6, SP_O7, |
|
SP_L0, SP_L1, SP_L2, SP_L3, |
|
SP_L4, SP_L5, SP_L6, SP_L7, |
|
SP_I0, SP_I1, SP_I2, SP_I3, |
|
SP_I4, SP_I5, SP_I6, SP_I7 |
|
}; |
|
|
|
static const unsigned FPRegDecoderTable[] = { |
|
SP_F0, SP_F1, SP_F2, SP_F3, |
|
SP_F4, SP_F5, SP_F6, SP_F7, |
|
SP_F8, SP_F9, SP_F10, SP_F11, |
|
SP_F12, SP_F13, SP_F14, SP_F15, |
|
SP_F16, SP_F17, SP_F18, SP_F19, |
|
SP_F20, SP_F21, SP_F22, SP_F23, |
|
SP_F24, SP_F25, SP_F26, SP_F27, |
|
SP_F28, SP_F29, SP_F30, SP_F31 |
|
}; |
|
|
|
static const unsigned DFPRegDecoderTable[] = { |
|
SP_D0, SP_D16, SP_D1, SP_D17, |
|
SP_D2, SP_D18, SP_D3, SP_D19, |
|
SP_D4, SP_D20, SP_D5, SP_D21, |
|
SP_D6, SP_D22, SP_D7, SP_D23, |
|
SP_D8, SP_D24, SP_D9, SP_D25, |
|
SP_D10, SP_D26, SP_D11, SP_D27, |
|
SP_D12, SP_D28, SP_D13, SP_D29, |
|
SP_D14, SP_D30, SP_D15, SP_D31 |
|
}; |
|
|
|
static const unsigned QFPRegDecoderTable[] = { |
|
SP_Q0, SP_Q8, ~0U, ~0U, |
|
SP_Q1, SP_Q9, ~0U, ~0U, |
|
SP_Q2, SP_Q10, ~0U, ~0U, |
|
SP_Q3, SP_Q11, ~0U, ~0U, |
|
SP_Q4, SP_Q12, ~0U, ~0U, |
|
SP_Q5, SP_Q13, ~0U, ~0U, |
|
SP_Q6, SP_Q14, ~0U, ~0U, |
|
SP_Q7, SP_Q15, ~0U, ~0U |
|
}; |
|
|
|
static const unsigned FCCRegDecoderTable[] = { |
|
SP_FCC0, SP_FCC1, SP_FCC2, SP_FCC3 |
|
}; |
|
|
|
static uint64_t getFeatureBits(int mode) |
|
{ |
|
// support everything |
|
return (uint64_t)-1; |
|
} |
|
|
|
static DecodeStatus DecodeIntRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned Reg; |
|
|
|
if (RegNo > 31) |
|
return MCDisassembler_Fail; |
|
|
|
Reg = IntRegDecoderTable[RegNo]; |
|
MCInst_addOperand(Inst, MCOperand_CreateReg(Reg)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeI64RegsRegisterClass(MCInst *Inst, unsigned RegNo, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned Reg; |
|
|
|
if (RegNo > 31) |
|
return MCDisassembler_Fail; |
|
|
|
Reg = IntRegDecoderTable[RegNo]; |
|
MCInst_addOperand(Inst, MCOperand_CreateReg(Reg)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned Reg; |
|
|
|
if (RegNo > 31) |
|
return MCDisassembler_Fail; |
|
|
|
Reg = FPRegDecoderTable[RegNo]; |
|
MCInst_addOperand(Inst, MCOperand_CreateReg(Reg)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeDFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned Reg; |
|
|
|
if (RegNo > 31) |
|
return MCDisassembler_Fail; |
|
|
|
Reg = DFPRegDecoderTable[RegNo]; |
|
MCInst_addOperand(Inst, MCOperand_CreateReg(Reg)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeQFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned Reg; |
|
|
|
if (RegNo > 31) |
|
return MCDisassembler_Fail; |
|
|
|
Reg = QFPRegDecoderTable[RegNo]; |
|
if (Reg == ~0U) |
|
return MCDisassembler_Fail; |
|
|
|
MCInst_addOperand(Inst, MCOperand_CreateReg(Reg)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeFCCRegsRegisterClass(MCInst *Inst, unsigned RegNo, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
if (RegNo > 3) |
|
return MCDisassembler_Fail; |
|
|
|
MCInst_addOperand(Inst, MCOperand_CreateReg(FCCRegDecoderTable[RegNo])); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
|
|
static DecodeStatus DecodeLoadInt(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
static DecodeStatus DecodeLoadFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
static DecodeStatus DecodeLoadDFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
static DecodeStatus DecodeLoadQFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
static DecodeStatus DecodeStoreInt(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder); |
|
static DecodeStatus DecodeStoreFP(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder); |
|
static DecodeStatus DecodeStoreDFP(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder); |
|
static DecodeStatus DecodeStoreQFP(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder); |
|
static DecodeStatus DecodeCall(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder); |
|
static DecodeStatus DecodeSIMM13(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder); |
|
static DecodeStatus DecodeJMPL(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
static DecodeStatus DecodeReturn(MCInst *MI, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
static DecodeStatus DecodeSWAP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
|
|
|
|
#define GET_SUBTARGETINFO_ENUM |
|
#include "SparcGenSubtargetInfo.inc" |
|
#include "SparcGenDisassemblerTables.inc" |
|
|
|
/// readInstruction - read four bytes and return 32 bit word. |
|
static DecodeStatus readInstruction32(const uint8_t *code, size_t len, uint32_t *Insn) |
|
{ |
|
uint8_t Bytes[4]; |
|
|
|
if (len < 4) |
|
// not enough data |
|
return MCDisassembler_Fail; |
|
|
|
memcpy(Bytes, code, 4); |
|
|
|
// Encoded as a big-endian 32-bit word in the stream. |
|
*Insn = (Bytes[3] << 0) | |
|
(Bytes[2] << 8) | |
|
(Bytes[1] << 16) | |
|
(Bytes[0] << 24); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
bool Sparc_getInstruction(csh ud, const uint8_t *code, size_t code_len, MCInst *MI, |
|
uint16_t *size, uint64_t address, void *info) |
|
{ |
|
uint32_t Insn; |
|
DecodeStatus Result; |
|
|
|
Result = readInstruction32(code, code_len, &Insn); |
|
if (Result == MCDisassembler_Fail) |
|
return MCDisassembler_Fail; |
|
|
|
Result = decodeInstruction_4(DecoderTableSparc32, MI, Insn, address, |
|
(MCRegisterInfo *)info, 0); |
|
if (Result != MCDisassembler_Fail) { |
|
*size = 4; |
|
return Result; |
|
} |
|
|
|
return MCDisassembler_Fail; |
|
} |
|
|
|
typedef DecodeStatus (*DecodeFunc)(MCInst *MI, unsigned insn, uint64_t Address, |
|
const void *Decoder); |
|
|
|
static DecodeStatus DecodeMem(MCInst *MI, unsigned insn, uint64_t Address, |
|
const void *Decoder, |
|
bool isLoad, DecodeFunc DecodeRD) |
|
{ |
|
DecodeStatus status; |
|
unsigned rd = fieldFromInstruction_4(insn, 25, 5); |
|
unsigned rs1 = fieldFromInstruction_4(insn, 14, 5); |
|
bool isImm = fieldFromInstruction_4(insn, 13, 1); |
|
unsigned rs2 = 0; |
|
unsigned simm13 = 0; |
|
|
|
if (isImm) |
|
simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13); |
|
else |
|
rs2 = fieldFromInstruction_4(insn, 0, 5); |
|
|
|
if (isLoad) { |
|
status = DecodeRD(MI, rd, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
} |
|
|
|
// Decode rs1. |
|
status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
|
|
// Decode imm|rs2. |
|
if (isImm) |
|
MCInst_addOperand(MI, MCOperand_CreateImm(simm13)); |
|
else { |
|
status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
} |
|
|
|
if (!isLoad) { |
|
status = DecodeRD(MI, rd, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
} |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeLoadInt(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, true, |
|
DecodeIntRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeLoadFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, true, |
|
DecodeFPRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeLoadDFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, true, |
|
DecodeDFPRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeLoadQFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, true, |
|
DecodeQFPRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeStoreInt(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, false, |
|
DecodeIntRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeStoreFP(MCInst *Inst, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, false, |
|
DecodeFPRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeStoreDFP(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, false, |
|
DecodeDFPRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeStoreQFP(MCInst *Inst, unsigned insn, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
return DecodeMem(Inst, insn, Address, Decoder, false, |
|
DecodeQFPRegsRegisterClass); |
|
} |
|
|
|
static DecodeStatus DecodeCall(MCInst *MI, unsigned insn, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned tgt = fieldFromInstruction_4(insn, 0, 30); |
|
tgt <<= 2; |
|
|
|
MCInst_addOperand(MI, MCOperand_CreateImm(tgt)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeSIMM13(MCInst *MI, unsigned insn, |
|
uint64_t Address, const void *Decoder) |
|
{ |
|
unsigned tgt = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13); |
|
|
|
MCInst_addOperand(MI, MCOperand_CreateImm(tgt)); |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeJMPL(MCInst *MI, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
DecodeStatus status; |
|
unsigned rd = fieldFromInstruction_4(insn, 25, 5); |
|
unsigned rs1 = fieldFromInstruction_4(insn, 14, 5); |
|
unsigned isImm = fieldFromInstruction_4(insn, 13, 1); |
|
unsigned rs2 = 0; |
|
unsigned simm13 = 0; |
|
|
|
if (isImm) |
|
simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13); |
|
else |
|
rs2 = fieldFromInstruction_4(insn, 0, 5); |
|
|
|
// Decode RD. |
|
status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
|
|
// Decode RS1. |
|
status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
|
|
// Decode RS1 | SIMM13. |
|
if (isImm) |
|
MCInst_addOperand(MI, MCOperand_CreateImm(simm13)); |
|
else { |
|
status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
} |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeReturn(MCInst *MI, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
DecodeStatus status; |
|
unsigned rs1 = fieldFromInstruction_4(insn, 14, 5); |
|
unsigned isImm = fieldFromInstruction_4(insn, 13, 1); |
|
unsigned rs2 = 0; |
|
unsigned simm13 = 0; |
|
if (isImm) |
|
simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13); |
|
else |
|
rs2 = fieldFromInstruction_4(insn, 0, 5); |
|
|
|
// Decode RS1. |
|
status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
|
|
// Decode RS2 | SIMM13. |
|
if (isImm) |
|
MCInst_addOperand(MI, MCOperand_CreateImm(simm13)); |
|
else { |
|
status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
} |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
static DecodeStatus DecodeSWAP(MCInst *MI, unsigned insn, uint64_t Address, |
|
const void *Decoder) |
|
{ |
|
DecodeStatus status; |
|
unsigned rd = fieldFromInstruction_4(insn, 25, 5); |
|
unsigned rs1 = fieldFromInstruction_4(insn, 14, 5); |
|
unsigned isImm = fieldFromInstruction_4(insn, 13, 1); |
|
unsigned rs2 = 0; |
|
unsigned simm13 = 0; |
|
|
|
if (isImm) |
|
simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13); |
|
else |
|
rs2 = fieldFromInstruction_4(insn, 0, 5); |
|
|
|
// Decode RD. |
|
status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
|
|
// Decode RS1. |
|
status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
|
|
// Decode RS1 | SIMM13. |
|
if (isImm) |
|
MCInst_addOperand(MI, MCOperand_CreateImm(simm13)); |
|
else { |
|
status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder); |
|
if (status != MCDisassembler_Success) |
|
return status; |
|
} |
|
|
|
return MCDisassembler_Success; |
|
} |
|
|
|
void Sparc_init(MCRegisterInfo *MRI) |
|
{ |
|
/* |
|
InitMCRegisterInfo(SparcRegDesc, 119, RA, PC, |
|
SparcMCRegisterClasses, 8, |
|
SparcRegUnitRoots, |
|
86, |
|
SparcRegDiffLists, |
|
SparcRegStrings, |
|
SparcSubRegIdxLists, |
|
7, |
|
SparcSubRegIdxRanges, |
|
SparcRegEncodingTable); |
|
*/ |
|
|
|
MCRegisterInfo_InitMCRegisterInfo(MRI, SparcRegDesc, 119, |
|
0, 0, |
|
SparcMCRegisterClasses, 8, |
|
0, 0, |
|
SparcRegDiffLists, |
|
0, |
|
SparcSubRegIdxLists, 7, |
|
0); |
|
} |
|
|
|
#endif
|
|
|