summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
diff options
context:
space:
mode:
authorMikhail Maltsev <mikhail.maltsev@arm.com>2019-06-11 12:04:32 +0000
committerMikhail Maltsev <mikhail.maltsev@arm.com>2019-06-11 12:04:32 +0000
commit7bd5c55cadc9f7f8f9a677aadd1be652e0c15afb (patch)
tree47b2a71b99c19b5a897c3aa079486e0defe4f9af /llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
parentdd6019526de2f26a9db21b90702fea8cbccc7e7c (diff)
downloadbcm5719-llvm-7bd5c55cadc9f7f8f9a677aadd1be652e0c15afb.tar.gz
bcm5719-llvm-7bd5c55cadc9f7f8f9a677aadd1be652e0c15afb.zip
[ARM] First MVE instructions: scalar shifts.
This introduces a new decoding table for MVE instructions, and starts by adding the family of scalar shift instructions that are part of the MVE architecture extension: saturating shifts within a single GPR, and long shifts across a pair of GPRs (both saturating and normal). Some of these shift instructions have only 3-bit register fields in the encoding, with the low bit fixed. So they can only address an odd or even numbered GPR (depending on the operand), and therefore I add two new register classes, GPREven and GPROdd. Differential Revision: https://reviews.llvm.org/D62668 Change-Id: Iad95d5f83d26aef70c674027a184a6b1e0098d33 llvm-svn: 363051
Diffstat (limited to 'llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index df6a9a15099..ef71cacfa92 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -146,6 +146,10 @@ static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeCLRMGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodetGPROddRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodetGPREvenRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
static DecodeStatus DecodeGPRnopcRegisterClass(MCInst &Inst,
unsigned RegNo, uint64_t Address,
const void *Decoder);
@@ -432,12 +436,18 @@ static DecodeStatus DecodePredNoALOperand(MCInst &Inst, unsigned Val,
const void *Decoder);
static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeLongShiftOperand(MCInst &Inst, unsigned Val,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder);
template<bool Writeback>
static DecodeStatus DecodeVSTRVLDR_SYSREG(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeMVEOverlappingLongShift(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
#include "ARMGenDisassemblerTables.inc"
static MCDisassembler *createARMDisassembler(const Target &T,
@@ -801,6 +811,15 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
uint32_t Insn32 =
(Bytes[3] << 8) | (Bytes[2] << 0) | (Bytes[1] << 24) | (Bytes[0] << 16);
+
+ Result =
+ decodeInstruction(DecoderTableMVE32, MI, Insn32, Address, this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ Check(Result, AddThumbPredicate(MI));
+ return Result;
+ }
+
Result =
decodeInstruction(DecoderTableThumb32, MI, Insn32, Address, this, STI);
if (Result != MCDisassembler::Fail) {
@@ -5643,6 +5662,39 @@ static DecodeStatus DecodeLOLoop(MCInst &Inst, unsigned Insn, uint64_t Address,
return S;
}
+static DecodeStatus DecodeLongShiftOperand(MCInst &Inst, unsigned Val,
+ uint64_t Address,
+ const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ if (Val == 0)
+ Val = 32;
+
+ Inst.addOperand(MCOperand::createImm(Val));
+
+ return S;
+}
+
+static DecodeStatus DecodetGPROddRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if ((RegNo) + 1 > 11)
+ return MCDisassembler::Fail;
+
+ unsigned Register = GPRDecoderTable[(RegNo) + 1];
+ Inst.addOperand(MCOperand::createReg(Register));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodetGPREvenRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder) {
+ if ((RegNo) > 14)
+ return MCDisassembler::Fail;
+
+ unsigned Register = GPRDecoderTable[(RegNo)];
+ Inst.addOperand(MCOperand::createReg(Register));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeVSCCLRM(MCInst &Inst, unsigned Insn, uint64_t Address,
const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
@@ -5726,3 +5778,69 @@ static DecodeStatus DecodeVSTRVLDR_SYSREG(MCInst &Inst, unsigned Val,
return S;
}
+
+static DecodeStatus DecodeMVEOverlappingLongShift(
+ MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) {
+ DecodeStatus S = MCDisassembler::Success;
+
+ unsigned RdaLo = fieldFromInstruction(Insn, 17, 3) << 1;
+ unsigned RdaHi = fieldFromInstruction(Insn, 9, 3) << 1;
+ unsigned Rm = fieldFromInstruction(Insn, 12, 4);
+
+ if (RdaHi == 14) {
+ // This value of RdaHi (really indicating pc, because RdaHi has to
+ // be an odd-numbered register, so the low bit will be set by the
+ // decode function below) indicates that we must decode as SQRSHR
+ // or UQRSHL, which both have a single Rda register field with all
+ // four bits.
+ unsigned Rda = fieldFromInstruction(Insn, 16, 4);
+
+ switch (Inst.getOpcode()) {
+ case ARM::t2ASRLr:
+ case ARM::t2SQRSHRL:
+ Inst.setOpcode(ARM::t2SQRSHR);
+ break;
+ case ARM::t2LSLLr:
+ case ARM::t2UQRSHLL:
+ Inst.setOpcode(ARM::t2UQRSHL);
+ break;
+ default:
+ llvm_unreachable("Unexpected starting opcode!");
+ }
+
+ // Rda as output parameter
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rda, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // Rda again as input parameter
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rda, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // Rm, the amount to shift by
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+ }
+
+ // Otherwise, we decode as whichever opcode our caller has already
+ // put into Inst. Those all look the same:
+
+ // RdaLo,RdaHi as output parameters
+ if (!Check(S, DecodetGPREvenRegisterClass(Inst, RdaLo, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodetGPROddRegisterClass(Inst, RdaHi, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // RdaLo,RdaHi again as input parameters
+ if (!Check(S, DecodetGPREvenRegisterClass(Inst, RdaLo, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodetGPROddRegisterClass(Inst, RdaHi, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ // Rm, the amount to shift by
+ if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
+ return MCDisassembler::Fail;
+
+ return S;
+}
OpenPOWER on IntegriCloud