diff options
Diffstat (limited to 'capstone/arch/Sparc/SparcDisassembler.c')
-rw-r--r-- | capstone/arch/Sparc/SparcDisassembler.c | 500 |
1 files changed, 500 insertions, 0 deletions
diff --git a/capstone/arch/Sparc/SparcDisassembler.c b/capstone/arch/Sparc/SparcDisassembler.c new file mode 100644 index 000000000..3e6d0e0b9 --- /dev/null +++ b/capstone/arch/Sparc/SparcDisassembler.c @@ -0,0 +1,500 @@ +//===------ 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-2015 */ + +#ifdef CAPSTONE_HAS_SPARC + +#include <stdio.h> // DEBUG +#include <stdlib.h> +#include <string.h> + +#include "../../cs_priv.h" +#include "../../utils.h" + +#include "SparcDisassembler.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]; + MCOperand_CreateReg0(Inst, 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]; + MCOperand_CreateReg0(Inst, 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]; + MCOperand_CreateReg0(Inst, 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]; + MCOperand_CreateReg0(Inst, 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; + + MCOperand_CreateReg0(Inst, Reg); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeFCCRegsRegisterClass(MCInst *Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) +{ + if (RegNo > 3) + return MCDisassembler_Fail; + + MCOperand_CreateReg0(Inst, 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) +{ + if (len < 4) + // not enough data + return MCDisassembler_Fail; + + // Encoded as a big-endian 32-bit word in the stream. + *Insn = (code[3] << 0) | + (code[2] << 8) | + (code[1] << 16) | + ((uint32_t) code[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 false; + + if (MI->flat_insn->detail) { + memset(MI->flat_insn->detail, 0, offsetof(cs_detail, sparc)+sizeof(cs_sparc)); + } + + Result = decodeInstruction_4(DecoderTableSparc32, MI, Insn, address, + (MCRegisterInfo *)info, 0); + if (Result != MCDisassembler_Fail) { + *size = 4; + return true; + } + + return false; +} + +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) != 0; + 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) + MCOperand_CreateImm0(MI, 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; + + MCOperand_CreateImm0(MI, 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); + + MCOperand_CreateImm0(MI, 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) + MCOperand_CreateImm0(MI, 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) + MCOperand_CreateImm0(MI, 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) + MCOperand_CreateImm0(MI, 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 |