summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSam Parker <sam.parker@arm.com>2017-09-29 13:11:33 +0000
committerSam Parker <sam.parker@arm.com>2017-09-29 13:11:33 +0000
commit963da5b1191f0ec084247252666d3f669fdaf71c (patch)
tree397d3ead2a6958ba1ccedc93cec935b89036c180 /llvm/lib
parent0b5db55b963a69d45f5712935c60d1ec8e69a511 (diff)
downloadbcm5719-llvm-963da5b1191f0ec084247252666d3f669fdaf71c.tar.gz
bcm5719-llvm-963da5b1191f0ec084247252666d3f669fdaf71c.zip
[ARM] v8.3-a complex number support
New instructions are added to AArch32 and AArch64 to aid floating-point multiplication and addition of complex numbers, where the complex numbers are packed in a vector register as a pair of elements. The Imaginary part of the number is placed in the more significant element, and the Real part of the number is placed in the less significant element. This patch adds assembler for the ARM target. Differential Revision: https://reviews.llvm.org/D36789 llvm-svn: 314511
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/ARM/ARMInstrFormats.td75
-rw-r--r--llvm/lib/Target/ARM/ARMInstrNEON.td133
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp42
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp37
-rw-r--r--llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp9
-rw-r--r--llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h3
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h1
7 files changed, 298 insertions, 2 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index 1bbe7f0d275..8bb64835450 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -69,6 +69,7 @@ def NVExtFrm : Format<39>;
def NVMulSLFrm : Format<40>;
def NVTBLFrm : Format<41>;
def DPSoRegImmFrm : Format<42>;
+def N3RegCplxFrm : Format<43>;
// Misc flags.
@@ -2513,6 +2514,80 @@ multiclass NEONDTAnyInstAlias<string opc, string asm, dag Result, bit EmitPriori
class NEONDataTypeAsmPseudoInst<string opc, string dt, string asm, dag iops> :
AsmPseudoInst<!strconcat(opc, dt, "\t", asm), iops>, Requires<[HasNEON]>;
+// Extension of NEON 3-vector data processing instructions in coprocessor 8
+// encoding space, introduced in ARMv8.3-A.
+class N3VCP8<bits<2> op24_23, bits<2> op21_20, bit op6, bit op4,
+ dag oops, dag iops, InstrItinClass itin,
+ string opc, string dt, string asm, string cstr, list<dag> pattern>
+ : NeonInp<oops, iops, AddrModeNone, IndexModeNone, N3RegCplxFrm, itin, opc,
+ dt, asm, cstr, pattern> {
+ bits<5> Vd;
+ bits<5> Vn;
+ bits<5> Vm;
+
+ let DecoderNamespace = "VFPV8";
+ // These have the same encodings in ARM and Thumb2
+ let PostEncoderMethod = "";
+
+ let Inst{31-25} = 0b1111110;
+ let Inst{24-23} = op24_23;
+ let Inst{22} = Vd{4};
+ let Inst{21-20} = op21_20;
+ let Inst{19-16} = Vn{3-0};
+ let Inst{15-12} = Vd{3-0};
+ let Inst{11-8} = 0b1000;
+ let Inst{7} = Vn{4};
+ let Inst{6} = op6;
+ let Inst{5} = Vm{4};
+ let Inst{4} = op4;
+ let Inst{3-0} = Vm{3-0};
+}
+
+// Extension of NEON 2-vector-and-scalar data processing instructions in
+// coprocessor 8 encoding space, introduced in ARMv8.3-A.
+class N3VLaneCP8<bit op23, bits<2> op21_20, bit op6, bit op4,
+ dag oops, dag iops, InstrItinClass itin,
+ string opc, string dt, string asm, string cstr, list<dag> pattern>
+ : NeonInp<oops, iops, AddrModeNone, IndexModeNone, N3RegCplxFrm, itin, opc,
+ dt, asm, cstr, pattern> {
+ bits<5> Vd;
+ bits<5> Vn;
+ bits<5> Vm;
+
+ let DecoderNamespace = "VFPV8";
+ // These have the same encodings in ARM and Thumb2
+ let PostEncoderMethod = "";
+
+ let Inst{31-24} = 0b11111110;
+ let Inst{23} = op23;
+ let Inst{22} = Vd{4};
+ let Inst{21-20} = op21_20;
+ let Inst{19-16} = Vn{3-0};
+ let Inst{15-12} = Vd{3-0};
+ let Inst{11-8} = 0b1000;
+ let Inst{7} = Vn{4};
+ let Inst{6} = op6;
+ // Bit 5 set by sub-classes
+ let Inst{4} = op4;
+ let Inst{3-0} = Vm{3-0};
+}
+
+// Operand types for complex instructions
+class ComplexRotationOperand<int Angle, int Remainder, string Type>
+ : AsmOperandClass {
+ let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
+ let DiagnosticType = "InvalidComplexRotation" # Type;
+ let Name = "ComplexRotation" # Type;
+}
+def complexrotateop : Operand<i32> {
+ let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
+ let PrintMethod = "printComplexRotationOp<90, 0>";
+}
+def complexrotateopodd : Operand<i32> {
+ let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
+ let PrintMethod = "printComplexRotationOp<180, 90>";
+}
+
// 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/ARMInstrNEON.td b/llvm/lib/Target/ARM/ARMInstrNEON.td
index 495d44f96b8..cd67dded585 100644
--- a/llvm/lib/Target/ARM/ARMInstrNEON.td
+++ b/llvm/lib/Target/ARM/ARMInstrNEON.td
@@ -108,6 +108,7 @@ def nImmSplatI64 : Operand<i32> {
def VectorIndex8Operand : AsmOperandClass { let Name = "VectorIndex8"; }
def VectorIndex16Operand : AsmOperandClass { let Name = "VectorIndex16"; }
def VectorIndex32Operand : AsmOperandClass { let Name = "VectorIndex32"; }
+def VectorIndex64Operand : AsmOperandClass { let Name = "VectorIndex64"; }
def VectorIndex8 : Operand<i32>, ImmLeaf<i32, [{
return ((uint64_t)Imm) < 8;
}]> {
@@ -129,6 +130,13 @@ def VectorIndex32 : Operand<i32>, ImmLeaf<i32, [{
let PrintMethod = "printVectorIndex";
let MIOperandInfo = (ops i32imm);
}
+def VectorIndex64 : Operand<i32>, ImmLeaf<i32, [{
+ return ((uint64_t)Imm) < 1;
+}]> {
+ let ParserMatchClass = VectorIndex64Operand;
+ let PrintMethod = "printVectorIndex";
+ let MIOperandInfo = (ops i32imm);
+}
// Register list of one D register.
def VecListOneDAsmOperand : AsmOperandClass {
@@ -4724,6 +4732,131 @@ def VSDOTQI : DOTI<"vsdot", "s8", 0b1, 0b0, QPR>;
} // HasDotProd
+// ARMv8.3 complex operations
+class BaseN3VCP8ComplexTied<bit op21, bit op4, bit s, bit q,
+ InstrItinClass itin, dag oops, dag iops,
+ string opc, string dt, list<dag> pattern>
+ : N3VCP8<{?,?}, {op21,s}, q, op4, oops,
+ iops, itin, opc, dt, "$Vd, $Vn, $Vm, $rot", "$src1 = $Vd", pattern>{
+ bits<2> rot;
+ let Inst{24-23} = rot;
+}
+
+class BaseN3VCP8ComplexOdd<bit op23, bit op21, bit op4, bit s, bit q,
+ InstrItinClass itin, dag oops, dag iops, string opc,
+ string dt, list<dag> pattern>
+ : N3VCP8<{?,op23}, {op21,s}, q, op4, oops,
+ iops, itin, opc, dt, "$Vd, $Vn, $Vm, $rot", "", pattern> {
+ bits<1> rot;
+ let Inst{24} = rot;
+}
+
+class BaseN3VCP8ComplexTiedLane32<bit op4, bit s, bit q, InstrItinClass itin,
+ dag oops, dag iops, string opc, string dt,
+ list<dag> pattern>
+ : N3VLaneCP8<s, {?,?}, q, op4, oops, iops, itin, opc, dt,
+ "$Vd, $Vn, $Vm$lane, $rot", "$src1 = $Vd", pattern> {
+ bits<2> rot;
+ bit lane;
+
+ let Inst{21-20} = rot;
+ let Inst{5} = lane;
+}
+
+class BaseN3VCP8ComplexTiedLane64<bit op4, bit s, bit q, InstrItinClass itin,
+ dag oops, dag iops, string opc, string dt,
+ list<dag> pattern>
+ : N3VLaneCP8<s, {?,?}, q, op4, oops, iops, itin, opc, dt,
+ "$Vd, $Vn, $Vm$lane, $rot", "$src1 = $Vd", pattern> {
+ bits<2> rot;
+ bit lane;
+
+ let Inst{21-20} = rot;
+ let Inst{5} = Vm{4};
+ // This is needed because the lane operand does not have any bits in the
+ // encoding (it only has one possible value), so we need to manually set it
+ // to it's default value.
+ let DecoderMethod = "DecodeNEONComplexLane64Instruction";
+}
+
+multiclass N3VCP8ComplexTied<bit op21, bit op4,
+ string OpcodeStr, SDPatternOperator Op> {
+ let Predicates = [HasNEON,HasV8_3a,HasFullFP16] in {
+ def v4f16 : BaseN3VCP8ComplexTied<op21, op4, 0, 0, IIC_VMACD, (outs DPR:$Vd),
+ (ins DPR:$src1, DPR:$Vn, DPR:$Vm, complexrotateop:$rot),
+ OpcodeStr, "f16", []>;
+ def v8f16 : BaseN3VCP8ComplexTied<op21, op4, 0, 1, IIC_VMACQ, (outs QPR:$Vd),
+ (ins QPR:$src1, QPR:$Vn, QPR:$Vm, complexrotateop:$rot),
+ OpcodeStr, "f16", []>;
+ }
+ let Predicates = [HasNEON,HasV8_3a] in {
+ def v2f32 : BaseN3VCP8ComplexTied<op21, op4, 1, 0, IIC_VMACD, (outs DPR:$Vd),
+ (ins DPR:$src1, DPR:$Vn, DPR:$Vm, complexrotateop:$rot),
+ OpcodeStr, "f32", []>;
+ def v4f32 : BaseN3VCP8ComplexTied<op21, op4, 1, 1, IIC_VMACQ, (outs QPR:$Vd),
+ (ins QPR:$src1, QPR:$Vn, QPR:$Vm, complexrotateop:$rot),
+ OpcodeStr, "f32", []>;
+ }
+}
+
+multiclass N3VCP8ComplexOdd<bit op23, bit op21, bit op4,
+ string OpcodeStr, SDPatternOperator Op> {
+ let Predicates = [HasNEON,HasV8_3a,HasFullFP16] in {
+ def v4f16 : BaseN3VCP8ComplexOdd<op23, op21, op4, 0, 0, IIC_VMACD,
+ (outs DPR:$Vd),
+ (ins DPR:$Vn, DPR:$Vm, complexrotateopodd:$rot),
+ OpcodeStr, "f16", []>;
+ def v8f16 : BaseN3VCP8ComplexOdd<op23, op21, op4, 0, 1, IIC_VMACQ,
+ (outs QPR:$Vd),
+ (ins QPR:$Vn, QPR:$Vm, complexrotateopodd:$rot),
+ OpcodeStr, "f16", []>;
+ }
+ let Predicates = [HasNEON,HasV8_3a] in {
+ def v2f32 : BaseN3VCP8ComplexOdd<op23, op21, op4, 1, 0, IIC_VMACD,
+ (outs DPR:$Vd),
+ (ins DPR:$Vn, DPR:$Vm, complexrotateopodd:$rot),
+ OpcodeStr, "f32", []>;
+ def v4f32 : BaseN3VCP8ComplexOdd<op23, op21, op4, 1, 1, IIC_VMACQ,
+ (outs QPR:$Vd),
+ (ins QPR:$Vn, QPR:$Vm, complexrotateopodd:$rot),
+ OpcodeStr, "f32", []>;
+ }
+}
+
+// These instructions index by pairs of lanes, so the VectorIndexes are twice
+// as wide as the data types.
+multiclass N3VCP8ComplexTiedLane<bit op4, string OpcodeStr,
+ SDPatternOperator Op> {
+ let Predicates = [HasNEON,HasV8_3a,HasFullFP16] in {
+ def v4f16_indexed : BaseN3VCP8ComplexTiedLane32<op4, 0, 0, IIC_VMACD,
+ (outs DPR:$Vd),
+ (ins DPR:$src1, DPR:$Vn, DPR_VFP2:$Vm,
+ VectorIndex32:$lane, complexrotateop:$rot),
+ OpcodeStr, "f16", []>;
+ def v8f16_indexed : BaseN3VCP8ComplexTiedLane32<op4, 0, 1, IIC_VMACQ,
+ (outs QPR:$Vd),
+ (ins QPR:$src1, QPR:$Vn, DPR_VFP2:$Vm,
+ VectorIndex32:$lane, complexrotateop:$rot),
+ OpcodeStr, "f16", []>;
+ }
+ let Predicates = [HasNEON,HasV8_3a] in {
+ def v2f32_indexed : BaseN3VCP8ComplexTiedLane64<op4, 1, 0, IIC_VMACD,
+ (outs DPR:$Vd),
+ (ins DPR:$src1, DPR:$Vn, DPR:$Vm, VectorIndex64:$lane,
+ complexrotateop:$rot),
+ OpcodeStr, "f32", []>;
+ def v4f32_indexed : BaseN3VCP8ComplexTiedLane64<op4, 1, 1, IIC_VMACQ,
+ (outs QPR:$Vd),
+ (ins QPR:$src1, QPR:$Vn, DPR:$Vm, VectorIndex64:$lane,
+ complexrotateop:$rot),
+ OpcodeStr, "f32", []>;
+ }
+}
+
+defm VCMLA : N3VCP8ComplexTied<1, 0, "vcmla", null_frag>;
+defm VCADD : N3VCP8ComplexOdd<1, 0, 0, "vcadd", null_frag>;
+defm VCMLA : N3VCP8ComplexTiedLane<0, "vcmla", null_frag>;
+
// Vector Subtract Operations.
// VSUB : Vector Subtract (integer and floating-point)
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 287ed20988f..b84a4e8b8e5 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -1756,6 +1756,10 @@ public:
if (Kind != k_VectorIndex) return false;
return VectorIndex.Val < 2;
}
+ bool isVectorIndex64() const {
+ if (Kind != k_VectorIndex) return false;
+ return VectorIndex.Val < 1;
+ }
bool isNEONi8splat() const {
if (!isImm()) return false;
@@ -1885,6 +1889,17 @@ public:
return true;
}
+ template<int64_t Angle, int64_t Remainder>
+ bool isComplexRotation() const {
+ if (!isImm()) return false;
+
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ if (!CE) return false;
+ uint64_t Value = CE->getValue();
+
+ return (Value % Angle == Remainder && Value <= 270);
+ }
+
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediates when possible. Null MCExpr = 0.
if (!Expr)
@@ -2628,6 +2643,11 @@ public:
Inst.addOperand(MCOperand::createImm(getVectorIndex()));
}
+ void addVectorIndex64Operands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createImm(getVectorIndex()));
+ }
+
void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
// The immediate encodes the type of constant as well as the value.
@@ -2740,6 +2760,18 @@ public:
Inst.addOperand(MCOperand::createImm(Imm | 0x1e00));
}
+ void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::createImm(CE->getValue() / 90));
+ }
+
+ void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+ Inst.addOperand(MCOperand::createImm((CE->getValue() - 90) / 180));
+ }
+
void print(raw_ostream &OS) const override;
static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
@@ -5432,7 +5464,8 @@ StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic == "hvc" ||
Mnemonic.startswith("vsel") || Mnemonic == "vins" || Mnemonic == "vmovx" ||
Mnemonic == "bxns" || Mnemonic == "blxns" ||
- Mnemonic == "vudot" || Mnemonic == "vsdot")
+ Mnemonic == "vudot" || Mnemonic == "vsdot" ||
+ Mnemonic == "vcmla" || Mnemonic == "vcadd")
return Mnemonic;
// First, split out any predication code. Ignore mnemonics we know aren't
@@ -5521,7 +5554,8 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") ||
(FullInst.startswith("vmull") && FullInst.endswith(".p64")) ||
Mnemonic == "vmovx" || Mnemonic == "vins" ||
- Mnemonic == "vudot" || Mnemonic == "vsdot") {
+ Mnemonic == "vudot" || Mnemonic == "vsdot" ||
+ Mnemonic == "vcmla" || Mnemonic == "vcadd") {
// These mnemonics are never predicable
CanAcceptPredicationCode = false;
} else if (!isThumb()) {
@@ -9155,6 +9189,10 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(ErrorLoc, "alignment must be 64, 128, 256 or omitted");
}
}
+ case Match_InvalidComplexRotationEven:
+ return Error(IDLoc, "complex rotation must be 0, 90, 180 or 270");
+ case Match_InvalidComplexRotationOdd:
+ return Error(IDLoc, "complex rotation must be 90 or 270");
}
llvm_unreachable("Implement any new match types added!");
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index e3854989c4f..737450d6b34 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -322,6 +322,10 @@ static DecodeStatus DecodeVCVTD(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeVCVTQ(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeNEONComplexLane64Instruction(MCInst &Inst,
+ unsigned Val,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn,
uint64_t Address, const void *Decoder);
@@ -5215,6 +5219,39 @@ static DecodeStatus DecodeVCVTQ(MCInst &Inst, unsigned Insn,
return S;
}
+static DecodeStatus DecodeNEONComplexLane64Instruction(MCInst &Inst,
+ unsigned Insn,
+ uint64_t Address,
+ const void *Decoder) {
+ unsigned Vd = (fieldFromInstruction(Insn, 12, 4) << 0);
+ Vd |= (fieldFromInstruction(Insn, 22, 1) << 4);
+ unsigned Vn = (fieldFromInstruction(Insn, 16, 4) << 0);
+ Vn |= (fieldFromInstruction(Insn, 7, 1) << 4);
+ unsigned Vm = (fieldFromInstruction(Insn, 0, 4) << 0);
+ Vm |= (fieldFromInstruction(Insn, 5, 1) << 4);
+ unsigned q = (fieldFromInstruction(Insn, 6, 1) << 0);
+ unsigned rotate = (fieldFromInstruction(Insn, 20, 2) << 0);
+
+ DecodeStatus S = MCDisassembler::Success;
+
+ auto DestRegDecoder = q ? DecodeQPRRegisterClass : DecodeDPRRegisterClass;
+
+ if (!Check(S, DestRegDecoder(Inst, Vd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DestRegDecoder(Inst, Vd, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DestRegDecoder(Inst, Vn, Address, Decoder)))
+ return MCDisassembler::Fail;
+ if (!Check(S, DecodeDPRRegisterClass(Inst, Vm, Address, Decoder)))
+ return MCDisassembler::Fail;
+ // The lane index does not have any bits in the encoding, because it can only
+ // be 0.
+ Inst.addOperand(MCOperand::createImm(0));
+ Inst.addOperand(MCOperand::createImm(rotate));
+
+ return S;
+}
+
static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
index be6815af2eb..4fc67a4f6eb 100644
--- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
+++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp
@@ -1535,3 +1535,12 @@ void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
printRegName(O, MI->getOperand(OpNum).getReg() + 6);
O << "}";
}
+
+template<int64_t Angle, int64_t Remainder>
+void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Val = MI->getOperand(OpNo).getImm();
+ O << "#" << (Val * Angle) + Remainder;
+}
+
diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
index 86873a3a6cc..7dc311229cc 100644
--- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
+++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.h
@@ -231,6 +231,9 @@ public:
const MCSubtargetInfo &STI, raw_ostream &O);
void printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
+ template<int64_t Angle, int64_t Remainder>
+ void printComplexRotationOp(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
};
} // end namespace llvm
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
index 31f081b77bd..17da82b4ca3 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h
@@ -343,6 +343,7 @@ namespace ARMII {
NVExtFrm = 39 << FormShift,
NVMulSLFrm = 40 << FormShift,
NVTBLFrm = 41 << FormShift,
+ N3RegCplxFrm = 43 << FormShift,
//===------------------------------------------------------------------===//
// Misc flags.
OpenPOWER on IntegriCloud