summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/ARM
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrFormats.td10
-rw-r--r--llvm/lib/Target/ARM/ARMInstrMVE.td36
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp16
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp7
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp8
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h3
6 files changed, 69 insertions, 11 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index bc93a058720..300e35e20da 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -2724,6 +2724,16 @@ def complexrotateopodd : Operand<i32> {
let PrintMethod = "printComplexRotationOp<180, 90>";
}
+def MveSaturateOperand : AsmOperandClass {
+ let PredicateMethod = "isMveSaturateOp";
+ let DiagnosticString = "saturate operand must be 48 or 64";
+ let Name = "MveSaturate";
+}
+def saturateop : Operand<i32> {
+ let ParserMatchClass = MveSaturateOperand;
+ let PrintMethod = "printMveSaturateOp";
+}
+
// Data type suffix token aliases. Implements Table A7-3 in the ARM ARM.
def : TokenAlias<".s8", ".i8">;
def : TokenAlias<".u8", ".i8">;
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index 3e7ae55c7fc..f96b5b91486 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -403,18 +403,17 @@ class MVE_ScalarShiftDRegImm<string iname, bits<2> op5_4, bit op16,
let Inst{3-0} = 0b1111;
}
-class MVE_ScalarShiftDRegReg<string iname, bit op5, bit op16,
- list<dag> pattern=[]>
+class MVE_ScalarShiftDRegRegBase<string iname, dag iops, string asm,
+ bit op5, bit op16, list<dag> pattern=[]>
: MVE_ScalarShiftDoubleReg<
- iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
- "$RdaLo, $RdaHi, $Rm", "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
- "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
+ iname, iops, asm, "@earlyclobber $RdaHi,@earlyclobber $RdaLo,"
+ "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src",
pattern> {
bits<4> Rm;
let Inst{16} = op16;
let Inst{15-12} = Rm{3-0};
- let Inst{7-6} = 0b00;
+ let Inst{6} = 0b0;
let Inst{5} = op5;
let Inst{4} = 0b0;
let Inst{3-0} = 0b1101;
@@ -427,13 +426,30 @@ class MVE_ScalarShiftDRegReg<string iname, bit op5, bit op16,
let DecoderMethod = "DecodeMVEOverlappingLongShift";
}
-def MVE_ASRLr : MVE_ScalarShiftDRegReg<"asrl", 0b1, 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
+class MVE_ScalarShiftDRegReg<string iname, bit op5, list<dag> pattern=[]>
+ : MVE_ScalarShiftDRegRegBase<
+ iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm),
+ "$RdaLo, $RdaHi, $Rm", op5, 0b0, pattern> {
+
+ let Inst{7} = 0b0;
+}
+
+class MVE_ScalarShiftDRegRegWithSat<string iname, bit op5, list<dag> pattern=[]>
+ : MVE_ScalarShiftDRegRegBase<
+ iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm, saturateop:$sat),
+ "$RdaLo, $RdaHi, $sat, $Rm", op5, 0b1, pattern> {
+ bit sat;
+
+ let Inst{7} = sat;
+}
+
+def MVE_ASRLr : MVE_ScalarShiftDRegReg<"asrl", 0b1, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
(ARMasrl tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
def MVE_ASRLi : MVE_ScalarShiftDRegImm<"asrl", 0b10, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
(ARMasrl tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, (i32 imm:$imm)))]>;
-def MVE_LSLLr : MVE_ScalarShiftDRegReg<"lsll", 0b0, 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
+def MVE_LSLLr : MVE_ScalarShiftDRegReg<"lsll", 0b0, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
(ARMlsll tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, rGPR:$Rm))]>;
def MVE_LSLLi : MVE_ScalarShiftDRegImm<"lsll", 0b00, ?, [(set tGPREven:$RdaLo, tGPROdd:$RdaHi,
@@ -443,11 +459,11 @@ def MVE_LSRL : MVE_ScalarShiftDRegImm<"lsrl", 0b01, ?, [(set tGPREven:$Rda
(ARMlsrl tGPREven:$RdaLo_src,
tGPROdd:$RdaHi_src, (i32 imm:$imm)))]>;
-def MVE_SQRSHRL : MVE_ScalarShiftDRegReg<"sqrshrl", 0b1, 0b1>;
+def MVE_SQRSHRL : MVE_ScalarShiftDRegRegWithSat<"sqrshrl", 0b1>;
def MVE_SQSHLL : MVE_ScalarShiftDRegImm<"sqshll", 0b11, 0b1>;
def MVE_SRSHRL : MVE_ScalarShiftDRegImm<"srshrl", 0b10, 0b1>;
-def MVE_UQRSHLL : MVE_ScalarShiftDRegReg<"uqrshll", 0b0, 0b1>;
+def MVE_UQRSHLL : MVE_ScalarShiftDRegRegWithSat<"uqrshll", 0b0>;
def MVE_UQSHLL : MVE_ScalarShiftDRegImm<"uqshll", 0b00, 0b1>;
def MVE_URSHRL : MVE_ScalarShiftDRegImm<"urshrl", 0b01, 0b1>;
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 1da9452f1d2..29353d5f349 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -2275,6 +2275,14 @@ public:
return Value >= 1 && Value <= 32;
}
+ bool isMveSaturateOp() const {
+ if (!isImm()) return false;
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ uint64_t Value = CE->getValue();
+ return Value == 48 || Value == 64;
+ }
+
bool isITCondCodeNoAL() const {
if (!isITCondCode()) return false;
ARMCC::CondCodes CC = getCondCode();
@@ -3370,6 +3378,14 @@ public:
Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180));
}
+ void addMveSaturateOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ unsigned Imm = CE->getValue();
+ assert((Imm == 48 || Imm == 64) && "Invalid saturate operand");
+ Inst.addOperand(MCOperand::createImm(Imm == 48 ? 1 : 0));
+ }
+
void print(raw_ostream &OS) const override;
static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index 673691ebd93..2bb88eec453 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -6503,6 +6503,13 @@ static DecodeStatus DecodeMVEOverlappingLongShift(
if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;
+ if (Inst.getOpcode() == ARM::MVE_SQRSHRL ||
+ Inst.getOpcode() == ARM::MVE_UQRSHLL) {
+ unsigned Saturate = fieldFromInstruction(Insn, 7, 1);
+ // Saturate, the bit position for saturation
+ Inst.addOperand(MCOperand::createImm(Saturate));
+ }
+
return S;
}
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
index 45be1ee9634..30b82faa0ed 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
@@ -1676,3 +1676,11 @@ void ARMInstPrinter::printExpandedImmOperand(const MCInst *MI, unsigned OpNum,
O.write_hex(Val);
O << markup(">");
}
+
+void ARMInstPrinter::printMveSaturateOp(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ uint32_t Val = MI->getOperand(OpNum).getImm();
+ assert(Val <= 1 && "Invalid MVE saturate operand");
+ O << "#" << (Val == 1 ? 48 : 64);
+}
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
index 69026956b60..7b02198d02e 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
@@ -262,7 +262,8 @@ public:
const MCSubtargetInfo &STI, raw_ostream &O);
void printExpandedImmOperand(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
-
+ void printMveSaturateOp(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
private:
unsigned DefaultAltIdx = ARM::NoRegAltName;
};
OpenPOWER on IntegriCloud