-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[Xtensa] Implement Code Density Option. #119639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b9a6a95
9dc207f
32270ea
343fdac
c8c4428
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,9 +38,7 @@ class XtensaDisassembler : public MCDisassembler { | |
XtensaDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool isLE) | ||
: MCDisassembler(STI, Ctx), IsLittleEndian(isLE) {} | ||
|
||
bool hasDensity() const { | ||
return STI.hasFeature(Xtensa::FeatureDensity); | ||
} | ||
bool hasDensity() const { return STI.hasFeature(Xtensa::FeatureDensity); } | ||
|
||
DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, | ||
ArrayRef<uint8_t> Bytes, uint64_t Address, | ||
|
@@ -99,8 +97,8 @@ static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch, | |
uint64_t InstSize, MCInst &MI, | ||
const void *Decoder) { | ||
const MCDisassembler *Dis = static_cast<const MCDisassembler *>(Decoder); | ||
return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, /*OpSize=*/0, | ||
InstSize); | ||
return Dis->tryAddingSymbolicOperand(MI, Value, Address, isBranch, Offset, | ||
/*OpSize=*/0, InstSize); | ||
} | ||
|
||
static DecodeStatus decodeCallOperand(MCInst &Inst, uint64_t Imm, | ||
|
@@ -190,6 +188,28 @@ static DecodeStatus decodeImm1_16Operand(MCInst &Inst, uint64_t Imm, | |
return MCDisassembler::Success; | ||
} | ||
|
||
static DecodeStatus decodeImm1n_15Operand(MCInst &Inst, uint64_t Imm, | ||
int64_t Address, | ||
const void *Decoder) { | ||
assert(isUInt<4>(Imm) && "Invalid immediate"); | ||
if (!Imm) | ||
Inst.addOperand(MCOperand::createImm(-1)); | ||
else | ||
Inst.addOperand(MCOperand::createImm(Imm)); | ||
return MCDisassembler::Success; | ||
} | ||
|
||
static DecodeStatus decodeImm32n_95Operand(MCInst &Inst, uint64_t Imm, | ||
int64_t Address, | ||
const void *Decoder) { | ||
assert(isUInt<7>(Imm) && "Invalid immediate"); | ||
if ((Imm & 0x60) == 0x60) | ||
Inst.addOperand(MCOperand::createImm((~0x1f) | Imm)); | ||
else | ||
Inst.addOperand(MCOperand::createImm(Imm)); | ||
return MCDisassembler::Success; | ||
} | ||
|
||
static DecodeStatus decodeShimm1_31Operand(MCInst &Inst, uint64_t Imm, | ||
int64_t Address, | ||
const void *Decoder) { | ||
|
@@ -243,9 +263,37 @@ static DecodeStatus decodeMem32Operand(MCInst &Inst, uint64_t Imm, | |
return MCDisassembler::Success; | ||
} | ||
|
||
static DecodeStatus decodeMem32nOperand(MCInst &Inst, uint64_t Imm, | ||
int64_t Address, const void *Decoder) { | ||
assert(isUInt<8>(Imm) && "Invalid immediate"); | ||
DecodeARRegisterClass(Inst, Imm & 0xf, Address, Decoder); | ||
Inst.addOperand(MCOperand::createImm((Imm >> 2) & 0x3c)); | ||
return MCDisassembler::Success; | ||
} | ||
|
||
/// Read two bytes from the ArrayRef and return 16 bit data sorted | ||
/// according to the given endianness. | ||
static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address, | ||
uint64_t &Size, uint64_t &Insn, | ||
bool IsLittleEndian) { | ||
// We want to read exactly 2 Bytes of data. | ||
if (Bytes.size() < 2) { | ||
Size = 0; | ||
return MCDisassembler::Fail; | ||
} | ||
|
||
if (!IsLittleEndian) { | ||
report_fatal_error("Big-endian mode currently is not supported!"); | ||
} else { | ||
Insn = (Bytes[1] << 8) | Bytes[0]; | ||
} | ||
|
||
return MCDisassembler::Success; | ||
} | ||
|
||
/// Read three bytes from the ArrayRef and return 24 bit data | ||
static DecodeStatus readInstruction24(ArrayRef<uint8_t> 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) { | ||
|
@@ -259,7 +307,6 @@ static DecodeStatus readInstruction24(ArrayRef<uint8_t> Bytes, uint64_t Address, | |
Insn = (Bytes[2] << 16) | (Bytes[1] << 8) | (Bytes[0] << 0); | ||
} | ||
|
||
Size = 3; | ||
return MCDisassembler::Success; | ||
} | ||
|
||
|
@@ -269,13 +316,31 @@ DecodeStatus XtensaDisassembler::getInstruction(MCInst &MI, uint64_t &Size, | |
ArrayRef<uint8_t> Bytes, | ||
uint64_t Address, | ||
raw_ostream &CS) const { | ||
uint32_t Insn; | ||
uint64_t Insn; | ||
DecodeStatus Result; | ||
|
||
// Parse 16-bit instructions | ||
if (hasDensity()) { | ||
Result = readInstruction16(Bytes, Address, Size, Insn, IsLittleEndian); | ||
if (Result == MCDisassembler::Fail) | ||
return MCDisassembler::Fail; | ||
LLVM_DEBUG(dbgs() << "Trying Xtensa 16-bit instruction table :\n"); | ||
Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI); | ||
Comment on lines
+327
to
+328
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the disassembler test, make sure to test mismatches (e.g. !hasDensity and there are encoded values using the extension) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you mean try to disassemble 16-bit code with the hasDensity option disabled and check that it produces erroneous decoding? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it should not crash There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this verification to the disassembler test. |
||
if (Result != MCDisassembler::Fail) { | ||
Size = 2; | ||
return Result; | ||
} | ||
} | ||
|
||
// Parse Core 24-bit instructions | ||
Result = readInstruction24(Bytes, Address, Size, Insn, IsLittleEndian); | ||
if (Result == MCDisassembler::Fail) | ||
return MCDisassembler::Fail; | ||
LLVM_DEBUG(dbgs() << "Trying Xtensa 24-bit instruction table :\n"); | ||
Result = decodeInstruction(DecoderTable24, MI, Insn, Address, this, STI); | ||
if (Result != MCDisassembler::Fail) { | ||
Size = 3; | ||
return Result; | ||
} | ||
return Result; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing disassembler tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added disassembler test.