summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARC/Disassembler
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARC/Disassembler')
-rw-r--r--llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp210
1 files changed, 141 insertions, 69 deletions
diff --git a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
index b49658004f7..82199d858c0 100644
--- a/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
+++ b/llvm/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
@@ -67,6 +67,15 @@ static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
return true;
}
+static bool readInstruction48(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint64_t &Insn) {
+ Size = 6;
+ Insn = ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) |
+ ((uint64_t)Bytes[2] << 32) | ((uint64_t)Bytes[3] << 40) |
+ ((uint64_t)Bytes[4] << 16) | ((uint64_t)Bytes[5] << 24);
+ return true;
+}
+
static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
uint64_t &Size, uint32_t &Insn) {
Size = 2;
@@ -74,32 +83,33 @@ static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
return true;
}
-static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned,
- uint64_t, const void *);
-
-static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned,
- uint64_t, const void *);
+template <unsigned B>
+static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
+ uint64_t Address = 0,
+ const void *Decoder = nullptr);
-static MCDisassembler::DecodeStatus
-DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *);
+template <unsigned B>
+static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
+ uint64_t Address = 0,
+ const void *Decoder = nullptr);
-static MCDisassembler::DecodeStatus
-DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *);
+template <unsigned B>
+static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
+ uint64_t Address, const void *Decoder);
-static MCDisassembler::DecodeStatus
-DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *);
+static DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t, const void *);
-static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
- const void *);
+static DecodeStatus DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t,
+ const void *);
-static MCDisassembler::DecodeStatus
-DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+static DecodeStatus DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t,
+ const void *);
-static MCDisassembler::DecodeStatus
-DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+static DecodeStatus DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t,
+ const void *);
-static MCDisassembler::DecodeStatus
-DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t, uint64_t,
+ const void *);
static const uint16_t GPR32DecoderTable[] = {
ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
@@ -115,11 +125,22 @@ static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
DEBUG(dbgs() << "Not a GPR32 register.");
return MCDisassembler::Fail;
}
+
unsigned Reg = GPR32DecoderTable[RegNo];
Inst.addOperand(MCOperand::createReg(Reg));
return MCDisassembler::Success;
}
+static DecodeStatus DecodeGBR32ShortRegister(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ // Enumerates registers from ranges [r0-r3],[r12-r15].
+ if (RegNo > 3)
+ RegNo += 8; // 4 for r12, etc...
+
+ return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);
+}
+
#include "ARCGenDisassemblerTables.inc"
static unsigned decodeCField(unsigned Insn) {
@@ -135,8 +156,8 @@ static unsigned decodeAField(unsigned Insn) {
return fieldFromInstruction(Insn, 0, 6);
}
-static MCDisassembler::DecodeStatus
-DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
+static DecodeStatus DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address,
+ const void *Dec) {
// We have the 9-bit immediate in the low bits, 6-bit register in high bits.
unsigned S9 = Insn & 0x1ff;
unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
@@ -145,49 +166,59 @@ DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
return MCDisassembler::Success;
}
-static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst,
- unsigned InsnS9,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9)));
- return MCDisassembler::Success;
+static bool DecodeSymbolicOperand(MCInst &Inst, uint64_t Address,
+ uint64_t Value, const void *Decoder) {
+ static const uint64_t atLeast = 2;
+ // TODO: Try to force emitter to use MCDisassembler* instead of void*.
+ auto Disassembler = static_cast<const MCDisassembler *>(Decoder);
+ return (nullptr != Disassembler &&
+ Disassembler->tryAddingSymbolicOperand(Inst, Value, Address, true, 0,
+ atLeast));
}
-static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst,
- unsigned InsnS12,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12)));
- return MCDisassembler::Success;
+static void DecodeSymbolicOperandOff(MCInst &Inst, uint64_t Address,
+ uint64_t Offset, const void *Decoder) {
+ uint64_t nextAddress = Address + Offset;
+
+ if (!DecodeSymbolicOperand(Inst, Address, nextAddress, Decoder))
+ Inst.addOperand(MCOperand::createImm(Offset));
}
-static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst,
- unsigned S,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S)));
+template <unsigned B>
+static DecodeStatus DecodeBranchTargetS(MCInst &Inst, unsigned InsnS,
+ uint64_t Address, const void *Decoder) {
+
+ static_assert(B > 0, "field is empty");
+ DecodeSymbolicOperandOff(Inst, Address, SignExtend32<B>(InsnS), Decoder);
return MCDisassembler::Success;
}
-static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst,
- unsigned S,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S)));
+template <unsigned B>
+static DecodeStatus DecodeSignedOperand(MCInst &Inst, unsigned InsnS,
+ uint64_t /*Address*/,
+ const void * /*Decoder*/) {
+
+ static_assert(B > 0, "field is empty");
+ Inst.addOperand(MCOperand::createImm(
+ SignExtend32<B>(maskTrailingOnes<decltype(InsnS)>(B) & InsnS)));
return MCDisassembler::Success;
}
-static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst,
- unsigned S,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S)));
+template <unsigned B>
+static DecodeStatus DecodeFromCyclicRange(MCInst &Inst, unsigned InsnS,
+ uint64_t /*Address*/,
+ const void * /*Decoder*/) {
+
+ static_assert(B > 0, "field is empty");
+ const unsigned max = (1u << B) - 1;
+ Inst.addOperand(
+ MCOperand::createImm(InsnS < max ? static_cast<int>(InsnS) : -1));
return MCDisassembler::Success;
}
-static MCDisassembler::DecodeStatus
-DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
- const void *Decoder) {
+static DecodeStatus DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn,
+ uint64_t Address,
+ const void *Decoder) {
unsigned SrcC, DstB, LImm;
DstB = decodeBField(Insn);
if (DstB != 62) {
@@ -202,9 +233,9 @@ DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
return MCDisassembler::Success;
}
-static MCDisassembler::DecodeStatus
-DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
- const void *Decoder) {
+static DecodeStatus DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn,
+ uint64_t Address,
+ const void *Decoder) {
unsigned DstA, SrcB, LImm;
DEBUG(dbgs() << "Decoding LdLImm:\n");
SrcB = decodeBField(Insn);
@@ -220,9 +251,9 @@ DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
return MCDisassembler::Success;
}
-static MCDisassembler::DecodeStatus
-DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
- const void *Decoder) {
+static DecodeStatus DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn,
+ uint64_t Address,
+ const void *Decoder) {
unsigned DstA, SrcB;
DEBUG(dbgs() << "Decoding LdRLimm\n");
DstA = decodeAField(Insn);
@@ -237,9 +268,37 @@ DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
return MCDisassembler::Success;
}
-MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
- MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
- raw_ostream &vStream, raw_ostream &cStream) const {
+static DecodeStatus DecodeMoveHRegInstruction(MCInst &Inst, uint64_t Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ DEBUG(dbgs() << "Decoding MOV_S h-register\n");
+ using Field = decltype(Insn);
+ Field h = fieldFromInstruction(Insn, 5, 3) |
+ (fieldFromInstruction(Insn, 0, 2) << 3);
+ Field g = fieldFromInstruction(Insn, 8, 3) |
+ (fieldFromInstruction(Insn, 3, 2) << 3);
+
+ auto DecodeRegisterOrImm = [&Inst, Address, Decoder](Field RegNum,
+ Field Value) {
+ if (30 == RegNum) {
+ Inst.addOperand(MCOperand::createImm(Value));
+ return MCDisassembler::Success;
+ }
+
+ return DecodeGPR32RegisterClass(Inst, RegNum, Address, Decoder);
+ };
+
+ if (MCDisassembler::Success != DecodeRegisterOrImm(g, 0))
+ return MCDisassembler::Fail;
+
+ return DecodeRegisterOrImm(h, Insn >> 16u);
+}
+
+DecodeStatus ARCDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes,
+ uint64_t Address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const {
MCDisassembler::DecodeStatus Result;
if (Bytes.size() < 2) {
Size = 0;
@@ -262,9 +321,9 @@ MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
return Fail;
Result =
decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
- if (Result == MCDisassembler::Success) {
+ if (Success == Result) {
DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
- return MCDisassembler::Success;
+ return Result;
}
DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
}
@@ -274,15 +333,28 @@ MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
}
// Calling the auto-generated decoder function.
return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
- }
+ } else {
+ if (Bytes.size() >= 6) {
+ // Attempt to treat as instr. with limm data.
+ uint64_t Insn48;
+ if (!readInstruction48(Bytes, Address, Size, Insn48))
+ return Fail;
+ Result =
+ decodeInstruction(DecoderTable48, Instr, Insn48, Address, this, STI);
+ if (Success == Result) {
+ DEBUG(dbgs() << "Successfully decoded 16-bit instruction with limm.");
+ return Result;
+ }
+ DEBUG(dbgs() << "Not a 16-bit instruction with limm, try without it.");
+ }
- // 16-bit instruction.
- uint32_t Insn16;
- if (!readInstruction16(Bytes, Address, Size, Insn16)) {
- return Fail;
+ uint32_t Insn16;
+ if (!readInstruction16(Bytes, Address, Size, Insn16))
+ return Fail;
+
+ // Calling the auto-generated decoder function.
+ return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
}
- // Calling the auto-generated decoder function.
- return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
}
static MCDisassembler *createARCDisassembler(const Target &T,
OpenPOWER on IntegriCloud