//===------ SystemZDisassembler.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 , 2013-2014 */ #ifdef CAPSTONE_HAS_SYSZ #include // DEBUG #include #include #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" #include "SystemZMCTargetDesc.h" static uint64_t getFeatureBits(int mode) { // support everything return (uint64_t)-1; } static DecodeStatus decodeRegisterClass(MCInst *Inst, uint64_t RegNo, const unsigned *Regs) { //assert(RegNo < 16 && "Invalid register"); RegNo = Regs[RegNo]; if (RegNo == 0) return MCDisassembler_Fail; MCOperand_CreateReg0(Inst, (unsigned)RegNo); return MCDisassembler_Success; } static DecodeStatus DecodeGR32BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_GR32Regs); } static DecodeStatus DecodeGRH32BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_GRH32Regs); } static DecodeStatus DecodeGR64BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_GR64Regs); } static DecodeStatus DecodeGR128BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_GR128Regs); } static DecodeStatus DecodeADDR64BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_GR64Regs); } static DecodeStatus DecodeFP32BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_FP32Regs); } static DecodeStatus DecodeFP64BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_FP64Regs); } static DecodeStatus DecodeFP128BitRegisterClass(MCInst *Inst, uint64_t RegNo, uint64_t Address, const void *Decoder) { return decodeRegisterClass(Inst, RegNo, SystemZMC_FP128Regs); } static DecodeStatus decodeUImmOperand(MCInst *Inst, uint64_t Imm) { //assert(isUInt(Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, Imm); return MCDisassembler_Success; } static DecodeStatus decodeSImmOperand(MCInst *Inst, uint64_t Imm, unsigned N) { //assert(isUInt(Imm) && "Invalid immediate"); MCOperand_CreateImm0(Inst, SignExtend64(Imm, N)); return MCDisassembler_Success; } static DecodeStatus decodeAccessRegOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeUImmOperand(Inst, Imm); } static DecodeStatus decodeU4ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeUImmOperand(Inst, Imm); } static DecodeStatus decodeU6ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeUImmOperand(Inst, Imm); } static DecodeStatus decodeU8ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeUImmOperand(Inst, Imm); } static DecodeStatus decodeU16ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeUImmOperand(Inst, Imm); } static DecodeStatus decodeU32ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeUImmOperand(Inst, Imm); } static DecodeStatus decodeS8ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeSImmOperand(Inst, Imm, 8); } static DecodeStatus decodeS16ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeSImmOperand(Inst, Imm, 16); } static DecodeStatus decodeS32ImmOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodeSImmOperand(Inst, Imm, 32); } static DecodeStatus decodePCDBLOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, unsigned N) { //assert(isUInt(Imm) && "Invalid PC-relative offset"); MCOperand_CreateImm0(Inst, SignExtend64(Imm, N) * 2 + Address); return MCDisassembler_Success; } static DecodeStatus decodePC16DBLOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodePCDBLOperand(Inst, Imm, Address, 16); } static DecodeStatus decodePC32DBLOperand(MCInst *Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { return decodePCDBLOperand(Inst, Imm, Address, 32); } static DecodeStatus decodeBDAddr12Operand(MCInst *Inst, uint64_t Field, const unsigned *Regs) { uint64_t Base = Field >> 12; uint64_t Disp = Field & 0xfff; //assert(Base < 16 && "Invalid BDAddr12"); MCOperand_CreateReg0(Inst, Base == 0 ? 0 : Regs[Base]); MCOperand_CreateImm0(Inst, Disp); return MCDisassembler_Success; } static DecodeStatus decodeBDAddr20Operand(MCInst *Inst, uint64_t Field, const unsigned *Regs) { uint64_t Base = Field >> 20; uint64_t Disp = ((Field << 12) & 0xff000) | ((Field >> 8) & 0xfff); //assert(Base < 16 && "Invalid BDAddr20"); MCOperand_CreateReg0(Inst, Base == 0 ? 0 : Regs[Base]); MCOperand_CreateImm0(Inst, SignExtend64(Disp, 20)); return MCDisassembler_Success; } static DecodeStatus decodeBDXAddr12Operand(MCInst *Inst, uint64_t Field, const unsigned *Regs) { uint64_t Index = Field >> 16; uint64_t Base = (Field >> 12) & 0xf; uint64_t Disp = Field & 0xfff; //assert(Index < 16 && "Invalid BDXAddr12"); MCOperand_CreateReg0(Inst, Base == 0 ? 0 : Regs[Base]); MCOperand_CreateImm0(Inst, Disp); MCOperand_CreateReg0(Inst, Index == 0 ? 0 : Regs[Index]); return MCDisassembler_Success; } static DecodeStatus decodeBDXAddr20Operand(MCInst *Inst, uint64_t Field, const unsigned *Regs) { uint64_t Index = Field >> 24; uint64_t Base = (Field >> 20) & 0xf; uint64_t Disp = ((Field & 0xfff00) >> 8) | ((Field & 0xff) << 12); //assert(Index < 16 && "Invalid BDXAddr20"); MCOperand_CreateReg0(Inst, Base == 0 ? 0 : Regs[Base]); MCOperand_CreateImm0(Inst, SignExtend64(Disp, 20)); MCOperand_CreateReg0(Inst, Index == 0 ? 0 : Regs[Index]); return MCDisassembler_Success; } static DecodeStatus decodeBDLAddr12Len8Operand(MCInst *Inst, uint64_t Field, const unsigned *Regs) { uint64_t Length = Field >> 16; uint64_t Base = (Field >> 12) & 0xf; uint64_t Disp = Field & 0xfff; //assert(Length < 256 && "Invalid BDLAddr12Len8"); MCOperand_CreateReg0(Inst, Base == 0 ? 0 : Regs[Base]); MCOperand_CreateImm0(Inst, Disp); MCOperand_CreateImm0(Inst, Length + 1); return MCDisassembler_Success; } static DecodeStatus decodeBDAddr32Disp12Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDAddr12Operand(Inst, Field, SystemZMC_GR32Regs); } static DecodeStatus decodeBDAddr32Disp20Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDAddr20Operand(Inst, Field, SystemZMC_GR32Regs); } static DecodeStatus decodeBDAddr64Disp12Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDAddr12Operand(Inst, Field, SystemZMC_GR64Regs); } static DecodeStatus decodeBDAddr64Disp20Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDAddr20Operand(Inst, Field, SystemZMC_GR64Regs); } static DecodeStatus decodeBDXAddr64Disp12Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDXAddr12Operand(Inst, Field, SystemZMC_GR64Regs); } static DecodeStatus decodeBDXAddr64Disp20Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDXAddr20Operand(Inst, Field, SystemZMC_GR64Regs); } static DecodeStatus decodeBDLAddr64Disp12Len8Operand(MCInst *Inst, uint64_t Field, uint64_t Address, const void *Decoder) { return decodeBDLAddr12Len8Operand(Inst, Field, SystemZMC_GR64Regs); } #define GET_SUBTARGETINFO_ENUM #include "SystemZGenSubtargetInfo.inc" #include "SystemZGenDisassemblerTables.inc" bool SystemZ_getInstruction(csh ud, const uint8_t *code, size_t code_len, MCInst *MI, uint16_t *size, uint64_t address, void *info) { uint64_t Inst; uint8_t Bytes[6]; const uint8_t *Table; uint16_t I; // The top 2 bits of the first byte specify the size. if (*code < 0x40) { *size = 2; Table = DecoderTable16; } else if (*code < 0xc0) { *size = 4; Table = DecoderTable32; } else { *size = 6; Table = DecoderTable48; } if (code_len < *size) // short of input data return false; if (MI->flat_insn->detail) { memset(MI->flat_insn->detail, 0, sizeof(cs_detail)); } memcpy(Bytes, code, *size); // Construct the instruction. Inst = 0; for (I = 0; I < *size; ++I) Inst = (Inst << 8) | Bytes[I]; return decodeInstruction(Table, MI, Inst, address, info, 0); } #define GET_REGINFO_ENUM #define GET_REGINFO_MC_DESC #include "SystemZGenRegisterInfo.inc" void SystemZ_init(MCRegisterInfo *MRI) { /* InitMCRegisterInfo(SystemZRegDesc, 98, RA, PC, SystemZMCRegisterClasses, 12, SystemZRegUnitRoots, 49, SystemZRegDiffLists, SystemZRegStrings, SystemZSubRegIdxLists, 7, SystemZSubRegIdxRanges, SystemZRegEncodingTable); */ MCRegisterInfo_InitMCRegisterInfo(MRI, SystemZRegDesc, 98, 0, 0, SystemZMCRegisterClasses, 12, 0, 0, SystemZRegDiffLists, 0, SystemZSubRegIdxLists, 7, 0); } #endif