/* Capstone Disassembly Engine, http://www.capstone-engine.org */ /* By Nguyen Anh Quynh , 2013-2022, */ /* Rot127 2022-2023 */ /* Automatically translated source file from LLVM. */ /* LLVM-commit: */ /* LLVM-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 */ //===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- C++ -*-===// // // 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 Sparc Disassembler. // //===----------------------------------------------------------------------===// #include #include #include #include #include "../../MCDisassembler.h" #include "../../MCFixedLenDisassembler.h" #include "SparcDisassemblerExtension.h" #include "SparcLinkage.h" #include "SparcMapping.h" #include "SparcMCTargetDesc.h" #define CONCAT(a, b) CONCAT_(a, b) #define CONCAT_(a, b) a##_##b #define DEBUG_TYPE "sparc-disassembler" static const unsigned IntRegDecoderTable[] = { Sparc_G0, Sparc_G1, Sparc_G2, Sparc_G3, Sparc_G4, Sparc_G5, Sparc_G6, Sparc_G7, Sparc_O0, Sparc_O1, Sparc_O2, Sparc_O3, Sparc_O4, Sparc_O5, Sparc_O6, Sparc_O7, Sparc_L0, Sparc_L1, Sparc_L2, Sparc_L3, Sparc_L4, Sparc_L5, Sparc_L6, Sparc_L7, Sparc_I0, Sparc_I1, Sparc_I2, Sparc_I3, Sparc_I4, Sparc_I5, Sparc_I6, Sparc_I7 }; static const unsigned FPRegDecoderTable[] = { Sparc_F0, Sparc_F1, Sparc_F2, Sparc_F3, Sparc_F4, Sparc_F5, Sparc_F6, Sparc_F7, Sparc_F8, Sparc_F9, Sparc_F10, Sparc_F11, Sparc_F12, Sparc_F13, Sparc_F14, Sparc_F15, Sparc_F16, Sparc_F17, Sparc_F18, Sparc_F19, Sparc_F20, Sparc_F21, Sparc_F22, Sparc_F23, Sparc_F24, Sparc_F25, Sparc_F26, Sparc_F27, Sparc_F28, Sparc_F29, Sparc_F30, Sparc_F31 }; static const unsigned DFPRegDecoderTable[] = { Sparc_D0, Sparc_D16, Sparc_D1, Sparc_D17, Sparc_D2, Sparc_D18, Sparc_D3, Sparc_D19, Sparc_D4, Sparc_D20, Sparc_D5, Sparc_D21, Sparc_D6, Sparc_D22, Sparc_D7, Sparc_D23, Sparc_D8, Sparc_D24, Sparc_D9, Sparc_D25, Sparc_D10, Sparc_D26, Sparc_D11, Sparc_D27, Sparc_D12, Sparc_D28, Sparc_D13, Sparc_D29, Sparc_D14, Sparc_D30, Sparc_D15, Sparc_D31 }; static const unsigned QFPRegDecoderTable[] = { Sparc_Q0, Sparc_Q8, ~0U, ~0U, Sparc_Q1, Sparc_Q9, ~0U, ~0U, Sparc_Q2, Sparc_Q10, ~0U, ~0U, Sparc_Q3, Sparc_Q11, ~0U, ~0U, Sparc_Q4, Sparc_Q12, ~0U, ~0U, Sparc_Q5, Sparc_Q13, ~0U, ~0U, Sparc_Q6, Sparc_Q14, ~0U, ~0U, Sparc_Q7, Sparc_Q15, ~0U, ~0U }; static const unsigned FCCRegDecoderTable[] = { Sparc_FCC0, Sparc_FCC1, Sparc_FCC2, Sparc_FCC3 }; static const unsigned ASRRegDecoderTable[] = { Sparc_Y, Sparc_ASR1, Sparc_ASR2, Sparc_ASR3, Sparc_ASR4, Sparc_ASR5, Sparc_ASR6, Sparc_ASR7, Sparc_ASR8, Sparc_ASR9, Sparc_ASR10, Sparc_ASR11, Sparc_ASR12, Sparc_ASR13, Sparc_ASR14, Sparc_ASR15, Sparc_ASR16, Sparc_ASR17, Sparc_ASR18, Sparc_ASR19, Sparc_ASR20, Sparc_ASR21, Sparc_ASR22, Sparc_ASR23, Sparc_ASR24, Sparc_ASR25, Sparc_ASR26, Sparc_ASR27, Sparc_ASR28, Sparc_ASR29, Sparc_ASR30, Sparc_ASR31 }; static const unsigned PRRegDecoderTable[] = { Sparc_TPC, Sparc_TNPC, Sparc_TSTATE, Sparc_TT, Sparc_TICK, Sparc_TBA, Sparc_PSTATE, Sparc_TL, Sparc_PIL, Sparc_CWP, Sparc_CANSAVE, Sparc_CANRESTORE, Sparc_CLEANWIN, Sparc_OTHERWIN, Sparc_WSTATE }; static const uint16_t IntPairDecoderTable[] = { Sparc_G0_G1, Sparc_G2_G3, Sparc_G4_G5, Sparc_G6_G7, Sparc_O0_O1, Sparc_O2_O3, Sparc_O4_O5, Sparc_O6_O7, Sparc_L0_L1, Sparc_L2_L3, Sparc_L4_L5, Sparc_L6_L7, Sparc_I0_I1, Sparc_I2_I3, Sparc_I4_I5, Sparc_I6_I7, }; static const unsigned CPRegDecoderTable[] = { Sparc_C0, Sparc_C1, Sparc_C2, Sparc_C3, Sparc_C4, Sparc_C5, Sparc_C6, Sparc_C7, Sparc_C8, Sparc_C9, Sparc_C10, Sparc_C11, Sparc_C12, Sparc_C13, Sparc_C14, Sparc_C15, Sparc_C16, Sparc_C17, Sparc_C18, Sparc_C19, Sparc_C20, Sparc_C21, Sparc_C22, Sparc_C23, Sparc_C24, Sparc_C25, Sparc_C26, Sparc_C27, Sparc_C28, Sparc_C29, Sparc_C30, Sparc_C31 }; static const uint16_t CPPairDecoderTable[] = { Sparc_C0_C1, Sparc_C2_C3, Sparc_C4_C5, Sparc_C6_C7, Sparc_C8_C9, Sparc_C10_C11, Sparc_C12_C13, Sparc_C14_C15, Sparc_C16_C17, Sparc_C18_C19, Sparc_C20_C21, Sparc_C22_C23, Sparc_C24_C25, Sparc_C26_C27, Sparc_C28_C29, Sparc_C30_C31 }; static DecodeStatus DecodeDisp19(MCInst *Inst, uint32_t ImmVal, uint64_t Address, const void *Decoder) { int64_t BranchTarget = Address + (SignExtend64(ImmVal, 19) * 4); MCOperand_CreateImm0(Inst, BranchTarget); return MCDisassembler_Success; } static DecodeStatus DecodeDisp16(MCInst *Inst, uint32_t ImmVal, uint64_t Address, const void *Decoder) { int64_t BranchTarget = Address + (SignExtend64(ImmVal, 16) * 4); MCOperand_CreateImm0(Inst, BranchTarget); return MCDisassembler_Success; } static DecodeStatus DecodeDisp22(MCInst *Inst, uint32_t ImmVal, uint64_t Address, const void *Decoder) { int64_t BranchTarget = Address + (SignExtend64(ImmVal, 22) * 4); MCOperand_CreateImm0(Inst, BranchTarget); return MCDisassembler_Success; } static DecodeStatus DecodeIntRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = IntRegDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeI64RegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); } // This is used for the type "ptr_rc", which is either IntRegs or I64Regs // depending on SparcRegisterInfo::getPointerRegClass. static DecodeStatus DecodePointerLikeRegClass0(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder); } static DecodeStatus DecodeFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = FPRegDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeDFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = DFPRegDecoderTable[RegNo]; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeQFPRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = QFPRegDecoderTable[RegNo]; if (Reg == ~0U) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (Reg)); return MCDisassembler_Success; } static DecodeStatus DecodeCoprocRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned Reg = CPRegDecoderTable[RegNo]; 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 DecodeASRRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (ASRRegDecoderTable[RegNo])); return MCDisassembler_Success; } static DecodeStatus DecodePRRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo >= ARR_SIZE(PRRegDecoderTable)) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (PRRegDecoderTable[RegNo])); return MCDisassembler_Success; } static DecodeStatus DecodeIntPairRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler_Success; if (RegNo > 31) return MCDisassembler_Fail; if ((RegNo & 1)) S = MCDisassembler_SoftFail; unsigned RegisterPair = IntPairDecoderTable[RegNo / 2]; MCOperand_CreateReg0(Inst, (RegisterPair)); return S; } static DecodeStatus DecodeCoprocPairRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 31) return MCDisassembler_Fail; unsigned RegisterPair = CPPairDecoderTable[RegNo / 2]; MCOperand_CreateReg0(Inst, (RegisterPair)); return MCDisassembler_Success; } 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); #include "SparcGenDisassemblerTables.inc" static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes, size_t BytesLen, uint64_t Address, SStream *CStream) { if (BytesLen < 4) { return MCDisassembler_Fail; } uint32_t Insn = readBytes32(Instr, Bytes); DecodeStatus Result = MCDisassembler_Fail; // Calling the auto-generated decoder function. if (Sparc_getFeatureBits(Instr->csh->mode, Sparc_FeatureV9)) { Result = decodeInstruction_4(DecoderTableSparcV932, Instr, Insn, Address, NULL); } else { Result = decodeInstruction_4(DecoderTableSparcV832, Instr, Insn, Address, NULL); } if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } Result = decodeInstruction_4(DecoderTableSparc32, Instr, Insn, Address, NULL); if (Result != MCDisassembler_Fail) { *Size = 4; return Result; } return MCDisassembler_Fail; } static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, uint64_t Address, uint64_t Offset, uint64_t Width, MCInst *MI, const void *Decoder) { // Capstone doesn't support symbols. return false; } static DecodeStatus DecodeCall(MCInst *MI, unsigned insn, uint64_t Address, const void *Decoder) { unsigned Offset = fieldFromInstruction_4(insn, 0, 30); int64_t CallTarget = Address + (SignExtend64(Offset, 30) * 4); if (!tryAddingSymbolicOperand(CallTarget, false, Address, 0, 30, MI, Decoder)) MCOperand_CreateImm0(MI, CallTarget); return MCDisassembler_Success; } static DecodeStatus DecodeSIMM13(MCInst *MI, unsigned insn, uint64_t Address, const void *Decoder) { CS_ASSERT(isUIntN(13, insn)); MCOperand_CreateImm0(MI, (SignExtend64((insn), 13))); return MCDisassembler_Success; } DecodeStatus Sparc_LLVM_getInstruction(csh handle, const uint8_t *Bytes, size_t ByteLen, MCInst *MI, uint16_t *Size, uint64_t Address, void *Info) { uint64_t s = 0; DecodeStatus status = getInstruction(MI, &s, Bytes, ByteLen, Address, NULL); *Size = (uint16_t) s; return status; }