| //===------ 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 "../../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, sizeof(cs_detail)); |
| } |
| |
| 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 |