//===------ 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 "../../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) { 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 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