diff options
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrInfo.td | 6 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrMVE.td | 130 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMInstrThumb2.td | 10 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMRegisterInfo.td | 14 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 118 |
7 files changed, 294 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td index 2888c8b0d8f..ed634144562 100644 --- a/llvm/lib/Target/ARM/ARMInstrInfo.td +++ b/llvm/lib/Target/ARM/ARMInstrInfo.td @@ -5759,6 +5759,12 @@ include "ARMInstrVFP.td" include "ARMInstrNEON.td" //===----------------------------------------------------------------------===// +// MVE Support +// + +include "ARMInstrMVE.td" + +//===----------------------------------------------------------------------===// // Assembler aliases // diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td new file mode 100644 index 00000000000..06fb3ece389 --- /dev/null +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -0,0 +1,130 @@ +//===-- ARMInstrMVE.td - MVE support for ARM ---------------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file describes the ARM MVE instruction set. +// +//===----------------------------------------------------------------------===// + +class MVE_MI_with_pred<dag oops, dag iops, InstrItinClass itin, string asm, + string ops, string cstr, list<dag> pattern> + : Thumb2I<oops, iops, AddrModeNone, 4, itin, asm, !strconcat("\t", ops), cstr, + pattern>, + Requires<[HasV8_1MMainline, HasMVEInt]> { + let D = MVEDomain; + let DecoderNamespace = "MVE"; +} + +class t2MVEShift<string iname, dag oops, dag iops, string asm, string cstr, + list<dag> pattern=[]> + : MVE_MI_with_pred<oops, iops, NoItinerary, iname, asm, cstr, pattern> { + let Inst{31-20} = 0b111010100101; + let Inst{8} = 0b1; + +} + +class t2MVEShiftSingleReg<string iname, dag iops, string asm, string cstr, + list<dag> pattern=[]> + : t2MVEShift<iname, (outs rGPR:$RdaDest), iops, asm, cstr, pattern> { + bits<4> RdaDest; + + let Inst{19-16} = RdaDest{3-0}; +} + +class t2MVEShiftSRegImm<string iname, bits<2> op5_4, list<dag> pattern=[]> + : t2MVEShiftSingleReg<iname, (ins rGPR:$RdaSrc, long_shift:$imm), + "$RdaSrc, $imm", "$RdaDest = $RdaSrc", pattern> { + bits<5> imm; + + let Inst{15} = 0b0; + let Inst{14-12} = imm{4-2}; + let Inst{11-8} = 0b1111; + let Inst{7-6} = imm{1-0}; + let Inst{5-4} = op5_4{1-0}; + let Inst{3-0} = 0b1111; +} + +def t2SQSHL : t2MVEShiftSRegImm<"sqshl", 0b11>; +def t2SRSHR : t2MVEShiftSRegImm<"srshr", 0b10>; +def t2UQSHL : t2MVEShiftSRegImm<"uqshl", 0b00>; +def t2URSHR : t2MVEShiftSRegImm<"urshr", 0b01>; + +class t2MVEShiftSRegReg<string iname, bits<2> op5_4, list<dag> pattern=[]> + : t2MVEShiftSingleReg<iname, (ins rGPR:$RdaSrc, rGPR:$Rm), + "$RdaSrc, $Rm", "$RdaDest = $RdaSrc", pattern> { + bits<4> Rm; + + let Inst{15-12} = Rm{3-0}; + let Inst{11-8} = 0b1111; + let Inst{7-6} = 0b00; + let Inst{5-4} = op5_4{1-0}; + let Inst{3-0} = 0b1101; +} + +def t2SQRSHR : t2MVEShiftSRegReg<"sqrshr", 0b10>; +def t2UQRSHL : t2MVEShiftSRegReg<"uqrshl", 0b00>; + +class t2MVEShiftDoubleReg<string iname, dag iops, string asm, string cstr, + list<dag> pattern=[]> + : t2MVEShift<iname, (outs tGPREven:$RdaLo, tGPROdd:$RdaHi), iops, asm, cstr, + pattern> { + bits<4> RdaLo; + bits<4> RdaHi; + + let Inst{19-17} = RdaLo{3-1}; + let Inst{11-9} = RdaHi{3-1}; +} + +class t2MVEShiftDRegImm<string iname, bits<2> op5_4, bit op16, list<dag> pattern=[]> + : t2MVEShiftDoubleReg<iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, + long_shift:$imm), "$RdaLo, $RdaHi, $imm", + "$RdaLo = $RdaLo_src,$RdaHi = $RdaHi_src", pattern> { + bits<5> imm; + + let Inst{16} = op16; + let Inst{15} = 0b0; + let Inst{14-12} = imm{4-2}; + let Inst{7-6} = imm{1-0}; + let Inst{5-4} = op5_4{1-0}; + let Inst{3-0} = 0b1111; +} + +class t2MVEShiftDRegReg<string iname, bit op5, bit op16, list<dag> pattern=[]> + : t2MVEShiftDoubleReg<iname, (ins tGPREven:$RdaLo_src, tGPROdd:$RdaHi_src, rGPR:$Rm), + "$RdaLo, $RdaHi, $Rm", + "@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{5} = op5; + let Inst{4} = 0b0; + let Inst{3-0} = 0b1101; + + // Custom decoder method because of the following overlapping encodings: + // ASRL and SQRSHR + // LSLL and UQRSHL + // SQRSHRL and SQRSHR + // UQRSHLL and UQRSHL + let DecoderMethod = "DecodeMVEOverlappingLongShift"; +} + +def t2ASRLr : t2MVEShiftDRegReg<"asrl", 0b1, 0b0>; +def t2ASRLi : t2MVEShiftDRegImm<"asrl", 0b10, ?>; +def t2LSLLr : t2MVEShiftDRegReg<"lsll", 0b0, 0b0>; +def t2LSLLi : t2MVEShiftDRegImm<"lsll", 0b00, ?>; +def t2LSRL : t2MVEShiftDRegImm<"lsrl", 0b01, ?>; + +def t2SQRSHRL : t2MVEShiftDRegReg<"sqrshrl", 0b1, 0b1>; +def t2SQSHLL : t2MVEShiftDRegImm<"sqshll", 0b11, 0b1>; +def t2SRSHRL : t2MVEShiftDRegImm<"srshrl", 0b10, 0b1>; + +def t2UQRSHLL : t2MVEShiftDRegReg<"uqrshll", 0b0, 0b1>; +def t2UQSHLL : t2MVEShiftDRegImm<"uqshll", 0b00, 0b1>; +def t2URSHRL : t2MVEShiftDRegImm<"urshrl", 0b01, 0b1>; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index e324dbe5466..1f7d28a4c8b 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -39,6 +39,16 @@ def t2_shift_imm : Operand<i32> { let DecoderMethod = "DecodeT2ShifterImmOperand"; } +def mve_shift_imm : AsmOperandClass { + let Name = "MVELongShift"; + let RenderMethod = "addImmOperands"; + let DiagnosticString = "operand must be an immediate in the range [1,32]"; +} +def long_shift : Operand<i32> { + let ParserMatchClass = mve_shift_imm; + let DecoderMethod = "DecodeLongShiftOperand"; +} + // Shifted operands. No register controlled shifts for Thumb2. // Note: We do not support rrx shifted operands yet. def t2_so_reg : Operand<i32>, // reg imm diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp index 4566ac2c9dd..f3253c8806c 100644 --- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -181,6 +181,13 @@ const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( case tGPR_and_tcGPRRegClassID: case tcGPRRegClassID: case tGPRRegClassID: + case tGPREvenRegClassID: + case tGPROddRegClassID: + case tGPR_and_tGPREvenRegClassID: + case tGPR_and_tGPROddRegClassID: + case tGPREven_and_tcGPRRegClassID: + case tGPREven_and_tGPR_and_tcGPRRegClassID: + case tGPROdd_and_tcGPRRegClassID: return getRegBank(ARM::GPRRegBankID); case HPRRegClassID: case SPR_8RegClassID: diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td index 43e6b2aa1b9..9b72c5fa73b 100644 --- a/llvm/lib/Target/ARM/ARMRegisterInfo.td +++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td @@ -331,6 +331,20 @@ def tcGPR : RegisterClass<"ARM", [i32], 32, (add R0, R1, R2, R3, R12)> { }]; } +def tGPROdd : RegisterClass<"ARM", [i32], 32, (add R1, R3, R5, R7, R9, R11)> { + let AltOrders = [(and tGPROdd, tGPR)]; + let AltOrderSelect = [{ + return MF.getSubtarget<ARMSubtarget>().isThumb1Only(); + }]; +} + +def tGPREven : RegisterClass<"ARM", [i32], 32, (add R0, R2, R4, R6, R8, R10, R12, LR)> { + let AltOrders = [(and tGPREven, tGPR)]; + let AltOrderSelect = [{ + return MF.getSubtarget<ARMSubtarget>().isThumb1Only(); + }]; +} + // Condition code registers. def CCR : RegisterClass<"ARM", [i32], 32, (add CPSR)> { let CopyCost = -1; // Don't allow copying of status registers. diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 7451b931c84..f8dc24a4267 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -2048,6 +2048,15 @@ public: return (Value % Angle == Remainder && Value <= 270); } + bool isMVELongShift() const { + if (!isImm()) return false; + const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); + // Must be a constant. + if (!CE) return false; + uint64_t Value = CE->getValue(); + return Value >= 1 && Value <= 32; + } + bool isITCondCodeNoAL() const { if (!isITCondCode()) return false; auto CC = (ARMCC::CondCodes) getCondCode(); 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; +} |