diff options
author | 2023-10-10 14:33:42 +0000 | |
---|---|---|
committer | 2023-10-10 14:33:42 +0000 | |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /capstone/arch/TMS320C64x/TMS320C64xDisassembler.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'capstone/arch/TMS320C64x/TMS320C64xDisassembler.c')
-rw-r--r-- | capstone/arch/TMS320C64x/TMS320C64xDisassembler.c | 628 |
1 files changed, 628 insertions, 0 deletions
diff --git a/capstone/arch/TMS320C64x/TMS320C64xDisassembler.c b/capstone/arch/TMS320C64x/TMS320C64xDisassembler.c new file mode 100644 index 000000000..282918783 --- /dev/null +++ b/capstone/arch/TMS320C64x/TMS320C64xDisassembler.c @@ -0,0 +1,628 @@ +/* Capstone Disassembly Engine */ +/* TMS320C64x Backend by Fotis Loukos <me@fotisl.com> 2016 */ + +#ifdef CAPSTONE_HAS_TMS320C64X + +#include <string.h> + +#include "../../cs_priv.h" +#include "../../utils.h" + +#include "TMS320C64xDisassembler.h" + +#include "../../MCInst.h" +#include "../../MCInstrDesc.h" +#include "../../MCFixedLenDisassembler.h" +#include "../../MCRegisterInfo.h" +#include "../../MCDisassembler.h" +#include "../../MathExtras.h" + +static uint64_t getFeatureBits(int mode); + +static DecodeStatus DecodeGPRegsRegisterClass(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeControlRegsRegisterClass(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeScst5(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeScst16(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodePCRelScst7(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodePCRelScst10(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodePCRelScst12(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodePCRelScst21(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeMemOperand(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeMemOperandSc(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeMemOperand2(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeRegPair5(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeRegPair4(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeCondRegister(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeCondRegisterZero(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeSide(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeParallel(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeCrosspathX1(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeCrosspathX2(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeCrosspathX3(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +static DecodeStatus DecodeNop(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder); + +#include "TMS320C64xGenDisassemblerTables.inc" + +#define GET_REGINFO_ENUM +#define GET_REGINFO_MC_DESC +#include "TMS320C64xGenRegisterInfo.inc" + +static const unsigned GPRegsDecoderTable[] = { + TMS320C64x_A0, TMS320C64x_A1, TMS320C64x_A2, TMS320C64x_A3, + TMS320C64x_A4, TMS320C64x_A5, TMS320C64x_A6, TMS320C64x_A7, + TMS320C64x_A8, TMS320C64x_A9, TMS320C64x_A10, TMS320C64x_A11, + TMS320C64x_A12, TMS320C64x_A13, TMS320C64x_A14, TMS320C64x_A15, + TMS320C64x_A16, TMS320C64x_A17, TMS320C64x_A18, TMS320C64x_A19, + TMS320C64x_A20, TMS320C64x_A21, TMS320C64x_A22, TMS320C64x_A23, + TMS320C64x_A24, TMS320C64x_A25, TMS320C64x_A26, TMS320C64x_A27, + TMS320C64x_A28, TMS320C64x_A29, TMS320C64x_A30, TMS320C64x_A31 +}; + +static const unsigned ControlRegsDecoderTable[] = { + TMS320C64x_AMR, TMS320C64x_CSR, TMS320C64x_ISR, TMS320C64x_ICR, + TMS320C64x_IER, TMS320C64x_ISTP, TMS320C64x_IRP, TMS320C64x_NRP, + ~0U, ~0U, TMS320C64x_TSCL, TMS320C64x_TSCH, + ~0U, TMS320C64x_ILC, TMS320C64x_RILC, TMS320C64x_REP, + TMS320C64x_PCE1, TMS320C64x_DNUM, ~0U, ~0U, + ~0U, TMS320C64x_SSR, TMS320C64x_GPLYA, TMS320C64x_GPLYB, + TMS320C64x_GFPGFR, TMS320C64x_DIER, TMS320C64x_TSR, TMS320C64x_ITSR, + TMS320C64x_NTSR, TMS320C64x_ECR, ~0U, TMS320C64x_IERR +}; + +static uint64_t getFeatureBits(int mode) +{ + // support everything + return (uint64_t)-1; +} + +static unsigned getReg(const unsigned *RegTable, unsigned RegNo) +{ + if(RegNo > 31) + return ~0U; + return RegTable[RegNo]; +} + +static DecodeStatus DecodeGPRegsRegisterClass(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder) +{ + unsigned Reg; + + if(RegNo > 31) + return MCDisassembler_Fail; + + Reg = getReg(GPRegsDecoderTable, RegNo); + if(Reg == ~0U) + return MCDisassembler_Fail; + MCOperand_CreateReg0(Inst, Reg); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeControlRegsRegisterClass(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder) +{ + unsigned Reg; + + if(RegNo > 31) + return MCDisassembler_Fail; + + Reg = getReg(ControlRegsDecoderTable, RegNo); + if(Reg == ~0U) + return MCDisassembler_Fail; + MCOperand_CreateReg0(Inst, Reg); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeScst5(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + int32_t imm; + + imm = Val; + /* Sign extend 5 bit value */ + if(imm & (1 << (5 - 1))) + imm |= ~((1 << 5) - 1); + + MCOperand_CreateImm0(Inst, imm); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeScst16(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + int32_t imm; + + imm = Val; + /* Sign extend 16 bit value */ + if(imm & (1 << (16 - 1))) + imm |= ~((1 << 16) - 1); + + MCOperand_CreateImm0(Inst, imm); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodePCRelScst7(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + int32_t imm; + + imm = Val; + /* Sign extend 7 bit value */ + if(imm & (1 << (7 - 1))) + imm |= ~((1 << 7) - 1); + + /* Address is relative to the address of the first instruction in the fetch packet */ + MCOperand_CreateImm0(Inst, (Address & ~31) + (imm * 4)); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodePCRelScst10(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + int32_t imm; + + imm = Val; + /* Sign extend 10 bit value */ + if(imm & (1 << (10 - 1))) + imm |= ~((1 << 10) - 1); + + /* Address is relative to the address of the first instruction in the fetch packet */ + MCOperand_CreateImm0(Inst, (Address & ~31) + (imm * 4)); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodePCRelScst12(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + int32_t imm; + + imm = Val; + /* Sign extend 12 bit value */ + if(imm & (1 << (12 - 1))) + imm |= ~((1 << 12) - 1); + + /* Address is relative to the address of the first instruction in the fetch packet */ + MCOperand_CreateImm0(Inst, (Address & ~31) + (imm * 4)); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodePCRelScst21(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + int32_t imm; + + imm = Val; + /* Sign extend 21 bit value */ + if(imm & (1 << (21 - 1))) + imm |= ~((1 << 21) - 1); + + /* Address is relative to the address of the first instruction in the fetch packet */ + MCOperand_CreateImm0(Inst, (Address & ~31) + (imm * 4)); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeMemOperand(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + return DecodeMemOperandSc(Inst, Val | (1 << 15), Address, Decoder); +} + +static DecodeStatus DecodeMemOperandSc(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + uint8_t scaled, base, offset, mode, unit; + unsigned basereg, offsetreg; + + scaled = (Val >> 15) & 1; + base = (Val >> 10) & 0x1f; + offset = (Val >> 5) & 0x1f; + mode = (Val >> 1) & 0xf; + unit = Val & 1; + + if((base >= TMS320C64X_REG_A0) && (base <= TMS320C64X_REG_A31)) + base = (base - TMS320C64X_REG_A0 + TMS320C64X_REG_B0); + else if((base >= TMS320C64X_REG_B0) && (base <= TMS320C64X_REG_B31)) + base = (base - TMS320C64X_REG_B0 + TMS320C64X_REG_A0); + basereg = getReg(GPRegsDecoderTable, base); + if (basereg == ~0U) + return MCDisassembler_Fail; + + switch(mode) { + case 0: + case 1: + case 8: + case 9: + case 10: + case 11: + MCOperand_CreateImm0(Inst, (scaled << 19) | (basereg << 12) | (offset << 5) | (mode << 1) | unit); + break; + case 4: + case 5: + case 12: + case 13: + case 14: + case 15: + if((offset >= TMS320C64X_REG_A0) && (offset <= TMS320C64X_REG_A31)) + offset = (offset - TMS320C64X_REG_A0 + TMS320C64X_REG_B0); + else if((offset >= TMS320C64X_REG_B0) && (offset <= TMS320C64X_REG_B31)) + offset = (offset - TMS320C64X_REG_B0 + TMS320C64X_REG_A0); + offsetreg = getReg(GPRegsDecoderTable, offset); + if (offsetreg == ~0U) + return MCDisassembler_Fail; + MCOperand_CreateImm0(Inst, (scaled << 19) | (basereg << 12) | (offsetreg << 5) | (mode << 1) | unit); + break; + default: + return MCDisassembler_Fail; + } + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeMemOperand2(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + uint16_t offset; + unsigned basereg; + + if(Val & 1) + basereg = TMS320C64X_REG_B15; + else + basereg = TMS320C64X_REG_B14; + + offset = (Val >> 1) & 0x7fff; + MCOperand_CreateImm0(Inst, (offset << 7) | basereg); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeRegPair5(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder) +{ + unsigned Reg; + + if(RegNo > 31) + return MCDisassembler_Fail; + + Reg = getReg(GPRegsDecoderTable, RegNo); + MCOperand_CreateReg0(Inst, Reg); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeRegPair4(MCInst *Inst, unsigned RegNo, + uint64_t Address, void *Decoder) +{ + unsigned Reg; + + if(RegNo > 15) + return MCDisassembler_Fail; + + Reg = getReg(GPRegsDecoderTable, RegNo << 1); + MCOperand_CreateReg0(Inst, Reg); + + return MCDisassembler_Success; +} + +static DecodeStatus DecodeCondRegister(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + case 7: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_INVALID; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_B0; + break; + case 2: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_B1; + break; + case 3: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_B2; + break; + case 4: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_A1; + break; + case 5: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_A2; + break; + case 6: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_A0; + break; + default: + Inst->flat_insn->detail->tms320c64x.condition.reg = TMS320C64X_REG_INVALID; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + +static DecodeStatus DecodeCondRegisterZero(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + Inst->flat_insn->detail->tms320c64x.condition.zero = 0; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.condition.zero = 1; + break; + default: + Inst->flat_insn->detail->tms320c64x.condition.zero = 0; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + +static DecodeStatus DecodeSide(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + MCOperand *op; + int i; + + /* This is pretty messy, probably we should find a better way */ + if(Val == 1) { + for(i = 0; i < Inst->size; i++) { + op = &Inst->Operands[i]; + if(op->Kind == kRegister) { + if((op->RegVal >= TMS320C64X_REG_A0) && (op->RegVal <= TMS320C64X_REG_A31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_A0 + TMS320C64X_REG_B0); + else if((op->RegVal >= TMS320C64X_REG_B0) && (op->RegVal <= TMS320C64X_REG_B31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_B0 + TMS320C64X_REG_A0); + } + } + } + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + Inst->flat_insn->detail->tms320c64x.funit.side = 1; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.funit.side = 2; + break; + default: + Inst->flat_insn->detail->tms320c64x.funit.side = 0; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + +static DecodeStatus DecodeParallel(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + Inst->flat_insn->detail->tms320c64x.parallel = 0; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.parallel = 1; + break; + default: + Inst->flat_insn->detail->tms320c64x.parallel = -1; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + +static DecodeStatus DecodeCrosspathX1(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + MCOperand *op; + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = 0; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = 1; + op = &Inst->Operands[0]; + if(op->Kind == kRegister) { + if((op->RegVal >= TMS320C64X_REG_A0) && (op->RegVal <= TMS320C64X_REG_A31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_A0 + TMS320C64X_REG_B0); + else if((op->RegVal >= TMS320C64X_REG_B0) && (op->RegVal <= TMS320C64X_REG_B31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_B0 + TMS320C64X_REG_A0); + } + break; + default: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = -1; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + +static DecodeStatus DecodeCrosspathX2(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + MCOperand *op; + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = 0; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = 1; + op = &Inst->Operands[1]; + if(op->Kind == kRegister) { + if((op->RegVal >= TMS320C64X_REG_A0) && (op->RegVal <= TMS320C64X_REG_A31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_A0 + TMS320C64X_REG_B0); + else if((op->RegVal >= TMS320C64X_REG_B0) && (op->RegVal <= TMS320C64X_REG_B31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_B0 + TMS320C64X_REG_A0); + } + break; + default: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = -1; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + +static DecodeStatus DecodeCrosspathX3(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + DecodeStatus ret = MCDisassembler_Success; + MCOperand *op; + + if(!Inst->flat_insn->detail) + return MCDisassembler_Success; + + switch(Val) { + case 0: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = 0; + break; + case 1: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = 2; + op = &Inst->Operands[2]; + if(op->Kind == kRegister) { + if((op->RegVal >= TMS320C64X_REG_A0) && (op->RegVal <= TMS320C64X_REG_A31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_A0 + TMS320C64X_REG_B0); + else if((op->RegVal >= TMS320C64X_REG_B0) && (op->RegVal <= TMS320C64X_REG_B31)) + op->RegVal = (op->RegVal - TMS320C64X_REG_B0 + TMS320C64X_REG_A0); + } + break; + default: + Inst->flat_insn->detail->tms320c64x.funit.crosspath = -1; + ret = MCDisassembler_Fail; + break; + } + + return ret; +} + + +static DecodeStatus DecodeNop(MCInst *Inst, unsigned Val, + uint64_t Address, void *Decoder) +{ + MCOperand_CreateImm0(Inst, Val + 1); + + return MCDisassembler_Success; +} + +#define GET_INSTRINFO_ENUM +#include "TMS320C64xGenInstrInfo.inc" + +bool TMS320C64x_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; + + if(code_len < 4) { + *size = 0; + return MCDisassembler_Fail; + } + + if(MI->flat_insn->detail) + memset(MI->flat_insn->detail, 0, offsetof(cs_detail, tms320c64x)+sizeof(cs_tms320c64x)); + + insn = (code[3] << 0) | (code[2] << 8) | (code[1] << 16) | ((uint32_t) code[0] << 24); + result = decodeInstruction_4(DecoderTable32, MI, insn, address, info, 0); + + if(result == MCDisassembler_Success) { + *size = 4; + return true; + } + + MCInst_clear(MI); + *size = 0; + return false; +} + +void TMS320C64x_init(MCRegisterInfo *MRI) +{ + MCRegisterInfo_InitMCRegisterInfo(MRI, TMS320C64xRegDesc, 90, + 0, 0, + TMS320C64xMCRegisterClasses, 7, + 0, 0, + TMS320C64xRegDiffLists, + 0, + TMS320C64xSubRegIdxLists, 1, + 0); +} + +#endif |