diff --git a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp index e7b937cce57794..dda5e08461dd0b 100644 --- a/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp +++ b/llvm/lib/Target/Xtensa/Disassembler/XtensaDisassembler.cpp @@ -44,6 +44,11 @@ class XtensaDisassembler : public MCDisassembler { bool hasESP32S3Ops() const { return STI.getFeatureBits()[Xtensa::FeatureESP32S3Ops]; + + } + + bool hasHIFI3() const { + return STI.getFeatureBits()[Xtensa::FeatureHIFI3]; } DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, @@ -832,7 +837,7 @@ static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm, /// Read two bytes from the ArrayRef and return 16 bit data sorted /// according to the given endianness. static DecodeStatus readInstruction16(ArrayRef Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn, + uint64_t &Size, uint64_t &Insn, bool IsLittleEndian) { // We want to read exactly 2 Bytes of data. if (Bytes.size() < 2) { @@ -851,7 +856,7 @@ static DecodeStatus readInstruction16(ArrayRef Bytes, uint64_t Address, /// Read three bytes from the ArrayRef and return 24 bit data static DecodeStatus readInstruction24(ArrayRef Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn, + uint64_t &Size, uint64_t &Insn, bool IsLittleEndian) { // We want to read exactly 3 Bytes of data. if (Bytes.size() < 3) { @@ -870,7 +875,7 @@ static DecodeStatus readInstruction24(ArrayRef Bytes, uint64_t Address, /// Read three bytes from the ArrayRef and return 32 bit data static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, - uint64_t &Size, uint32_t &Insn, + uint64_t &Size, uint64_t &Insn, bool IsLittleEndian) { // We want to read exactly 4 Bytes of data. if (Bytes.size() < 4) { @@ -887,13 +892,37 @@ static DecodeStatus readInstruction32(ArrayRef Bytes, uint64_t Address, return MCDisassembler::Success; } +/// Read InstSize bytes from the ArrayRef and return 24 bit data +static DecodeStatus readInstructionN(ArrayRef Bytes, uint64_t Address, + unsigned InstSize, + uint64_t &Size, uint64_t &Insn, + bool IsLittleEndian) { + // We want to read exactly 3 Bytes of data. + if (Bytes.size() < InstSize) { + Size = 0; + return MCDisassembler::Fail; + } + + if (!IsLittleEndian) { + report_fatal_error("Big-endian mode currently is not supported!"); + } else { + Insn = 0; + for (unsigned i = 0; i < InstSize; i++) + Insn |= (Bytes[i] << 8*i); + } + + Size = InstSize; + return MCDisassembler::Success; +} + + #include "XtensaGenDisassemblerTables.inc" DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size, ArrayRef Bytes, uint64_t Address, raw_ostream &CS) const { - uint32_t Insn; + uint64_t Insn; DecodeStatus Result; // Parse 16-bit instructions @@ -946,5 +975,20 @@ DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } } + if (hasHIFI3()) { + LLVM_DEBUG(dbgs() << "Trying Xtensa HIFI3 24-bit instruction table :\n"); + Result = decodeInstruction(DecoderTableHIFI324, MI, Insn, Address, this, STI); + if(Result != MCDisassembler::Fail) + return Result; + + Result = readInstructionN(Bytes, Address, 48, Size, Insn, IsLittleEndian); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + + LLVM_DEBUG(dbgs() << "Trying Xtensa HIFI3 48-bit instruction table :\n"); + Result = decodeInstruction(DecoderTableHIFI348, MI, Insn, Address, this, STI); + if(Result != MCDisassembler::Fail) + return Result; + } return Result; }