2012-02-18 20:03:15 +08:00
|
|
|
|
//===-- ARMInstrFormats.td - ARM Instruction Formats -------*- tablegen -*-===//
|
2010-03-24 01:23:59 +08:00
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
|
// 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
|
2010-03-24 01:23:59 +08:00
|
|
|
|
//
|
2008-08-29 07:39:26 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
//
|
|
|
|
|
// ARM Instruction Format Definitions.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
// Format specifies the encoding used by the instruction. This is part of the
|
|
|
|
|
// ad-hoc solution used to emit machine instruction encodings by our machine
|
|
|
|
|
// code emitter.
|
2010-03-18 05:13:43 +08:00
|
|
|
|
class Format<bits<6> val> {
|
|
|
|
|
bits<6> Value = val;
|
2008-08-29 07:39:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-14 07:36:57 +08:00
|
|
|
|
def Pseudo : Format<0>;
|
|
|
|
|
def MulFrm : Format<1>;
|
|
|
|
|
def BrFrm : Format<2>;
|
|
|
|
|
def BrMiscFrm : Format<3>;
|
|
|
|
|
|
|
|
|
|
def DPFrm : Format<4>;
|
2011-07-22 07:38:37 +08:00
|
|
|
|
def DPSoRegRegFrm : Format<5>;
|
2008-11-14 07:36:57 +08:00
|
|
|
|
|
|
|
|
|
def LdFrm : Format<6>;
|
|
|
|
|
def StFrm : Format<7>;
|
|
|
|
|
def LdMiscFrm : Format<8>;
|
|
|
|
|
def StMiscFrm : Format<9>;
|
|
|
|
|
def LdStMulFrm : Format<10>;
|
|
|
|
|
|
2010-03-20 01:39:00 +08:00
|
|
|
|
def LdStExFrm : Format<11>;
|
2009-12-11 09:42:04 +08:00
|
|
|
|
|
2010-03-20 01:39:00 +08:00
|
|
|
|
def ArithMiscFrm : Format<12>;
|
2010-08-11 08:01:18 +08:00
|
|
|
|
def SatFrm : Format<13>;
|
|
|
|
|
def ExtFrm : Format<14>;
|
2008-11-14 07:36:57 +08:00
|
|
|
|
|
2010-08-11 08:01:18 +08:00
|
|
|
|
def VFPUnaryFrm : Format<15>;
|
|
|
|
|
def VFPBinaryFrm : Format<16>;
|
|
|
|
|
def VFPConv1Frm : Format<17>;
|
|
|
|
|
def VFPConv2Frm : Format<18>;
|
|
|
|
|
def VFPConv3Frm : Format<19>;
|
|
|
|
|
def VFPConv4Frm : Format<20>;
|
|
|
|
|
def VFPConv5Frm : Format<21>;
|
|
|
|
|
def VFPLdStFrm : Format<22>;
|
|
|
|
|
def VFPLdStMulFrm : Format<23>;
|
|
|
|
|
def VFPMiscFrm : Format<24>;
|
2008-11-14 07:36:57 +08:00
|
|
|
|
|
2010-08-11 08:01:18 +08:00
|
|
|
|
def ThumbFrm : Format<25>;
|
|
|
|
|
def MiscFrm : Format<26>;
|
2008-11-06 02:35:52 +08:00
|
|
|
|
|
2010-08-11 08:01:18 +08:00
|
|
|
|
def NGetLnFrm : Format<27>;
|
|
|
|
|
def NSetLnFrm : Format<28>;
|
|
|
|
|
def NDupFrm : Format<29>;
|
|
|
|
|
def NLdStFrm : Format<30>;
|
|
|
|
|
def N1RegModImmFrm: Format<31>;
|
|
|
|
|
def N2RegFrm : Format<32>;
|
|
|
|
|
def NVCVTFrm : Format<33>;
|
|
|
|
|
def NVDupLnFrm : Format<34>;
|
|
|
|
|
def N2RegVShLFrm : Format<35>;
|
|
|
|
|
def N2RegVShRFrm : Format<36>;
|
|
|
|
|
def N3RegFrm : Format<37>;
|
|
|
|
|
def N3RegVShFrm : Format<38>;
|
|
|
|
|
def NVExtFrm : Format<39>;
|
|
|
|
|
def NVMulSLFrm : Format<40>;
|
|
|
|
|
def NVTBLFrm : Format<41>;
|
2011-07-22 07:38:37 +08:00
|
|
|
|
def DPSoRegImmFrm : Format<42>;
|
2017-09-29 21:11:33 +08:00
|
|
|
|
def N3RegCplxFrm : Format<43>;
|
2010-03-20 08:17:00 +08:00
|
|
|
|
|
2009-07-08 09:46:35 +08:00
|
|
|
|
// Misc flags.
|
|
|
|
|
|
2010-12-01 10:42:55 +08:00
|
|
|
|
// The instruction has an Rn register operand.
|
2009-07-08 09:46:35 +08:00
|
|
|
|
// UnaryDP - Indicates this is a unary data processing instruction, i.e.
|
|
|
|
|
// it doesn't have a Rn operand.
|
|
|
|
|
class UnaryDP { bit isUnaryDataProc = 1; }
|
|
|
|
|
|
|
|
|
|
// Xform16Bit - Indicates this Thumb2 instruction may be transformed into
|
|
|
|
|
// a 16-bit Thumb instruction if certain conditions are met.
|
|
|
|
|
class Xform16Bit { bit canXformTo16Bit = 1; }
|
2008-08-29 07:39:26 +08:00
|
|
|
|
|
2009-06-29 15:51:04 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
2010-03-19 07:57:57 +08:00
|
|
|
|
// ARM Instruction flags. These need to match ARMBaseInstrInfo.h.
|
2009-06-29 15:51:04 +08:00
|
|
|
|
//
|
|
|
|
|
|
2011-01-19 03:59:19 +08:00
|
|
|
|
// FIXME: Once the JIT is MC-ized, these can go away.
|
2009-06-29 15:51:04 +08:00
|
|
|
|
// Addressing mode.
|
2010-10-06 02:14:55 +08:00
|
|
|
|
class AddrMode<bits<5> val> {
|
|
|
|
|
bits<5> Value = val;
|
2009-06-29 15:51:04 +08:00
|
|
|
|
}
|
2010-08-31 15:50:46 +08:00
|
|
|
|
def AddrModeNone : AddrMode<0>;
|
|
|
|
|
def AddrMode1 : AddrMode<1>;
|
|
|
|
|
def AddrMode2 : AddrMode<2>;
|
|
|
|
|
def AddrMode3 : AddrMode<3>;
|
|
|
|
|
def AddrMode4 : AddrMode<4>;
|
|
|
|
|
def AddrMode5 : AddrMode<5>;
|
|
|
|
|
def AddrMode6 : AddrMode<6>;
|
|
|
|
|
def AddrModeT1_1 : AddrMode<7>;
|
|
|
|
|
def AddrModeT1_2 : AddrMode<8>;
|
|
|
|
|
def AddrModeT1_4 : AddrMode<9>;
|
|
|
|
|
def AddrModeT1_s : AddrMode<10>;
|
|
|
|
|
def AddrModeT2_i12 : AddrMode<11>;
|
|
|
|
|
def AddrModeT2_i8 : AddrMode<12>;
|
|
|
|
|
def AddrModeT2_so : AddrMode<13>;
|
|
|
|
|
def AddrModeT2_pc : AddrMode<14>;
|
2009-07-02 07:16:05 +08:00
|
|
|
|
def AddrModeT2_i8s4 : AddrMode<15>;
|
2010-10-27 06:37:02 +08:00
|
|
|
|
def AddrMode_i12 : AddrMode<16>;
|
[ARM] Armv8.2-A FP16 code generation (part 1/3)
This is the groundwork for Armv8.2-A FP16 code generation .
Clang passes and returns _Float16 values as floats, together with the required
bitconverts and truncs etc. to implement correct AAPCS behaviour, see D42318.
We will implement half-precision argument passing/returning lowering in the ARM
backend soon, but for now this means that this:
_Float16 sub(_Float16 a, _Float16 b) {
return a + b;
}
gets lowered to this:
define float @sub(float %a.coerce, float %b.coerce) {
entry:
%0 = bitcast float %a.coerce to i32
%tmp.0.extract.trunc = trunc i32 %0 to i16
%1 = bitcast i16 %tmp.0.extract.trunc to half
<SNIP>
%add = fadd half %1, %3
<SNIP>
}
When FullFP16 is *not* supported, we don't make f16 a legal type, and we get
legalization for "free", i.e. nothing changes and everything works as before.
And also f16 argument passing/returning is handled.
When FullFP16 is supported, we do make f16 a legal type, and have 2 places that
we need to patch up: f16 argument passing and returning, which involves minor
tweaks to avoid unnecessary code generation for some bitcasts.
As a "demonstrator" that this works for the different FP16, FullFP16, softfp
modes, etc., I've added match rules to the VSUB instruction description showing
that we can codegen this instruction from IR, but more importantly, also to
some conversion instructions. These conversions were causing issue before in
the FP16 and FullFP16 cases.
I've also added match rules to the VLDRH and VSTRH desriptions, so that we can
actually compile the entire half-precision sub code example above. This showed
that these loads and stores had the wrong addressing mode specified: AddrMode5
instead of AddrMode5FP16, which turned out not be implemented at all, so that
has also been added.
This is the minimal patch that shows all the different moving parts. In patch
2/3 I will add some efficient lowering of bitcasts, and in 2/3 I will add the
remaining Armv8.2-A FP16 instruction descriptions.
Thanks to Sam Parker and Oliver Stannard for their help and reviews!
Differential Revision: https://reviews.llvm.org/D38315
llvm-svn: 323512
2018-01-26 17:26:40 +08:00
|
|
|
|
def AddrMode5FP16 : AddrMode<17>;
|
2018-09-07 17:21:25 +08:00
|
|
|
|
def AddrModeT2_ldrex : AddrMode<18>;
|
[ARM] Add the non-MVE instructions in Arm v8.1-M.
This adds support for the new family of conditional selection /
increment / negation instructions; the low-overhead branch
instructions (e.g. BF, WLS, DLS); the CLRM instruction to zero a whole
list of registers at once; the new VMRS/VMSR and VLDR/VSTR
instructions to get data in and out of 8.1-M system registers,
particularly including the new VPR register used by MVE vector
predication.
To support this, we also add a register name 'zr' (used by the CSEL
family to force one of the inputs to the constant 0), and operand
types for lists of registers that are also allowed to include APSR or
VPR (used by CLRM). The VLDR/VSTR instructions also need a new
addressing mode.
The low-overhead branch instructions exist in their own separate
architecture extension, which we treat as enabled by default, but you
can say -mattr=-lob or equivalent to turn it off.
Reviewers: dmgreen, samparker, SjoerdMeijer, t.p.northover
Reviewed By: samparker
Subscribers: miyuki, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62667
llvm-svn: 363039
2019-06-11 17:29:18 +08:00
|
|
|
|
def AddrModeT2_i7s4 : AddrMode<19>;
|
[ARM] Add MVE vector load/store instructions.
This adds the rest of the vector memory access instructions. It
includes contiguous loads/stores, with an ordinary addressing mode
such as [r0,#offset] (plus writeback variants); gather loads and
scatter stores with a scalar base address register and a vector of
offsets from it (written [r0,q1] or similar); and gather/scatters with
a vector of base addresses (written [q0,#offset], again with
writeback). Additionally, some of the loads can widen each loaded
value into a larger vector lane, and the corresponding stores narrow
them again.
To implement these, we also have to add the addressing modes they
need. Also, in AsmParser, the `isMem` query function now has
subqueries `isGPRMem` and `isMVEMem`, according to which kind of base
register is used by a given memory access operand.
I've also had to add an extra check in `checkTargetMatchPredicate` in
the AsmParser, without which our last-minute check of `rGPR` register
operands against SP and PC was failing an assertion because Tablegen
had inserted an immediate 0 in place of one of a pair of tied register
operands. (This matches the way the corresponding check for `MCK_rGPR`
in `validateTargetOperandClass` is guarded.) Apparently the MVE load
instructions were the first to have ever triggered this assertion, but
I think only because they were the first to have a combination of the
usual Arm pre/post writeback system and the `rGPR` class in particular.
Reviewers: dmgreen, samparker, SjoerdMeijer, t.p.northover
Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62680
llvm-svn: 364291
2019-06-25 19:24:18 +08:00
|
|
|
|
def AddrModeT2_i7s2 : AddrMode<20>;
|
|
|
|
|
def AddrModeT2_i7 : AddrMode<21>;
|
2009-06-29 15:51:04 +08:00
|
|
|
|
|
|
|
|
|
// Load / store index mode.
|
|
|
|
|
class IndexMode<bits<2> val> {
|
|
|
|
|
bits<2> Value = val;
|
|
|
|
|
}
|
|
|
|
|
def IndexModeNone : IndexMode<0>;
|
|
|
|
|
def IndexModePre : IndexMode<1>;
|
|
|
|
|
def IndexModePost : IndexMode<2>;
|
2010-03-13 15:34:35 +08:00
|
|
|
|
def IndexModeUpd : IndexMode<3>;
|
2009-06-29 15:51:04 +08:00
|
|
|
|
|
2009-11-02 08:10:38 +08:00
|
|
|
|
// Instruction execution domain.
|
2019-05-30 16:07:06 +08:00
|
|
|
|
class Domain<bits<4> val> {
|
|
|
|
|
bits<4> Value = val;
|
2009-11-02 08:10:38 +08:00
|
|
|
|
}
|
|
|
|
|
def GenericDomain : Domain<0>;
|
|
|
|
|
def VFPDomain : Domain<1>; // Instructions in VFP domain only
|
|
|
|
|
def NeonDomain : Domain<2>; // Instructions in Neon domain only
|
|
|
|
|
def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains
|
2011-02-23 10:35:33 +08:00
|
|
|
|
def VFPNeonA8Domain : Domain<5>; // Instructions in VFP & Neon under A8
|
2019-05-30 16:07:06 +08:00
|
|
|
|
def MVEDomain : Domain<8>; // Instructions in MVE and ARMv8.1m
|
2009-11-02 08:10:38 +08:00
|
|
|
|
|
2008-08-29 07:39:26 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-07-11 14:43:01 +08:00
|
|
|
|
// ARM special operands.
|
|
|
|
|
//
|
|
|
|
|
|
2011-07-26 04:38:18 +08:00
|
|
|
|
// ARM imod and iflag operands, used only by the CPS instruction.
|
|
|
|
|
def imod_op : Operand<i32> {
|
|
|
|
|
let PrintMethod = "printCPSIMod";
|
2011-02-08 06:09:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-14 21:09:44 +08:00
|
|
|
|
def ProcIFlagsOperand : AsmOperandClass {
|
|
|
|
|
let Name = "ProcIFlags";
|
2011-07-26 04:14:50 +08:00
|
|
|
|
let ParserMethod = "parseProcIFlagsOperand";
|
2011-02-14 21:09:44 +08:00
|
|
|
|
}
|
|
|
|
|
def iflags_op : Operand<i32> {
|
|
|
|
|
let PrintMethod = "printCPSIFlag";
|
|
|
|
|
let ParserMatchClass = ProcIFlagsOperand;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-11 14:43:01 +08:00
|
|
|
|
// ARM Predicate operand. Default to 14 = always (AL). Second part is CC
|
|
|
|
|
// register whose default is 0 (no register).
|
2011-07-26 04:38:18 +08:00
|
|
|
|
def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; }
|
2011-08-20 04:46:54 +08:00
|
|
|
|
def pred : PredicateOperand<OtherVT, (ops i32imm, i32imm),
|
2009-07-11 14:43:01 +08:00
|
|
|
|
(ops (i32 14), (i32 zero_reg))> {
|
|
|
|
|
let PrintMethod = "printPredicateOperand";
|
2010-08-11 14:36:53 +08:00
|
|
|
|
let ParserMatchClass = CondCodeOperand;
|
2011-08-20 04:30:19 +08:00
|
|
|
|
let DecoderMethod = "DecodePredicateOperand";
|
2009-07-11 14:43:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-08-22 17:57:11 +08:00
|
|
|
|
// Selectable predicate operand for CMOV instructions. We can't use a normal
|
|
|
|
|
// predicate because the default values interfere with instruction selection. In
|
|
|
|
|
// all other respects it is identical though: pseudo-instruction expansion
|
|
|
|
|
// relies on the MachineOperands being compatible.
|
|
|
|
|
def cmovpred : Operand<i32>, PredicateOp,
|
|
|
|
|
ComplexPattern<i32, 2, "SelectCMOVPred"> {
|
|
|
|
|
let MIOperandInfo = (ops i32imm, i32imm);
|
|
|
|
|
let PrintMethod = "printPredicateOperand";
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-11 14:43:01 +08:00
|
|
|
|
// Conditional code result for instructions whose 's' bit is set, e.g. subs.
|
2011-07-26 04:38:18 +08:00
|
|
|
|
def CCOutOperand : AsmOperandClass { let Name = "CCOut"; }
|
2009-07-11 14:43:01 +08:00
|
|
|
|
def cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 zero_reg))> {
|
2010-11-15 13:19:05 +08:00
|
|
|
|
let EncoderMethod = "getCCOutOpValue";
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let PrintMethod = "printSBitModifierOperand";
|
2010-12-07 02:21:12 +08:00
|
|
|
|
let ParserMatchClass = CCOutOperand;
|
2011-08-20 03:41:46 +08:00
|
|
|
|
let DecoderMethod = "DecodeCCOutOperand";
|
2009-07-11 14:43:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Same as cc_out except it defaults to setting CPSR.
|
|
|
|
|
def s_cc_out : OptionalDefOperand<OtherVT, (ops CCR), (ops (i32 CPSR))> {
|
2010-11-15 13:19:05 +08:00
|
|
|
|
let EncoderMethod = "getCCOutOpValue";
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let PrintMethod = "printSBitModifierOperand";
|
2010-12-07 02:21:12 +08:00
|
|
|
|
let ParserMatchClass = CCOutOperand;
|
2011-08-20 03:41:46 +08:00
|
|
|
|
let DecoderMethod = "DecodeCCOutOperand";
|
2009-07-11 14:43:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-03 18:53:07 +08:00
|
|
|
|
// Transform to generate the inverse of a condition code during ISel
|
|
|
|
|
def inv_cond_XFORM : SDNodeXForm<imm, [{
|
|
|
|
|
ARMCC::CondCodes CC = static_cast<ARMCC::CondCodes>(N->getZExtValue());
|
|
|
|
|
return CurDAG->getTargetConstant(ARMCC::getOppositeCondition(CC), SDLoc(N),
|
|
|
|
|
MVT::i32);
|
|
|
|
|
}]>;
|
|
|
|
|
|
[ARM] Set up infrastructure for MVE vector instructions.
This commit prepares the way to start adding the main collection of
MVE instructions, which operate on the 128-bit vector registers.
The most obvious thing that's needed, and the simplest, is to add the
MQPR register class, which is like the existing QPR except that it has
fewer registers in it.
The more complicated part: MVE defines a system of vector predication,
in which instructions operating on 128-bit vector registers can be
constrained to operate on only a subset of the lanes, using a system
of prefix instructions similar to the existing Thumb IT, in that you
have one prefix instruction which designates up to 4 following
instructions as subject to predication, and within that sequence, the
predicate can be inverted by means of T/E suffixes ('Then' / 'Else').
To support instructions of this type, we've added two new Tablegen
classes `vpred_n` and `vpred_r` for standard clusters of MC operands
to add to a predicated instruction. Both include a flag indicating how
the instruction is predicated at all (options are T, E and 'not
predicated'), and an input register field for the register controlling
the set of active lanes. They differ from each other in that `vpred_r`
also includes an input operand for the previous value of the output
register, for instructions that leave inactive lanes unchanged.
`vpred_n` lacks that extra operand; it will be used for instructions
that don't preserve inactive lanes in their output register (either
because inactive lanes are zeroed, as the MVE load instructions do, or
because the output register isn't a vector at all).
This commit also adds the family of prefix instructions themselves
(VPT / VPST), and all the machinery needed to work with them in
assembly and disassembly (e.g. generating the 't' and 'e' mnemonic
suffixes on disassembled instructions within a predicated block)
I've added a couple of demo instructions that derive from the new
Tablegen base classes and use those two operand clusters. The bulk of
the vector instructions will come in followup commits small enough to
be manageable. (One exception is that I've added the full version of
`isMnemonicVPTPredicable` in the AsmParser, because it seemed
pointless to carefully split it up.)
Reviewers: dmgreen, samparker, SjoerdMeijer, t.p.northover
Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62669
llvm-svn: 363258
2019-06-13 21:11:13 +08:00
|
|
|
|
// VPT predicate
|
|
|
|
|
|
|
|
|
|
def VPTPredNOperand : AsmOperandClass {
|
|
|
|
|
let Name = "VPTPredN";
|
|
|
|
|
let PredicateMethod = "isVPTPred";
|
|
|
|
|
}
|
|
|
|
|
def VPTPredROperand : AsmOperandClass {
|
|
|
|
|
let Name = "VPTPredR";
|
|
|
|
|
let PredicateMethod = "isVPTPred";
|
|
|
|
|
}
|
|
|
|
|
def undef_tied_input;
|
|
|
|
|
|
|
|
|
|
// Operand classes for the cluster of MC operands describing a
|
|
|
|
|
// VPT-predicated MVE instruction.
|
|
|
|
|
//
|
|
|
|
|
// There are two of these classes. Both of them have the same first
|
|
|
|
|
// two options:
|
|
|
|
|
//
|
|
|
|
|
// $cond (an integer) indicates the instruction's predication status:
|
|
|
|
|
// * ARMVCC::None means it's unpredicated
|
|
|
|
|
// * ARMVCC::Then means it's in a VPT block and appears with the T suffix
|
|
|
|
|
// * ARMVCC::Else means it's in a VPT block and appears with the E suffix.
|
|
|
|
|
// During code generation, unpredicated and predicated instructions
|
|
|
|
|
// are indicated by setting this parameter to 'None' or to 'Then'; the
|
|
|
|
|
// third value 'Else' is only used for assembly and disassembly.
|
|
|
|
|
//
|
|
|
|
|
// $cond_reg (type VCCR) gives the input predicate register. This is
|
|
|
|
|
// always either zero_reg or VPR, but needs to be modelled as an
|
|
|
|
|
// explicit operand so that it can be register-allocated and spilled
|
|
|
|
|
// when these operands are used in code generation).
|
|
|
|
|
//
|
|
|
|
|
// For 'vpred_r', there's an extra operand $inactive, which specifies
|
|
|
|
|
// the vector register which will supply any lanes of the output
|
|
|
|
|
// register that the predication mask prevents from being written by
|
|
|
|
|
// this instruction. It's always tied to the actual output register
|
|
|
|
|
// (i.e. must be allocated into the same physical reg), but again,
|
|
|
|
|
// code generation will need to model it as a separate input value.
|
|
|
|
|
//
|
|
|
|
|
// 'vpred_n' doesn't have that extra operand: it only has $cond and
|
|
|
|
|
// $cond_reg. This variant is used for any instruction that can't, or
|
|
|
|
|
// doesn't want to, tie $inactive to the output register. Sometimes
|
|
|
|
|
// that's because another input parameter is already tied to it (e.g.
|
|
|
|
|
// instructions that both read and write their Qd register even when
|
|
|
|
|
// unpredicated, either because they only partially overwrite it like
|
|
|
|
|
// a narrowing integer conversion, or simply because the instruction
|
|
|
|
|
// encoding doesn't have enough register fields to make the output
|
|
|
|
|
// independent of all inputs). It can also be because the instruction
|
|
|
|
|
// is defined to set disabled output lanes to zero rather than leaving
|
|
|
|
|
// them unchanged (vector loads), or because it doesn't output a
|
|
|
|
|
// vector register at all (stores, compares). In any of these
|
|
|
|
|
// situations it's unnecessary to have an extra operand tied to the
|
|
|
|
|
// output, and inconvenient to leave it there unused.
|
|
|
|
|
|
|
|
|
|
// Base class for both kinds of vpred.
|
|
|
|
|
class vpred_ops<dag extra_op, dag extra_mi> : OperandWithDefaultOps<OtherVT,
|
|
|
|
|
!con((ops (i32 0), (i32 zero_reg)), extra_op)> {
|
|
|
|
|
let PrintMethod = "printVPTPredicateOperand";
|
|
|
|
|
let OperandNamespace = "ARM";
|
|
|
|
|
let MIOperandInfo = !con((ops i32imm:$cond, VCCR:$cond_reg), extra_mi);
|
|
|
|
|
|
|
|
|
|
// For convenience, we provide a string value that can be appended
|
|
|
|
|
// to the constraints string. It's empty for vpred_n, and for
|
|
|
|
|
// vpred_r it ties the $inactive operand to the output q-register
|
|
|
|
|
// (which by convention will be called $Qd).
|
|
|
|
|
string vpred_constraint;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def vpred_r : vpred_ops<(ops (v4i32 undef_tied_input)), (ops MQPR:$inactive)> {
|
|
|
|
|
let ParserMatchClass = VPTPredROperand;
|
|
|
|
|
let OperandType = "OPERAND_VPRED_R";
|
|
|
|
|
let DecoderMethod = "DecodeVpredROperand";
|
|
|
|
|
let vpred_constraint = ",$Qd = $vp.inactive";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def vpred_n : vpred_ops<(ops), (ops)> {
|
|
|
|
|
let ParserMatchClass = VPTPredNOperand;
|
|
|
|
|
let OperandType = "OPERAND_VPRED_N";
|
|
|
|
|
let vpred_constraint = "";
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-11 02:59:38 +08:00
|
|
|
|
// ARM special operands for disassembly only.
|
|
|
|
|
//
|
2017-04-03 22:50:04 +08:00
|
|
|
|
def SetEndAsmOperand : ImmAsmOperand<0,1> {
|
2011-07-23 01:44:50 +08:00
|
|
|
|
let Name = "SetEndImm";
|
|
|
|
|
let ParserMethod = "parseSetEndImm";
|
|
|
|
|
}
|
2010-10-14 05:00:04 +08:00
|
|
|
|
def setend_op : Operand<i32> {
|
|
|
|
|
let PrintMethod = "printSetendOperand";
|
2011-07-23 01:44:50 +08:00
|
|
|
|
let ParserMatchClass = SetEndAsmOperand;
|
2010-10-14 05:00:04 +08:00
|
|
|
|
}
|
2010-03-11 02:59:38 +08:00
|
|
|
|
|
2011-07-26 04:38:18 +08:00
|
|
|
|
def MSRMaskOperand : AsmOperandClass {
|
|
|
|
|
let Name = "MSRMask";
|
|
|
|
|
let ParserMethod = "parseMSRMaskOperand";
|
|
|
|
|
}
|
2010-03-11 02:59:38 +08:00
|
|
|
|
def msr_mask : Operand<i32> {
|
|
|
|
|
let PrintMethod = "printMSRMaskOperand";
|
2011-08-12 04:21:46 +08:00
|
|
|
|
let DecoderMethod = "DecodeMSRMask";
|
2011-02-19 03:45:59 +08:00
|
|
|
|
let ParserMatchClass = MSRMaskOperand;
|
2010-03-11 02:59:38 +08:00
|
|
|
|
}
|
|
|
|
|
|
2014-08-15 18:47:12 +08:00
|
|
|
|
def BankedRegOperand : AsmOperandClass {
|
|
|
|
|
let Name = "BankedReg";
|
|
|
|
|
let ParserMethod = "parseBankedRegOperand";
|
|
|
|
|
}
|
|
|
|
|
def banked_reg : Operand<i32> {
|
|
|
|
|
let PrintMethod = "printBankedRegOperand";
|
|
|
|
|
let DecoderMethod = "DecodeBankedReg";
|
|
|
|
|
let ParserMatchClass = BankedRegOperand;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-08 07:38:41 +08:00
|
|
|
|
// Shift Right Immediate - A shift right immediate is encoded differently from
|
|
|
|
|
// other shift immediates. The imm6 field is encoded like so:
|
2011-03-01 09:00:59 +08:00
|
|
|
|
//
|
2011-03-08 07:38:41 +08:00
|
|
|
|
// Offset Encoding
|
|
|
|
|
// 8 imm6<5:3> = '001', 8 - <imm> is encoded in imm6<2:0>
|
|
|
|
|
// 16 imm6<5:4> = '01', 16 - <imm> is encoded in imm6<3:0>
|
|
|
|
|
// 32 imm6<5> = '1', 32 - <imm> is encoded in imm6<4:0>
|
|
|
|
|
// 64 64 - <imm> is encoded in imm6<5:0>
|
2017-04-03 22:50:04 +08:00
|
|
|
|
def shr_imm8_asm_operand : ImmAsmOperand<1,8> { let Name = "ShrImm8"; }
|
2014-02-10 22:04:07 +08:00
|
|
|
|
def shr_imm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 8; }]> {
|
2011-03-08 07:38:41 +08:00
|
|
|
|
let EncoderMethod = "getShiftRight8Imm";
|
2011-08-10 04:55:18 +08:00
|
|
|
|
let DecoderMethod = "DecodeShiftRight8Imm";
|
2011-12-09 06:06:06 +08:00
|
|
|
|
let ParserMatchClass = shr_imm8_asm_operand;
|
2011-03-01 09:00:59 +08:00
|
|
|
|
}
|
2017-04-03 22:50:04 +08:00
|
|
|
|
def shr_imm16_asm_operand : ImmAsmOperand<1,16> { let Name = "ShrImm16"; }
|
2014-02-10 22:04:07 +08:00
|
|
|
|
def shr_imm16 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 16; }]> {
|
2011-03-08 07:38:41 +08:00
|
|
|
|
let EncoderMethod = "getShiftRight16Imm";
|
2011-08-10 04:55:18 +08:00
|
|
|
|
let DecoderMethod = "DecodeShiftRight16Imm";
|
2011-12-09 06:06:06 +08:00
|
|
|
|
let ParserMatchClass = shr_imm16_asm_operand;
|
2011-03-01 09:00:59 +08:00
|
|
|
|
}
|
2017-04-03 22:50:04 +08:00
|
|
|
|
def shr_imm32_asm_operand : ImmAsmOperand<1,32> { let Name = "ShrImm32"; }
|
2014-02-10 22:04:07 +08:00
|
|
|
|
def shr_imm32 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 32; }]> {
|
2011-03-08 07:38:41 +08:00
|
|
|
|
let EncoderMethod = "getShiftRight32Imm";
|
2011-08-10 04:55:18 +08:00
|
|
|
|
let DecoderMethod = "DecodeShiftRight32Imm";
|
2011-12-09 06:06:06 +08:00
|
|
|
|
let ParserMatchClass = shr_imm32_asm_operand;
|
2011-03-08 07:38:41 +08:00
|
|
|
|
}
|
2017-04-03 22:50:04 +08:00
|
|
|
|
def shr_imm64_asm_operand : ImmAsmOperand<1,64> { let Name = "ShrImm64"; }
|
2014-02-10 22:04:07 +08:00
|
|
|
|
def shr_imm64 : Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 64; }]> {
|
2011-03-08 07:38:41 +08:00
|
|
|
|
let EncoderMethod = "getShiftRight64Imm";
|
2011-08-10 04:55:18 +08:00
|
|
|
|
let DecoderMethod = "DecodeShiftRight64Imm";
|
2011-12-09 06:06:06 +08:00
|
|
|
|
let ParserMatchClass = shr_imm64_asm_operand;
|
2011-03-01 09:00:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-05-13 05:22:31 +08:00
|
|
|
|
|
|
|
|
|
// ARM Assembler operand for ldr Rd, =expression which generates an offset
|
|
|
|
|
// to a constant pool entry or a MOV depending on the value of expression
|
|
|
|
|
def const_pool_asm_operand : AsmOperandClass { let Name = "ConstPoolAsmImm"; }
|
|
|
|
|
def const_pool_asm_imm : Operand<i32> {
|
|
|
|
|
let ParserMatchClass = const_pool_asm_operand;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-08-23 02:04:24 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// ARM Assembler alias templates.
|
|
|
|
|
//
|
2016-06-03 21:19:43 +08:00
|
|
|
|
// Note: When EmitPriority == 1, the alias will be used for printing
|
|
|
|
|
class ARMInstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[IsARM]>;
|
[ARM] [Assembler] Support negative immediates for A32, T32 and T16
Summary:
To support negative immediates for certain arithmetic instructions, the
instruction is converted to the inverse instruction with a negated (or inverted)
immediate. For example, "ADD r0, r1, #FFFFFFFF" cannot be encoded as an ADD
instruction. However, "SUB r0, r1, #1" is equivalent.
These conversions are different from instruction aliases. An alias maps
several assembler instructions onto one encoding. A conversion, however, maps
an *invalid* instruction--e.g. with an immediate that cannot be represented in
the encoding--to a different (but equivalent) instruction.
Several instructions with negative immediates were being converted already, but
this was not systematically tested, nor did it cover all instructions.
This patch implements all possible substitutions for ARM, Thumb1 and
Thumb2 assembler and adds tests. It also adds a feature flag
(-mattr=+no-neg-immediates) to turn these substitutions off. This is
helpful for users who want their code to assemble to exactly what they
wrote.
Reviewers: t.p.northover, rovka, samparker, javed.absar, peter.smith, rengolin
Reviewed By: javed.absar
Subscribers: aadg, aemerson, llvm-commits
Differential Revision: https://reviews.llvm.org/D30571
llvm-svn: 298380
2017-03-21 22:59:17 +08:00
|
|
|
|
class ARMInstSubst<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>,
|
|
|
|
|
Requires<[IsARM,UseNegativeImmediates]>;
|
2016-06-03 21:19:43 +08:00
|
|
|
|
class tInstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[IsThumb]>;
|
[ARM] [Assembler] Support negative immediates for A32, T32 and T16
Summary:
To support negative immediates for certain arithmetic instructions, the
instruction is converted to the inverse instruction with a negated (or inverted)
immediate. For example, "ADD r0, r1, #FFFFFFFF" cannot be encoded as an ADD
instruction. However, "SUB r0, r1, #1" is equivalent.
These conversions are different from instruction aliases. An alias maps
several assembler instructions onto one encoding. A conversion, however, maps
an *invalid* instruction--e.g. with an immediate that cannot be represented in
the encoding--to a different (but equivalent) instruction.
Several instructions with negative immediates were being converted already, but
this was not systematically tested, nor did it cover all instructions.
This patch implements all possible substitutions for ARM, Thumb1 and
Thumb2 assembler and adds tests. It also adds a feature flag
(-mattr=+no-neg-immediates) to turn these substitutions off. This is
helpful for users who want their code to assemble to exactly what they
wrote.
Reviewers: t.p.northover, rovka, samparker, javed.absar, peter.smith, rengolin
Reviewed By: javed.absar
Subscribers: aadg, aemerson, llvm-commits
Differential Revision: https://reviews.llvm.org/D30571
llvm-svn: 298380
2017-03-21 22:59:17 +08:00
|
|
|
|
class tInstSubst<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>,
|
|
|
|
|
Requires<[IsThumb,UseNegativeImmediates]>;
|
2016-06-03 21:19:43 +08:00
|
|
|
|
class t2InstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[IsThumb2]>;
|
[ARM] [Assembler] Support negative immediates for A32, T32 and T16
Summary:
To support negative immediates for certain arithmetic instructions, the
instruction is converted to the inverse instruction with a negated (or inverted)
immediate. For example, "ADD r0, r1, #FFFFFFFF" cannot be encoded as an ADD
instruction. However, "SUB r0, r1, #1" is equivalent.
These conversions are different from instruction aliases. An alias maps
several assembler instructions onto one encoding. A conversion, however, maps
an *invalid* instruction--e.g. with an immediate that cannot be represented in
the encoding--to a different (but equivalent) instruction.
Several instructions with negative immediates were being converted already, but
this was not systematically tested, nor did it cover all instructions.
This patch implements all possible substitutions for ARM, Thumb1 and
Thumb2 assembler and adds tests. It also adds a feature flag
(-mattr=+no-neg-immediates) to turn these substitutions off. This is
helpful for users who want their code to assemble to exactly what they
wrote.
Reviewers: t.p.northover, rovka, samparker, javed.absar, peter.smith, rengolin
Reviewed By: javed.absar
Subscribers: aadg, aemerson, llvm-commits
Differential Revision: https://reviews.llvm.org/D30571
llvm-svn: 298380
2017-03-21 22:59:17 +08:00
|
|
|
|
class t2InstSubst<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>,
|
|
|
|
|
Requires<[IsThumb2,UseNegativeImmediates]>;
|
2016-06-03 21:19:43 +08:00
|
|
|
|
class VFP2InstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[HasVFP2]>;
|
|
|
|
|
class VFP2DPInstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[HasVFP2,HasDPVFP]>;
|
|
|
|
|
class VFP3InstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[HasVFP3]>;
|
|
|
|
|
class NEONInstAlias<string Asm, dag Result, bit EmitPriority = 0>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[HasNEON]>;
|
2019-06-14 22:31:13 +08:00
|
|
|
|
class MVEInstAlias<string Asm, dag Result, bit EmitPriority = 1>
|
|
|
|
|
: InstAlias<Asm, Result, EmitPriority>, Requires<[HasMVEInt, IsThumb]>;
|
2011-08-23 02:04:24 +08:00
|
|
|
|
|
2011-12-14 04:08:32 +08:00
|
|
|
|
|
|
|
|
|
class VFP2MnemonicAlias<string src, string dst> : MnemonicAlias<src, dst>,
|
|
|
|
|
Requires<[HasVFP2]>;
|
|
|
|
|
class NEONMnemonicAlias<string src, string dst> : MnemonicAlias<src, dst>,
|
|
|
|
|
Requires<[HasNEON]>;
|
|
|
|
|
|
2009-07-11 14:43:01 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-08-29 07:39:26 +08:00
|
|
|
|
// ARM Instruction templates.
|
|
|
|
|
//
|
|
|
|
|
|
2011-08-23 02:04:24 +08:00
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class InstTemplate<AddrMode am, int sz, IndexMode im,
|
2009-12-16 01:24:14 +08:00
|
|
|
|
Format f, Domain d, string cstr, InstrItinClass itin>
|
2008-08-29 07:39:26 +08:00
|
|
|
|
: Instruction {
|
|
|
|
|
let Namespace = "ARM";
|
|
|
|
|
|
|
|
|
|
AddrMode AM = am;
|
2011-07-14 07:22:26 +08:00
|
|
|
|
int Size = sz;
|
2008-08-29 07:39:26 +08:00
|
|
|
|
IndexMode IM = im;
|
|
|
|
|
bits<2> IndexModeBits = IM.Value;
|
|
|
|
|
Format F = f;
|
2010-03-18 05:13:43 +08:00
|
|
|
|
bits<6> Form = F.Value;
|
2009-11-02 08:10:38 +08:00
|
|
|
|
Domain D = d;
|
2008-11-06 02:35:52 +08:00
|
|
|
|
bit isUnaryDataProc = 0;
|
2009-07-08 09:46:35 +08:00
|
|
|
|
bit canXformTo16Bit = 0;
|
2011-08-17 04:45:50 +08:00
|
|
|
|
// The instruction is a 16-bit flag setting Thumb instruction. Used
|
|
|
|
|
// by the parser to determine whether to require the 'S' suffix on the
|
|
|
|
|
// mnemonic (when not in an IT block) or preclude it (when in an IT block).
|
|
|
|
|
bit thumbArithFlagSetting = 0;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2019-10-15 21:12:51 +08:00
|
|
|
|
bit validForTailPredication = 0;
|
2019-09-17 15:43:04 +08:00
|
|
|
|
|
2010-11-01 03:22:57 +08:00
|
|
|
|
// If this is a pseudo instruction, mark it isCodeGenOnly.
|
|
|
|
|
let isCodeGenOnly = !eq(!cast<string>(f), "Pseudo");
|
2010-03-24 01:23:59 +08:00
|
|
|
|
|
2011-08-16 00:52:24 +08:00
|
|
|
|
// The layout of TSFlags should be kept in sync with ARMBaseInfo.h.
|
2010-10-06 02:14:55 +08:00
|
|
|
|
let TSFlags{4-0} = AM.Value;
|
2011-07-14 07:22:26 +08:00
|
|
|
|
let TSFlags{6-5} = IndexModeBits;
|
|
|
|
|
let TSFlags{12-7} = Form;
|
|
|
|
|
let TSFlags{13} = isUnaryDataProc;
|
|
|
|
|
let TSFlags{14} = canXformTo16Bit;
|
2019-05-30 16:07:06 +08:00
|
|
|
|
let TSFlags{18-15} = D.Value;
|
|
|
|
|
let TSFlags{19} = thumbArithFlagSetting;
|
2019-10-15 21:12:51 +08:00
|
|
|
|
let TSFlags{20} = validForTailPredication;
|
2010-04-05 11:10:20 +08:00
|
|
|
|
|
2008-08-29 07:39:26 +08:00
|
|
|
|
let Constraints = cstr;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
let Itinerary = itin;
|
2008-08-29 07:39:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-12-16 01:24:14 +08:00
|
|
|
|
class Encoding {
|
|
|
|
|
field bits<32> Inst;
|
2012-02-09 18:56:31 +08:00
|
|
|
|
// Mask of bits that cause an encoding to be UNPREDICTABLE.
|
|
|
|
|
// If a bit is set, then if the corresponding bit in the
|
|
|
|
|
// target encoding differs from its value in the "Inst" field,
|
|
|
|
|
// the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
|
|
|
|
|
field bits<32> Unpredictable = 0;
|
|
|
|
|
// SoftFail is the generic name for this field, but we alias it so
|
|
|
|
|
// as to make it more obvious what it means in ARM-land.
|
|
|
|
|
field bits<32> SoftFail = Unpredictable;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class InstARM<AddrMode am, int sz, IndexMode im,
|
2009-12-16 01:24:14 +08:00
|
|
|
|
Format f, Domain d, string cstr, InstrItinClass itin>
|
2011-07-20 05:06:00 +08:00
|
|
|
|
: InstTemplate<am, sz, im, f, d, cstr, itin>, Encoding {
|
|
|
|
|
let DecoderNamespace = "ARM";
|
|
|
|
|
}
|
2009-12-16 01:24:14 +08:00
|
|
|
|
|
|
|
|
|
// This Encoding-less class is used by Thumb1 to specify the encoding bits later
|
|
|
|
|
// on by adding flavors to specific instructions.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class InstThumb<AddrMode am, int sz, IndexMode im,
|
2009-12-16 01:24:14 +08:00
|
|
|
|
Format f, Domain d, string cstr, InstrItinClass itin>
|
2011-07-20 05:06:00 +08:00
|
|
|
|
: InstTemplate<am, sz, im, f, d, cstr, itin> {
|
|
|
|
|
let DecoderNamespace = "Thumb";
|
|
|
|
|
}
|
2009-12-16 01:24:14 +08:00
|
|
|
|
|
2011-11-01 09:24:45 +08:00
|
|
|
|
// Pseudo-instructions for alternate assembly syntax (never used by codegen).
|
|
|
|
|
// These are aliases that require C++ handling to convert to the target
|
|
|
|
|
// instruction, while InstAliases can be handled directly by tblgen.
|
2014-01-12 12:36:01 +08:00
|
|
|
|
class AsmPseudoInst<string asm, dag iops, dag oops = (outs)>
|
2011-11-01 09:24:45 +08:00
|
|
|
|
: InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo, GenericDomain,
|
|
|
|
|
"", NoItinerary> {
|
2014-01-12 12:36:01 +08:00
|
|
|
|
let OutOperandList = oops;
|
2011-11-01 09:24:45 +08:00
|
|
|
|
let InOperandList = iops;
|
|
|
|
|
let Pattern = [];
|
|
|
|
|
let isCodeGenOnly = 0; // So we get asm matcher for it.
|
2011-11-11 00:44:55 +08:00
|
|
|
|
let AsmString = asm;
|
2011-11-01 09:24:45 +08:00
|
|
|
|
let isPseudo = 1;
|
2019-09-29 16:38:48 +08:00
|
|
|
|
let hasNoSchedulingInfo = 1;
|
2011-11-01 09:24:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-12 12:36:01 +08:00
|
|
|
|
class ARMAsmPseudo<string asm, dag iops, dag oops = (outs)>
|
|
|
|
|
: AsmPseudoInst<asm, iops, oops>, Requires<[IsARM]>;
|
|
|
|
|
class tAsmPseudo<string asm, dag iops, dag oops = (outs)>
|
|
|
|
|
: AsmPseudoInst<asm, iops, oops>, Requires<[IsThumb]>;
|
|
|
|
|
class t2AsmPseudo<string asm, dag iops, dag oops = (outs)>
|
|
|
|
|
: AsmPseudoInst<asm, iops, oops>, Requires<[IsThumb2]>;
|
|
|
|
|
class VFP2AsmPseudo<string asm, dag iops, dag oops = (outs)>
|
|
|
|
|
: AsmPseudoInst<asm, iops, oops>, Requires<[HasVFP2]>;
|
|
|
|
|
class NEONAsmPseudo<string asm, dag iops, dag oops = (outs)>
|
|
|
|
|
: AsmPseudoInst<asm, iops, oops>, Requires<[HasNEON]>;
|
[ARM] Add MVE vector bit-operations (register inputs).
This includes all the obvious bitwise operations (AND, OR, BIC, ORN,
MVN) in register-to-register forms, and the immediate forms of
AND/OR/BIC/ORN; byte-order reverse instructions; and the VMOVs that
access a single lane of a vector.
Some of those VMOVs (specifically, the ones that access a 32-bit lane)
share an encoding with existing instructions that were disassembled as
accessing half of a d-register (e.g. `vmov.32 r0, d1[0]`), but in
8.1-M they're now written as accessing a quarter of a q-register (e.g.
`vmov.32 r0, q0[2]`). The older syntax is still accepted by the
assembler.
Reviewers: dmgreen, samparker, SjoerdMeijer, t.p.northover
Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62673
llvm-svn: 363838
2019-06-20 00:43:53 +08:00
|
|
|
|
class MVEAsmPseudo<string asm, dag iops, dag oops = (outs)>
|
|
|
|
|
: AsmPseudoInst<asm, iops, oops>, Requires<[HasMVEInt]>;
|
2011-11-01 09:24:45 +08:00
|
|
|
|
|
|
|
|
|
// Pseudo instructions for the code generator.
|
2010-11-18 09:38:26 +08:00
|
|
|
|
class PseudoInst<dag oops, dag iops, InstrItinClass itin, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstTemplate<AddrModeNone, 0, IndexModeNone, Pseudo,
|
2011-07-07 05:35:46 +08:00
|
|
|
|
GenericDomain, "", itin> {
|
2008-08-29 07:39:26 +08:00
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
|
|
|
|
let Pattern = pattern;
|
2011-03-11 03:06:39 +08:00
|
|
|
|
let isCodeGenOnly = 1;
|
2011-07-07 05:35:46 +08:00
|
|
|
|
let isPseudo = 1;
|
2008-08-29 07:39:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-18 09:15:56 +08:00
|
|
|
|
// PseudoInst that's ARM-mode only.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class ARMPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
|
2010-11-18 09:38:26 +08:00
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: PseudoInst<oops, iops, itin, pattern> {
|
2011-07-14 07:22:26 +08:00
|
|
|
|
let Size = sz;
|
2010-11-18 09:15:56 +08:00
|
|
|
|
list<Predicate> Predicates = [IsARM];
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-30 03:32:47 +08:00
|
|
|
|
// PseudoInst that's Thumb-mode only.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class tPseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
|
2010-11-30 03:32:47 +08:00
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: PseudoInst<oops, iops, itin, pattern> {
|
2011-07-14 07:22:26 +08:00
|
|
|
|
let Size = sz;
|
2010-11-30 03:32:47 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb];
|
|
|
|
|
}
|
2010-11-18 09:15:56 +08:00
|
|
|
|
|
2016-12-15 15:59:08 +08:00
|
|
|
|
// PseudoInst that's in ARMv8-M baseline (Somewhere between Thumb and Thumb2)
|
|
|
|
|
class t2basePseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
|
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: PseudoInst<oops, iops, itin, pattern> {
|
|
|
|
|
let Size = sz;
|
|
|
|
|
list<Predicate> Predicates = [IsThumb,HasV8MBaseline];
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-16 02:48:45 +08:00
|
|
|
|
// PseudoInst that's Thumb2-mode only.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class t2PseudoInst<dag oops, dag iops, int sz, InstrItinClass itin,
|
2010-12-16 02:48:45 +08:00
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: PseudoInst<oops, iops, itin, pattern> {
|
2011-07-14 07:22:26 +08:00
|
|
|
|
let Size = sz;
|
2010-12-16 02:48:45 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
|
|
|
|
}
|
2011-07-09 01:40:42 +08:00
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class ARMPseudoExpand<dag oops, dag iops, int sz,
|
2011-07-09 01:40:42 +08:00
|
|
|
|
InstrItinClass itin, list<dag> pattern,
|
|
|
|
|
dag Result>
|
|
|
|
|
: ARMPseudoInst<oops, iops, sz, itin, pattern>,
|
|
|
|
|
PseudoInstExpansion<Result>;
|
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class tPseudoExpand<dag oops, dag iops, int sz,
|
2011-07-09 01:40:42 +08:00
|
|
|
|
InstrItinClass itin, list<dag> pattern,
|
|
|
|
|
dag Result>
|
|
|
|
|
: tPseudoInst<oops, iops, sz, itin, pattern>,
|
|
|
|
|
PseudoInstExpansion<Result>;
|
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class t2PseudoExpand<dag oops, dag iops, int sz,
|
2011-07-09 01:40:42 +08:00
|
|
|
|
InstrItinClass itin, list<dag> pattern,
|
|
|
|
|
dag Result>
|
|
|
|
|
: t2PseudoInst<oops, iops, sz, itin, pattern>,
|
|
|
|
|
PseudoInstExpansion<Result>;
|
|
|
|
|
|
2008-08-29 07:39:26 +08:00
|
|
|
|
// Almost all ARM instructions are predicable.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class I<dag oops, dag iops, AddrMode am, int sz,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
string opc, string asm, string cstr,
|
2008-08-29 07:39:26 +08:00
|
|
|
|
list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
2010-10-12 02:51:51 +08:00
|
|
|
|
bits<4> p;
|
|
|
|
|
let Inst{31-28} = p;
|
2008-08-29 07:39:26 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", asm);
|
2008-08-29 07:39:26 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [IsARM];
|
|
|
|
|
}
|
2010-08-31 15:50:46 +08:00
|
|
|
|
|
2009-12-15 02:31:20 +08:00
|
|
|
|
// A few are not predicable
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class InoP<dag oops, dag iops, AddrMode am, int sz,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2009-12-15 02:31:20 +08:00
|
|
|
|
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = !strconcat(opc, asm);
|
2009-12-15 02:31:20 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
let isPredicable = 0;
|
|
|
|
|
list<Predicate> Predicates = [IsARM];
|
|
|
|
|
}
|
2008-08-29 07:39:26 +08:00
|
|
|
|
|
2010-08-30 09:47:35 +08:00
|
|
|
|
// Same as I except it can optionally modify CPSR. Note it's modeled as an input
|
|
|
|
|
// operand since by default it's a zero register. It will become an implicit def
|
|
|
|
|
// once it's "flipped".
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class sI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, string cstr,
|
2008-08-29 07:39:26 +08:00
|
|
|
|
list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
2010-10-12 02:51:51 +08:00
|
|
|
|
bits<4> p; // Predicate operand
|
2010-10-13 07:00:24 +08:00
|
|
|
|
bits<1> s; // condition-code set flag ('1' if the insn should set the flags)
|
2010-10-12 02:51:51 +08:00
|
|
|
|
let Inst{31-28} = p;
|
2010-10-13 07:00:24 +08:00
|
|
|
|
let Inst{20} = s;
|
2010-10-12 02:51:51 +08:00
|
|
|
|
|
2008-08-29 07:39:26 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p, cc_out:$s));
|
2010-10-15 11:23:44 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${s}${p}", asm);
|
2008-08-29 07:39:26 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [IsARM];
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-01 15:19:00 +08:00
|
|
|
|
// Special cases
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class XI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
2008-09-01 15:19:00 +08:00
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = asm;
|
2008-09-01 15:19:00 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [IsARM];
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AI<dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern>;
|
|
|
|
|
class AsI<dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: sI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern>;
|
|
|
|
|
class AXI<dag oops, dag iops, Format f, InstrItinClass itin,
|
2008-08-29 07:39:26 +08:00
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: XI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
|
2008-11-07 06:15:19 +08:00
|
|
|
|
asm, "", pattern>;
|
2014-01-28 05:39:04 +08:00
|
|
|
|
class AXIM<dag oops, dag iops, AddrMode am, Format f, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
|
|
|
|
: XI<oops, iops, am, 4, IndexModeNone, f, itin,
|
|
|
|
|
asm, "", pattern>;
|
2009-12-15 02:31:20 +08:00
|
|
|
|
class AInoP<dag oops, dag iops, Format f, InstrItinClass itin,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InoP<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
opc, asm, "", pattern>;
|
2008-09-01 16:25:56 +08:00
|
|
|
|
|
|
|
|
|
// Ctrl flow instructions
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class ABI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, BrFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2008-10-15 04:36:24 +08:00
|
|
|
|
let Inst{27-24} = opcod;
|
2008-09-01 16:25:56 +08:00
|
|
|
|
}
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class ABXI<bits<4> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: XI<oops, iops, AddrModeNone, 4, IndexModeNone, BrFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
asm, "", pattern> {
|
2008-10-15 04:36:24 +08:00
|
|
|
|
let Inst{27-24} = opcod;
|
2008-09-01 16:25:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BR_JT instructions
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class JTI<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: XI<oops, iops, AddrModeNone, 0, IndexModeNone, BrMiscFrm, itin,
|
2008-11-07 17:06:08 +08:00
|
|
|
|
asm, "", pattern>;
|
2008-09-01 09:51:14 +08:00
|
|
|
|
|
2013-08-28 01:38:16 +08:00
|
|
|
|
class AIldr_ex_or_acq<bits<2> opcod, bits<2> opcod2, dag oops, dag iops, InstrItinClass itin,
|
2009-12-11 09:42:04 +08:00
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin,
|
2009-12-11 09:42:04 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-10-30 03:58:57 +08:00
|
|
|
|
bits<4> Rt;
|
2011-07-27 01:44:46 +08:00
|
|
|
|
bits<4> addr;
|
2009-12-11 09:42:04 +08:00
|
|
|
|
let Inst{27-23} = 0b00011;
|
|
|
|
|
let Inst{22-21} = opcod;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{20} = 1;
|
2011-07-27 01:44:46 +08:00
|
|
|
|
let Inst{19-16} = addr;
|
2010-10-30 03:58:57 +08:00
|
|
|
|
let Inst{15-12} = Rt;
|
2013-08-28 01:38:16 +08:00
|
|
|
|
let Inst{11-10} = 0b11;
|
|
|
|
|
let Inst{9-8} = opcod2;
|
|
|
|
|
let Inst{7-0} = 0b10011111;
|
2009-12-11 09:42:04 +08:00
|
|
|
|
}
|
2013-08-28 01:38:16 +08:00
|
|
|
|
class AIstr_ex_or_rel<bits<2> opcod, bits<2> opcod2, dag oops, dag iops, InstrItinClass itin,
|
2009-12-11 09:42:04 +08:00
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, LdStExFrm, itin,
|
2009-12-11 09:42:04 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-10-30 03:58:57 +08:00
|
|
|
|
bits<4> Rt;
|
2011-03-25 05:04:58 +08:00
|
|
|
|
bits<4> addr;
|
2009-12-11 09:42:04 +08:00
|
|
|
|
let Inst{27-23} = 0b00011;
|
|
|
|
|
let Inst{22-21} = opcod;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{20} = 0;
|
2011-03-25 05:04:58 +08:00
|
|
|
|
let Inst{19-16} = addr;
|
2013-08-28 01:38:16 +08:00
|
|
|
|
let Inst{11-10} = 0b11;
|
|
|
|
|
let Inst{9-8} = opcod2;
|
|
|
|
|
let Inst{7-4} = 0b1001;
|
2010-10-30 03:58:57 +08:00
|
|
|
|
let Inst{3-0} = Rt;
|
2009-12-11 09:42:04 +08:00
|
|
|
|
}
|
2013-08-28 01:38:16 +08:00
|
|
|
|
// Atomic load/store instructions
|
|
|
|
|
class AIldrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AIldr_ex_or_acq<opcod, 0b11, oops, iops, itin, opc, asm, pattern>;
|
|
|
|
|
|
|
|
|
|
class AIstrex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AIstr_ex_or_rel<opcod, 0b11, oops, iops, itin, opc, asm, pattern> {
|
|
|
|
|
bits<4> Rd;
|
|
|
|
|
let Inst{15-12} = Rd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Exclusive load/store instructions
|
|
|
|
|
|
|
|
|
|
class AIldaex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AIldr_ex_or_acq<opcod, 0b10, oops, iops, itin, opc, asm, pattern>,
|
2016-01-15 18:23:46 +08:00
|
|
|
|
Requires<[IsARM, HasAcquireRelease, HasV7Clrex]>;
|
2013-08-28 01:38:16 +08:00
|
|
|
|
|
|
|
|
|
class AIstlex<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AIstr_ex_or_rel<opcod, 0b10, oops, iops, itin, opc, asm, pattern>,
|
2016-01-15 18:23:46 +08:00
|
|
|
|
Requires<[IsARM, HasAcquireRelease, HasV7Clrex]> {
|
2013-08-28 01:38:16 +08:00
|
|
|
|
bits<4> Rd;
|
|
|
|
|
let Inst{15-12} = Rd;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-30 04:21:36 +08:00
|
|
|
|
class AIswp<bit b, dag oops, dag iops, string opc, list<dag> pattern>
|
2011-07-27 01:15:11 +08:00
|
|
|
|
: AI<oops, iops, MiscFrm, NoItinerary, opc, "\t$Rt, $Rt2, $addr", pattern> {
|
2010-10-30 04:21:36 +08:00
|
|
|
|
bits<4> Rt;
|
|
|
|
|
bits<4> Rt2;
|
2011-07-27 01:15:11 +08:00
|
|
|
|
bits<4> addr;
|
2010-10-30 04:21:36 +08:00
|
|
|
|
let Inst{27-23} = 0b00010;
|
|
|
|
|
let Inst{22} = b;
|
|
|
|
|
let Inst{21-20} = 0b00;
|
2011-07-27 01:15:11 +08:00
|
|
|
|
let Inst{19-16} = addr;
|
2010-10-30 04:21:36 +08:00
|
|
|
|
let Inst{15-12} = Rt;
|
|
|
|
|
let Inst{11-4} = 0b00001001;
|
|
|
|
|
let Inst{3-0} = Rt2;
|
2011-10-29 02:02:13 +08:00
|
|
|
|
|
2012-04-18 22:18:57 +08:00
|
|
|
|
let Unpredictable{11-8} = 0b1111;
|
2011-10-29 02:02:13 +08:00
|
|
|
|
let DecoderMethod = "DecodeSwap";
|
2010-10-30 04:21:36 +08:00
|
|
|
|
}
|
2013-08-28 01:38:16 +08:00
|
|
|
|
// Acquire/Release load/store instructions
|
|
|
|
|
class AIldracq<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AIldr_ex_or_acq<opcod, 0b00, oops, iops, itin, opc, asm, pattern>,
|
2016-01-15 18:23:46 +08:00
|
|
|
|
Requires<[IsARM, HasAcquireRelease]>;
|
2013-08-28 01:38:16 +08:00
|
|
|
|
|
|
|
|
|
class AIstrrel<bits<2> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AIstr_ex_or_rel<opcod, 0b00, oops, iops, itin, opc, asm, pattern>,
|
2016-01-15 18:23:46 +08:00
|
|
|
|
Requires<[IsARM, HasAcquireRelease]> {
|
2013-08-28 01:38:16 +08:00
|
|
|
|
let Inst{15-12} = 0b1111;
|
|
|
|
|
}
|
2009-12-11 09:42:04 +08:00
|
|
|
|
|
2008-09-01 09:51:14 +08:00
|
|
|
|
// addrmode1 instructions
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrMode1, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2008-10-15 04:36:24 +08:00
|
|
|
|
let Inst{24-21} = opcod;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{27-26} = 0b00;
|
2008-08-29 15:40:52 +08:00
|
|
|
|
}
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AsI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: sI<oops, iops, AddrMode1, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2008-10-15 04:36:24 +08:00
|
|
|
|
let Inst{24-21} = opcod;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{27-26} = 0b00;
|
2008-08-29 15:40:52 +08:00
|
|
|
|
}
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AXI1<bits<4> opcod, dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: XI<oops, iops, AddrMode1, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
asm, "", pattern> {
|
2008-10-15 04:36:24 +08:00
|
|
|
|
let Inst{24-21} = opcod;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{27-26} = 0b00;
|
2008-09-01 15:19:00 +08:00
|
|
|
|
}
|
2008-09-01 03:02:21 +08:00
|
|
|
|
|
2008-09-01 09:27:33 +08:00
|
|
|
|
// loads
|
2010-10-27 06:37:02 +08:00
|
|
|
|
|
2010-11-20 05:07:51 +08:00
|
|
|
|
// LDR/LDRB/STR/STRB/...
|
|
|
|
|
class AI2ldst<bits<3> op, bit isLd, bit isByte, dag oops, dag iops, AddrMode am,
|
2010-10-28 07:12:14 +08:00
|
|
|
|
Format f, InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, am, 4, IndexModeNone, f, itin, opc, asm,
|
2010-10-27 06:37:02 +08:00
|
|
|
|
"", pattern> {
|
|
|
|
|
let Inst{27-25} = op;
|
|
|
|
|
let Inst{24} = 1; // 24 == P
|
|
|
|
|
// 23 == U
|
2010-11-13 08:35:48 +08:00
|
|
|
|
let Inst{22} = isByte;
|
2010-10-27 06:37:02 +08:00
|
|
|
|
let Inst{21} = 0; // 21 == W
|
2010-10-28 07:12:14 +08:00
|
|
|
|
let Inst{20} = isLd;
|
2010-10-27 06:37:02 +08:00
|
|
|
|
}
|
2010-11-13 08:35:48 +08:00
|
|
|
|
// Indexed load/stores
|
|
|
|
|
class AI2ldstidx<bit isLd, bit isByte, bit isPre, dag oops, dag iops,
|
2010-11-20 05:35:06 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin, string opc,
|
2010-11-13 08:35:48 +08:00
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrMode2, 4, im, f, itin,
|
2010-11-13 08:35:48 +08:00
|
|
|
|
opc, asm, cstr, pattern> {
|
2010-11-16 04:47:07 +08:00
|
|
|
|
bits<4> Rt;
|
2010-11-13 08:35:48 +08:00
|
|
|
|
let Inst{27-26} = 0b01;
|
|
|
|
|
let Inst{24} = isPre; // P bit
|
|
|
|
|
let Inst{22} = isByte; // B bit
|
|
|
|
|
let Inst{21} = isPre; // W bit
|
|
|
|
|
let Inst{20} = isLd; // L bit
|
2010-11-16 04:47:07 +08:00
|
|
|
|
let Inst{15-12} = Rt;
|
2010-10-27 06:37:02 +08:00
|
|
|
|
}
|
2011-07-27 04:54:26 +08:00
|
|
|
|
class AI2stridx_reg<bit isByte, bit isPre, dag oops, dag iops,
|
|
|
|
|
IndexMode im, Format f, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,
|
|
|
|
|
pattern> {
|
|
|
|
|
// AM2 store w/ two operands: (GPR, am2offset)
|
|
|
|
|
// {12} isAdd
|
|
|
|
|
// {11-0} imm12/Rm
|
|
|
|
|
bits<14> offset;
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
let Inst{25} = 1;
|
|
|
|
|
let Inst{23} = offset{12};
|
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{11-5} = offset{11-5};
|
|
|
|
|
let Inst{4} = 0;
|
|
|
|
|
let Inst{3-0} = offset{3-0};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AI2stridx_imm<bit isByte, bit isPre, dag oops, dag iops,
|
2010-11-20 05:35:06 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,
|
|
|
|
|
pattern> {
|
|
|
|
|
// AM2 store w/ two operands: (GPR, am2offset)
|
|
|
|
|
// {12} isAdd
|
|
|
|
|
// {11-0} imm12/Rm
|
2011-03-31 23:54:36 +08:00
|
|
|
|
bits<14> offset;
|
|
|
|
|
bits<4> Rn;
|
2011-07-27 04:54:26 +08:00
|
|
|
|
let Inst{25} = 0;
|
2011-03-31 23:54:36 +08:00
|
|
|
|
let Inst{23} = offset{12};
|
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{11-0} = offset{11-0};
|
2010-11-20 05:35:06 +08:00
|
|
|
|
}
|
2011-07-27 04:54:26 +08:00
|
|
|
|
|
|
|
|
|
|
2011-04-01 07:26:08 +08:00
|
|
|
|
// FIXME: Merge with the above class when addrmode2 gets used for STR, STRB
|
|
|
|
|
// but for now use this class for STRT and STRBT.
|
|
|
|
|
class AI2stridxT<bit isByte, bit isPre, dag oops, dag iops,
|
|
|
|
|
IndexMode im, Format f, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: AI2ldstidx<0, isByte, isPre, oops, iops, im, f, itin, opc, asm, cstr,
|
|
|
|
|
pattern> {
|
|
|
|
|
// AM2 store w/ two operands: (GPR, am2offset)
|
|
|
|
|
// {17-14} Rn
|
|
|
|
|
// {13} 1 == Rm, 0 == imm12
|
|
|
|
|
// {12} isAdd
|
|
|
|
|
// {11-0} imm12/Rm
|
|
|
|
|
bits<18> addr;
|
|
|
|
|
let Inst{25} = addr{13};
|
|
|
|
|
let Inst{23} = addr{12};
|
|
|
|
|
let Inst{19-16} = addr{17-14};
|
|
|
|
|
let Inst{11-0} = addr{11-0};
|
|
|
|
|
}
|
2010-10-27 06:37:02 +08:00
|
|
|
|
|
2008-09-01 09:51:14 +08:00
|
|
|
|
// addrmode3 instructions
|
2010-11-20 02:16:46 +08:00
|
|
|
|
class AI3ld<bits<4> op, bit op20, dag oops, dag iops, Format f,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrMode3, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-11-11 09:55:59 +08:00
|
|
|
|
bits<14> addr;
|
|
|
|
|
bits<4> Rt;
|
2009-07-09 06:51:32 +08:00
|
|
|
|
let Inst{27-25} = 0b000;
|
2010-11-11 09:55:59 +08:00
|
|
|
|
let Inst{24} = 1; // P bit
|
|
|
|
|
let Inst{23} = addr{8}; // U bit
|
|
|
|
|
let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
|
|
|
|
|
let Inst{21} = 0; // W bit
|
2010-11-20 02:16:46 +08:00
|
|
|
|
let Inst{20} = op20; // L bit
|
2010-11-11 09:55:59 +08:00
|
|
|
|
let Inst{19-16} = addr{12-9}; // Rn
|
|
|
|
|
let Inst{15-12} = Rt; // Rt
|
|
|
|
|
let Inst{11-8} = addr{7-4}; // imm7_4/zero
|
2010-11-18 08:46:58 +08:00
|
|
|
|
let Inst{7-4} = op;
|
2010-11-11 09:55:59 +08:00
|
|
|
|
let Inst{3-0} = addr{3-0}; // imm3_0/Rm
|
2011-08-10 04:55:18 +08:00
|
|
|
|
|
|
|
|
|
let DecoderMethod = "DecodeAddrMode3Instruction";
|
2008-09-01 15:00:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-08-12 04:41:13 +08:00
|
|
|
|
class AI3ldstidx<bits<4> op, bit op20, bit isPre, dag oops, dag iops,
|
2010-11-20 03:41:26 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrMode3, 4, im, f, itin,
|
2010-11-20 03:41:26 +08:00
|
|
|
|
opc, asm, cstr, pattern> {
|
|
|
|
|
bits<4> Rt;
|
|
|
|
|
let Inst{27-25} = 0b000;
|
|
|
|
|
let Inst{24} = isPre; // P bit
|
|
|
|
|
let Inst{21} = isPre; // W bit
|
|
|
|
|
let Inst{20} = op20; // L bit
|
|
|
|
|
let Inst{15-12} = Rt; // Rt
|
|
|
|
|
let Inst{7-4} = op;
|
|
|
|
|
}
|
2011-04-05 01:18:19 +08:00
|
|
|
|
|
|
|
|
|
// FIXME: Merge with the above class when addrmode2 gets used for LDR, LDRB
|
|
|
|
|
// but for now use this class for LDRSBT, LDRHT, LDSHT.
|
2011-08-04 07:50:40 +08:00
|
|
|
|
class AI3ldstidxT<bits<4> op, bit isLoad, dag oops, dag iops,
|
2011-04-05 01:18:19 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-08-04 07:50:40 +08:00
|
|
|
|
: I<oops, iops, AddrMode3, 4, im, f, itin, opc, asm, cstr, pattern> {
|
2011-04-05 01:18:19 +08:00
|
|
|
|
// {13} 1 == imm8, 0 == Rm
|
|
|
|
|
// {12-9} Rn
|
|
|
|
|
// {8} isAdd
|
|
|
|
|
// {7-4} imm7_4/zero
|
|
|
|
|
// {3-0} imm3_0/Rm
|
2011-08-04 07:50:40 +08:00
|
|
|
|
bits<4> addr;
|
2011-04-05 01:18:19 +08:00
|
|
|
|
bits<4> Rt;
|
|
|
|
|
let Inst{27-25} = 0b000;
|
2011-08-04 07:50:40 +08:00
|
|
|
|
let Inst{24} = 0; // P bit
|
|
|
|
|
let Inst{21} = 1;
|
|
|
|
|
let Inst{20} = isLoad; // L bit
|
|
|
|
|
let Inst{19-16} = addr; // Rn
|
2011-04-05 01:18:19 +08:00
|
|
|
|
let Inst{15-12} = Rt; // Rt
|
|
|
|
|
let Inst{7-4} = op;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-01 15:00:14 +08:00
|
|
|
|
// stores
|
2010-11-20 06:14:31 +08:00
|
|
|
|
class AI3str<bits<4> op, dag oops, dag iops, Format f, InstrItinClass itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrMode3, 4, IndexModeNone, f, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-11-11 09:09:40 +08:00
|
|
|
|
bits<14> addr;
|
|
|
|
|
bits<4> Rt;
|
2009-07-09 06:51:32 +08:00
|
|
|
|
let Inst{27-25} = 0b000;
|
2010-11-11 09:09:40 +08:00
|
|
|
|
let Inst{24} = 1; // P bit
|
|
|
|
|
let Inst{23} = addr{8}; // U bit
|
|
|
|
|
let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm
|
|
|
|
|
let Inst{21} = 0; // W bit
|
|
|
|
|
let Inst{20} = 0; // L bit
|
|
|
|
|
let Inst{19-16} = addr{12-9}; // Rn
|
|
|
|
|
let Inst{15-12} = Rt; // Rt
|
|
|
|
|
let Inst{11-8} = addr{7-4}; // imm7_4/zero
|
2010-11-20 06:14:31 +08:00
|
|
|
|
let Inst{7-4} = op;
|
2010-11-11 09:09:40 +08:00
|
|
|
|
let Inst{3-0} = addr{3-0}; // imm3_0/Rm
|
2011-08-13 04:02:50 +08:00
|
|
|
|
let DecoderMethod = "DecodeAddrMode3Instruction";
|
2008-09-01 15:00:14 +08:00
|
|
|
|
}
|
2008-09-01 09:51:14 +08:00
|
|
|
|
|
2008-09-01 15:00:14 +08:00
|
|
|
|
// addrmode4 instructions
|
2010-11-13 17:09:38 +08:00
|
|
|
|
class AXI4<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: XI<oops, iops, AddrMode4, 4, im, f, itin, asm, cstr, pattern> {
|
2010-11-13 17:09:38 +08:00
|
|
|
|
bits<4> p;
|
|
|
|
|
bits<16> regs;
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
let Inst{31-28} = p;
|
|
|
|
|
let Inst{27-25} = 0b100;
|
|
|
|
|
let Inst{22} = 0; // S bit
|
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{15-0} = regs;
|
|
|
|
|
}
|
2008-08-29 07:39:26 +08:00
|
|
|
|
|
2008-11-04 02:38:31 +08:00
|
|
|
|
// Unsigned multiply, multiply-accumulate instructions.
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2008-11-04 02:38:31 +08:00
|
|
|
|
let Inst{7-4} = 0b1001;
|
2008-11-06 09:21:28 +08:00
|
|
|
|
let Inst{20} = 0; // S bit
|
2008-11-06 16:47:38 +08:00
|
|
|
|
let Inst{27-21} = opcod;
|
2008-11-04 02:38:31 +08:00
|
|
|
|
}
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AsMul1I<bits<7> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: sI<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2008-11-04 02:38:31 +08:00
|
|
|
|
let Inst{7-4} = 0b1001;
|
2008-11-06 16:47:38 +08:00
|
|
|
|
let Inst{27-21} = opcod;
|
2008-11-06 09:21:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Most significant word multiply
|
2010-10-23 01:16:17 +08:00
|
|
|
|
class AMul2I<bits<7> opcod, bits<4> opc7_4, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-10-23 01:16:17 +08:00
|
|
|
|
bits<4> Rd;
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<4> Rm;
|
|
|
|
|
let Inst{7-4} = opc7_4;
|
2008-11-06 09:21:28 +08:00
|
|
|
|
let Inst{20} = 1;
|
2008-11-06 16:47:38 +08:00
|
|
|
|
let Inst{27-21} = opcod;
|
2010-10-23 01:16:17 +08:00
|
|
|
|
let Inst{19-16} = Rd;
|
|
|
|
|
let Inst{11-8} = Rm;
|
|
|
|
|
let Inst{3-0} = Rn;
|
|
|
|
|
}
|
|
|
|
|
// MSW multiple w/ Ra operand
|
|
|
|
|
class AMul2Ia<bits<7> opcod, bits<4> opc7_4, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AMul2I<opcod, opc7_4, oops, iops, itin, opc, asm, pattern> {
|
|
|
|
|
bits<4> Ra;
|
|
|
|
|
let Inst{15-12} = Ra;
|
2008-11-04 02:38:31 +08:00
|
|
|
|
}
|
2008-08-29 07:39:26 +08:00
|
|
|
|
|
2008-11-06 11:35:07 +08:00
|
|
|
|
// SMUL<x><y> / SMULW<y> / SMLA<x><y> / SMLAW<x><y>
|
2010-10-23 02:35:16 +08:00
|
|
|
|
class AMulxyIbase<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops,
|
2010-10-23 01:42:06 +08:00
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, MulFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-10-23 02:35:16 +08:00
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<4> Rm;
|
2008-11-06 11:35:07 +08:00
|
|
|
|
let Inst{4} = 0;
|
|
|
|
|
let Inst{7} = 1;
|
|
|
|
|
let Inst{20} = 0;
|
2008-11-06 16:47:38 +08:00
|
|
|
|
let Inst{27-21} = opcod;
|
2010-10-23 01:42:06 +08:00
|
|
|
|
let Inst{6-5} = bit6_5;
|
2010-10-23 02:35:16 +08:00
|
|
|
|
let Inst{11-8} = Rm;
|
|
|
|
|
let Inst{3-0} = Rn;
|
|
|
|
|
}
|
|
|
|
|
class AMulxyI<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AMulxyIbase<opcod, bit6_5, oops, iops, itin, opc, asm, pattern> {
|
|
|
|
|
bits<4> Rd;
|
|
|
|
|
let Inst{19-16} = Rd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AMulxyI with Ra operand
|
|
|
|
|
class AMulxyIa<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AMulxyI<opcod, bit6_5, oops, iops, itin, opc, asm, pattern> {
|
|
|
|
|
bits<4> Ra;
|
|
|
|
|
let Inst{15-12} = Ra;
|
|
|
|
|
}
|
|
|
|
|
// SMLAL*
|
|
|
|
|
class AMulxyI64<bits<7> opcod, bits<2> bit6_5, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AMulxyIbase<opcod, bit6_5, oops, iops, itin, opc, asm, pattern> {
|
|
|
|
|
bits<4> RdLo;
|
|
|
|
|
bits<4> RdHi;
|
|
|
|
|
let Inst{19-16} = RdHi;
|
|
|
|
|
let Inst{15-12} = RdLo;
|
2008-11-06 11:35:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 06:15:19 +08:00
|
|
|
|
// Extend instructions.
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AExtI<bits<8> opcod, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, ExtFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-10-14 03:56:10 +08:00
|
|
|
|
// All AExtI instructions have Rd and Rm register operands.
|
|
|
|
|
bits<4> Rd;
|
|
|
|
|
bits<4> Rm;
|
|
|
|
|
let Inst{15-12} = Rd;
|
|
|
|
|
let Inst{3-0} = Rm;
|
2008-11-07 06:15:19 +08:00
|
|
|
|
let Inst{7-4} = 0b0111;
|
2010-10-14 03:56:10 +08:00
|
|
|
|
let Inst{9-8} = 0b00;
|
2008-11-07 06:15:19 +08:00
|
|
|
|
let Inst{27-20} = opcod;
|
2012-05-11 17:28:27 +08:00
|
|
|
|
|
|
|
|
|
let Unpredictable{9-8} = 0b11;
|
2008-11-07 06:15:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 09:41:35 +08:00
|
|
|
|
// Misc Arithmetic instructions.
|
2010-10-23 06:12:16 +08:00
|
|
|
|
class AMiscA1I<bits<8> opcod, bits<4> opc7_4, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
2010-10-23 06:12:16 +08:00
|
|
|
|
bits<4> Rd;
|
|
|
|
|
bits<4> Rm;
|
|
|
|
|
let Inst{27-20} = opcod;
|
|
|
|
|
let Inst{19-16} = 0b1111;
|
|
|
|
|
let Inst{15-12} = Rd;
|
|
|
|
|
let Inst{11-8} = 0b1111;
|
|
|
|
|
let Inst{7-4} = opc7_4;
|
|
|
|
|
let Inst{3-0} = Rm;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-30 05:43:49 +08:00
|
|
|
|
// Division instructions.
|
|
|
|
|
class ADivA1I<bits<3> opcod, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin,
|
|
|
|
|
opc, asm, "", pattern> {
|
|
|
|
|
bits<4> Rd;
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<4> Rm;
|
|
|
|
|
let Inst{27-23} = 0b01110;
|
|
|
|
|
let Inst{22-20} = opcod;
|
|
|
|
|
let Inst{19-16} = Rd;
|
|
|
|
|
let Inst{15-12} = 0b1111;
|
|
|
|
|
let Inst{11-8} = Rm;
|
|
|
|
|
let Inst{7-4} = 0b0001;
|
|
|
|
|
let Inst{3-0} = Rn;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-23 06:12:16 +08:00
|
|
|
|
// PKH instructions
|
2017-04-03 22:50:04 +08:00
|
|
|
|
def PKHLSLAsmOperand : ImmAsmOperand<0,31> {
|
2011-07-22 01:23:04 +08:00
|
|
|
|
let Name = "PKHLSLImm";
|
|
|
|
|
let ParserMethod = "parsePKHLSLImm";
|
|
|
|
|
}
|
2011-07-21 05:40:26 +08:00
|
|
|
|
def pkh_lsl_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 32; }]>{
|
|
|
|
|
let PrintMethod = "printPKHLSLShiftImm";
|
2011-07-22 01:23:04 +08:00
|
|
|
|
let ParserMatchClass = PKHLSLAsmOperand;
|
|
|
|
|
}
|
|
|
|
|
def PKHASRAsmOperand : AsmOperandClass {
|
|
|
|
|
let Name = "PKHASRImm";
|
|
|
|
|
let ParserMethod = "parsePKHASRImm";
|
2011-07-21 05:40:26 +08:00
|
|
|
|
}
|
|
|
|
|
def pkh_asr_amt: Operand<i32>, ImmLeaf<i32, [{ return Imm > 0 && Imm <= 32; }]>{
|
|
|
|
|
let PrintMethod = "printPKHASRShiftImm";
|
2011-07-22 01:23:04 +08:00
|
|
|
|
let ParserMatchClass = PKHASRAsmOperand;
|
2011-07-21 05:40:26 +08:00
|
|
|
|
}
|
2011-07-21 04:49:03 +08:00
|
|
|
|
|
2010-10-23 06:12:16 +08:00
|
|
|
|
class APKHI<bits<8> opcod, bit tb, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: I<oops, iops, AddrModeNone, 4, IndexModeNone, ArithMiscFrm, itin,
|
2010-10-23 06:12:16 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
|
|
|
|
bits<4> Rd;
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<4> Rm;
|
2011-07-21 04:32:09 +08:00
|
|
|
|
bits<5> sh;
|
2008-11-07 09:41:35 +08:00
|
|
|
|
let Inst{27-20} = opcod;
|
2010-10-23 06:12:16 +08:00
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{15-12} = Rd;
|
2011-07-21 04:32:09 +08:00
|
|
|
|
let Inst{11-7} = sh;
|
2010-10-23 06:12:16 +08:00
|
|
|
|
let Inst{6} = tb;
|
|
|
|
|
let Inst{5-4} = 0b01;
|
|
|
|
|
let Inst{3-0} = Rm;
|
2008-11-07 09:41:35 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-08-29 07:39:26 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
// ARMPat - Same as Pat<>, but requires that the compiler be in ARM mode.
|
|
|
|
|
class ARMPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsARM];
|
|
|
|
|
}
|
2011-05-04 01:29:22 +08:00
|
|
|
|
class ARMV5TPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsARM, HasV5T];
|
|
|
|
|
}
|
2008-08-29 07:39:26 +08:00
|
|
|
|
class ARMV5TEPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsARM, HasV5TE];
|
|
|
|
|
}
|
2012-09-30 05:43:49 +08:00
|
|
|
|
// ARMV5MOPat - Same as ARMV5TEPat with UseMulOps.
|
|
|
|
|
class ARMV5MOPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsARM, HasV5TE, UseMulOps];
|
|
|
|
|
}
|
2008-08-29 07:39:26 +08:00
|
|
|
|
class ARMV6Pat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsARM, HasV6];
|
|
|
|
|
}
|
2015-03-24 00:15:16 +08:00
|
|
|
|
class VFPPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [HasVFP2];
|
|
|
|
|
}
|
|
|
|
|
class VFPNoNEONPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [HasVFP2, DontUseNEONForFP];
|
|
|
|
|
}
|
2016-08-02 20:44:27 +08:00
|
|
|
|
class Thumb2DSPPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsThumb2, HasDSP];
|
|
|
|
|
}
|
|
|
|
|
class Thumb2DSPMulPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsThumb2, UseMulOps, HasDSP];
|
|
|
|
|
}
|
2018-01-29 19:28:06 +08:00
|
|
|
|
class FP16Pat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [HasFP16];
|
|
|
|
|
}
|
|
|
|
|
class FullFP16Pat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [HasFullFP16];
|
|
|
|
|
}
|
2008-08-29 14:41:12 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// Thumb Instruction Format Definitions.
|
|
|
|
|
//
|
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class ThumbI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin, string asm, string cstr, list<dag> pattern>
|
2009-12-16 01:24:14 +08:00
|
|
|
|
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = asm;
|
2008-08-29 14:41:12 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [IsThumb];
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-01 10:42:55 +08:00
|
|
|
|
// TI - Thumb instruction.
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class TI<dag oops, dag iops, InstrItinClass itin, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: ThumbI<oops, iops, AddrModeNone, 2, itin, asm, "", pattern>;
|
2008-08-29 14:41:12 +08:00
|
|
|
|
|
2009-08-05 07:47:55 +08:00
|
|
|
|
// Two-address instructions
|
2010-03-24 01:23:59 +08:00
|
|
|
|
class TIt<dag oops, dag iops, InstrItinClass itin, string asm,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: ThumbI<oops, iops, AddrModeNone, 2, itin, asm, "$lhs = $dst",
|
2010-03-24 01:23:59 +08:00
|
|
|
|
pattern>;
|
2009-08-05 07:47:55 +08:00
|
|
|
|
|
2009-12-16 01:24:14 +08:00
|
|
|
|
// tBL, tBX 32-bit instructions
|
|
|
|
|
class TIx2<bits<5> opcod1, bits<2> opcod2, bit opcod3,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin, string asm,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: ThumbI<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
Encoding {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{31-27} = opcod1;
|
|
|
|
|
let Inst{15-14} = opcod2;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{12} = opcod3;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
}
|
2008-08-29 14:41:12 +08:00
|
|
|
|
|
|
|
|
|
// BR_JT instructions
|
2010-03-24 01:23:59 +08:00
|
|
|
|
class TJTI<dag oops, dag iops, InstrItinClass itin, string asm,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: ThumbI<oops, iops, AddrModeNone, 0, itin, asm, "", pattern>;
|
2008-08-29 14:41:12 +08:00
|
|
|
|
|
2009-06-24 03:38:13 +08:00
|
|
|
|
// Thumb1 only
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class Thumb1I<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin, string asm, string cstr, list<dag> pattern>
|
2009-12-16 01:24:14 +08:00
|
|
|
|
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = asm;
|
2009-06-24 03:38:13 +08:00
|
|
|
|
let Pattern = pattern;
|
2010-11-02 01:08:58 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
|
2009-06-24 03:38:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1I<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1I<oops, iops, AddrModeNone, 2, itin, asm, "", pattern>;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1Ix2<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1I<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>;
|
2009-07-11 14:43:01 +08:00
|
|
|
|
|
|
|
|
|
// Two-address instructions
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1It<dag oops, dag iops, InstrItinClass itin,
|
2010-03-13 09:08:20 +08:00
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1I<oops, iops, AddrModeNone, 2, itin,
|
2010-03-13 09:08:20 +08:00
|
|
|
|
asm, cstr, pattern>;
|
2009-07-11 14:43:01 +08:00
|
|
|
|
|
|
|
|
|
// Thumb1 instruction that can either be predicated or set CPSR.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class Thumb1sI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2009-07-11 14:43:01 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2009-12-16 01:24:14 +08:00
|
|
|
|
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let OutOperandList = !con(oops, (outs s_cc_out:$s));
|
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${s}${p}", asm);
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let Pattern = pattern;
|
2011-08-17 04:45:50 +08:00
|
|
|
|
let thumbArithFlagSetting = 1;
|
2010-11-02 01:08:58 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
|
2011-08-17 07:45:44 +08:00
|
|
|
|
let DecoderNamespace = "ThumbSBit";
|
2009-07-11 14:43:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1sI<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1sI<oops, iops, AddrModeNone, 2, itin, opc, asm, "", pattern>;
|
2009-07-11 14:43:01 +08:00
|
|
|
|
|
|
|
|
|
// Two-address instructions
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1sIt<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1sI<oops, iops, AddrModeNone, 2, itin, opc, asm,
|
2010-12-01 07:54:45 +08:00
|
|
|
|
"$Rn = $Rdn", pattern>;
|
2009-07-11 14:43:01 +08:00
|
|
|
|
|
|
|
|
|
// Thumb1 instruction that can be predicated.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class Thumb1pI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2009-07-11 14:43:01 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2009-12-16 01:24:14 +08:00
|
|
|
|
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", asm);
|
2009-07-11 14:43:01 +08:00
|
|
|
|
let Pattern = pattern;
|
2010-11-02 01:08:58 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
|
2009-07-11 14:43:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1pI<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1pI<oops, iops, AddrModeNone, 2, itin, opc, asm, "", pattern>;
|
2009-06-24 03:38:13 +08:00
|
|
|
|
|
|
|
|
|
// Two-address instructions
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T1pIt<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1pI<oops, iops, AddrModeNone, 2, itin, opc, asm,
|
2010-12-01 09:32:02 +08:00
|
|
|
|
"$Rn = $Rdn", pattern>;
|
2009-07-11 14:43:01 +08:00
|
|
|
|
|
2010-03-24 01:23:59 +08:00
|
|
|
|
class T1pIs<dag oops, dag iops,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1pI<oops, iops, AddrModeT1_s, 2, itin, opc, asm, "", pattern>;
|
2009-06-24 03:38:13 +08:00
|
|
|
|
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class Encoding16 : Encoding {
|
|
|
|
|
let Inst{31-16} = 0x0000;
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-16 01:24:14 +08:00
|
|
|
|
// A6.2 16-bit Thumb instruction encoding
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class T1Encoding<bits<6> opcode> : Encoding16 {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{15-10} = opcode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A6.2.1 Shift (immediate), add, subtract, move, and compare encoding.
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class T1General<bits<5> opcode> : Encoding16 {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{15-14} = 0b00;
|
|
|
|
|
let Inst{13-9} = opcode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A6.2.2 Data-processing encoding.
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class T1DataProcessing<bits<4> opcode> : Encoding16 {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{15-10} = 0b010000;
|
|
|
|
|
let Inst{9-6} = opcode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A6.2.3 Special data instructions and branch and exchange encoding.
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class T1Special<bits<4> opcode> : Encoding16 {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{15-10} = 0b010001;
|
2010-11-17 08:45:23 +08:00
|
|
|
|
let Inst{9-6} = opcode;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A6.2.4 Load/store single data item encoding.
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class T1LoadStore<bits<4> opA, bits<3> opB> : Encoding16 {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{15-12} = opA;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-9} = opB;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
}
|
2010-08-31 15:50:46 +08:00
|
|
|
|
class T1LdStSP<bits<3> opB> : T1LoadStore<0b1001, opB>; // SP relative
|
2009-12-16 01:24:14 +08:00
|
|
|
|
|
2011-05-27 11:50:53 +08:00
|
|
|
|
class T1BranchCond<bits<4> opcode> : Encoding16 {
|
|
|
|
|
let Inst{15-12} = opcode;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-01 06:57:21 +08:00
|
|
|
|
// Helper classes to encode Thumb1 loads and stores. For immediates, the
|
2010-12-01 07:54:45 +08:00
|
|
|
|
// following bits are used for "opA" (see A6.2.4):
|
2010-12-11 04:47:29 +08:00
|
|
|
|
//
|
2010-12-01 06:57:21 +08:00
|
|
|
|
// 0b0110 => Immediate, 4 bytes
|
|
|
|
|
// 0b1000 => Immediate, 2 bytes
|
|
|
|
|
// 0b0111 => Immediate, 1 byte
|
2010-12-01 09:38:08 +08:00
|
|
|
|
class T1pILdStEncode<bits<3> opcode, dag oops, dag iops, AddrMode am,
|
|
|
|
|
InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1pI<oops, iops, am, 2, itin, opc, asm, "", pattern>,
|
2010-12-01 07:16:25 +08:00
|
|
|
|
T1LoadStore<0b0101, opcode> {
|
2010-12-01 06:57:21 +08:00
|
|
|
|
bits<3> Rt;
|
|
|
|
|
bits<8> addr;
|
|
|
|
|
let Inst{8-6} = addr{5-3}; // Rm
|
|
|
|
|
let Inst{5-3} = addr{2-0}; // Rn
|
|
|
|
|
let Inst{2-0} = Rt;
|
|
|
|
|
}
|
2010-12-01 09:38:08 +08:00
|
|
|
|
class T1pILdStEncodeImm<bits<4> opA, bit opB, dag oops, dag iops, AddrMode am,
|
|
|
|
|
InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb1pI<oops, iops, am, 2, itin, opc, asm, "", pattern>,
|
2010-12-01 07:16:25 +08:00
|
|
|
|
T1LoadStore<opA, {opB,?,?}> {
|
2010-12-01 06:57:21 +08:00
|
|
|
|
bits<3> Rt;
|
|
|
|
|
bits<8> addr;
|
|
|
|
|
let Inst{10-6} = addr{7-3}; // imm5
|
|
|
|
|
let Inst{5-3} = addr{2-0}; // Rn
|
|
|
|
|
let Inst{2-0} = Rt;
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-16 01:24:14 +08:00
|
|
|
|
// A6.2.5 Miscellaneous 16-bit instructions encoding.
|
2009-12-16 10:32:54 +08:00
|
|
|
|
class T1Misc<bits<7> opcode> : Encoding16 {
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{15-12} = 0b1011;
|
|
|
|
|
let Inst{11-5} = opcode;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-25 10:08:06 +08:00
|
|
|
|
// Thumb2I - Thumb2 instruction. Almost all Thumb2 instructions are predicable.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class Thumb2I<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2009-06-25 10:08:06 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2009-06-25 10:08:06 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", asm);
|
2009-06-25 10:08:06 +08:00
|
|
|
|
let Pattern = pattern;
|
2009-07-02 14:38:40 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
2011-07-20 05:06:00 +08:00
|
|
|
|
let DecoderNamespace = "Thumb2";
|
2009-06-25 10:08:06 +08:00
|
|
|
|
}
|
2009-06-24 01:48:47 +08:00
|
|
|
|
|
2010-08-31 15:50:46 +08:00
|
|
|
|
// Same as Thumb2I except it can optionally modify CPSR. Note it's modeled as an
|
|
|
|
|
// input operand since by default it's a zero register. It will become an
|
|
|
|
|
// implicit def once it's "flipped".
|
2010-10-14 07:12:26 +08:00
|
|
|
|
//
|
2009-06-25 10:08:06 +08:00
|
|
|
|
// FIXME: This uses unified syntax so {s} comes before {p}. We should make it
|
|
|
|
|
// more consistent.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class Thumb2sI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2009-06-25 10:08:06 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2010-12-08 04:50:15 +08:00
|
|
|
|
bits<1> s; // condition-code set flag ('1' if the insn should set the flags)
|
|
|
|
|
let Inst{20} = s;
|
|
|
|
|
|
2009-06-25 10:08:06 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p, cc_out:$s));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${s}${p}", asm);
|
2009-06-25 10:08:06 +08:00
|
|
|
|
let Pattern = pattern;
|
2009-07-02 14:38:40 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
2011-07-20 05:06:00 +08:00
|
|
|
|
let DecoderNamespace = "Thumb2";
|
2009-06-25 10:08:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Special cases
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class Thumb2XI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2009-06-25 10:08:06 +08:00
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
2009-06-25 10:08:06 +08:00
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = asm;
|
2009-06-24 01:48:47 +08:00
|
|
|
|
let Pattern = pattern;
|
2009-07-02 14:38:40 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
2011-07-20 05:06:00 +08:00
|
|
|
|
let DecoderNamespace = "Thumb2";
|
2009-06-24 01:48:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class ThumbXI<dag oops, dag iops, AddrMode am, int sz,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
InstrItinClass itin,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2009-12-02 02:10:36 +08:00
|
|
|
|
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = asm;
|
2009-12-02 02:10:36 +08:00
|
|
|
|
let Pattern = pattern;
|
2010-11-02 01:08:58 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
|
2011-07-20 05:06:00 +08:00
|
|
|
|
let DecoderNamespace = "Thumb";
|
2009-12-02 02:10:36 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2I<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2I<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2Ii12<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2I<oops, iops, AddrModeT2_i12, 4, itin, opc, asm, "",pattern>;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2Ii8<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2I<oops, iops, AddrModeT2_i8, 4, itin, opc, asm, "", pattern>;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2Iso<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2I<oops, iops, AddrModeT2_so, 4, itin, opc, asm, "", pattern>;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2Ipc<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2I<oops, iops, AddrModeT2_pc, 4, itin, opc, asm, "", pattern>;
|
2010-12-11 04:51:35 +08:00
|
|
|
|
class T2Ii8s4<bit P, bit W, bit isLoad, dag oops, dag iops, InstrItinClass itin,
|
2011-09-09 06:07:06 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, cstr,
|
2009-12-16 01:24:14 +08:00
|
|
|
|
pattern> {
|
2010-12-02 03:18:46 +08:00
|
|
|
|
bits<4> Rt;
|
|
|
|
|
bits<4> Rt2;
|
|
|
|
|
bits<13> addr;
|
2010-12-11 04:51:35 +08:00
|
|
|
|
let Inst{31-25} = 0b1110100;
|
|
|
|
|
let Inst{24} = P;
|
|
|
|
|
let Inst{23} = addr{8};
|
|
|
|
|
let Inst{22} = 1;
|
|
|
|
|
let Inst{21} = W;
|
|
|
|
|
let Inst{20} = isLoad;
|
|
|
|
|
let Inst{19-16} = addr{12-9};
|
2010-12-02 03:18:46 +08:00
|
|
|
|
let Inst{15-12} = Rt{3-0};
|
|
|
|
|
let Inst{11-8} = Rt2{3-0};
|
|
|
|
|
let Inst{7-0} = addr{7-0};
|
2009-12-16 01:24:14 +08:00
|
|
|
|
}
|
2011-09-09 06:07:06 +08:00
|
|
|
|
class T2Ii8s4post<bit P, bit W, bit isLoad, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: Thumb2I<oops, iops, AddrModeT2_i8s4, 4, itin, opc, asm, cstr,
|
2011-08-05 07:18:05 +08:00
|
|
|
|
pattern> {
|
|
|
|
|
bits<4> Rt;
|
|
|
|
|
bits<4> Rt2;
|
2011-09-09 06:07:06 +08:00
|
|
|
|
bits<4> addr;
|
2011-08-05 07:18:05 +08:00
|
|
|
|
bits<9> imm;
|
|
|
|
|
let Inst{31-25} = 0b1110100;
|
|
|
|
|
let Inst{24} = P;
|
|
|
|
|
let Inst{23} = imm{8};
|
|
|
|
|
let Inst{22} = 1;
|
|
|
|
|
let Inst{21} = W;
|
|
|
|
|
let Inst{20} = isLoad;
|
2011-09-09 06:07:06 +08:00
|
|
|
|
let Inst{19-16} = addr;
|
2011-08-05 07:18:05 +08:00
|
|
|
|
let Inst{15-12} = Rt{3-0};
|
|
|
|
|
let Inst{11-8} = Rt2{3-0};
|
|
|
|
|
let Inst{7-0} = imm{7-0};
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2sI<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2sI<oops, iops, AddrModeNone, 4, itin, opc, asm, "", pattern>;
|
2009-06-25 10:08:06 +08:00
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2XI<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, "", pattern>;
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class T2JTI<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2XI<oops, iops, AddrModeNone, 0, itin, asm, "", pattern>;
|
2009-06-24 01:48:47 +08:00
|
|
|
|
|
2011-01-21 00:58:48 +08:00
|
|
|
|
// Move to/from coprocessor instructions
|
2013-06-27 00:52:40 +08:00
|
|
|
|
class T2Cop<bits<4> opc, dag oops, dag iops, string opcstr, string asm,
|
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: T2I <oops, iops, NoItinerary, opcstr, asm, pattern>, Requires<[IsThumb2]> {
|
2011-07-14 05:17:59 +08:00
|
|
|
|
let Inst{31-28} = opc;
|
2011-01-21 00:58:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-13 09:08:20 +08:00
|
|
|
|
// Two-address instructions
|
|
|
|
|
class T2XIt<dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: Thumb2XI<oops, iops, AddrModeNone, 4, itin, asm, cstr, pattern>;
|
2009-09-28 17:14:39 +08:00
|
|
|
|
|
2011-09-08 08:39:19 +08:00
|
|
|
|
// T2Ipreldst - Thumb2 pre-indexed load / store instructions.
|
|
|
|
|
class T2Ipreldst<bit signed, bits<2> opcod, bit load, bit pre,
|
2009-12-16 01:24:14 +08:00
|
|
|
|
dag oops, dag iops,
|
|
|
|
|
AddrMode am, IndexMode im, InstrItinClass itin,
|
2009-07-02 15:28:31 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> {
|
2009-07-02 15:28:31 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", asm);
|
2009-07-02 15:28:31 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
2011-07-20 05:06:00 +08:00
|
|
|
|
let DecoderNamespace = "Thumb2";
|
2011-09-08 08:39:19 +08:00
|
|
|
|
|
|
|
|
|
bits<4> Rt;
|
|
|
|
|
bits<13> addr;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{31-27} = 0b11111;
|
|
|
|
|
let Inst{26-25} = 0b00;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{24} = signed;
|
|
|
|
|
let Inst{23} = 0;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
let Inst{22-21} = opcod;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{20} = load;
|
2011-09-08 08:39:19 +08:00
|
|
|
|
let Inst{19-16} = addr{12-9};
|
|
|
|
|
let Inst{15-12} = Rt{3-0};
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11} = 1;
|
2009-12-16 01:24:14 +08:00
|
|
|
|
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{10} = pre; // The P bit.
|
2011-09-08 08:39:19 +08:00
|
|
|
|
let Inst{9} = addr{8}; // Sign bit
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{8} = 1; // The W bit.
|
2011-09-08 08:39:19 +08:00
|
|
|
|
let Inst{7-0} = addr{7-0};
|
2011-09-13 02:56:30 +08:00
|
|
|
|
|
|
|
|
|
let DecoderMethod = "DecodeT2LdStPre";
|
2011-09-08 08:39:19 +08:00
|
|
|
|
}
|
2010-12-11 04:47:29 +08:00
|
|
|
|
|
2011-09-08 08:39:19 +08:00
|
|
|
|
// T2Ipostldst - Thumb2 post-indexed load / store instructions.
|
|
|
|
|
class T2Ipostldst<bit signed, bits<2> opcod, bit load, bit pre,
|
|
|
|
|
dag oops, dag iops,
|
|
|
|
|
AddrMode am, IndexMode im, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: InstARM<am, 4, im, ThumbFrm, GenericDomain, cstr, itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
|
|
|
|
let AsmString = !strconcat(opc, "${p}", asm);
|
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
|
|
|
|
let DecoderNamespace = "Thumb2";
|
2010-12-11 04:47:29 +08:00
|
|
|
|
|
2010-11-30 08:14:31 +08:00
|
|
|
|
bits<4> Rt;
|
|
|
|
|
bits<4> Rn;
|
2011-09-08 09:01:32 +08:00
|
|
|
|
bits<9> offset;
|
2011-09-08 08:39:19 +08:00
|
|
|
|
let Inst{31-27} = 0b11111;
|
|
|
|
|
let Inst{26-25} = 0b00;
|
|
|
|
|
let Inst{24} = signed;
|
|
|
|
|
let Inst{23} = 0;
|
|
|
|
|
let Inst{22-21} = opcod;
|
|
|
|
|
let Inst{20} = load;
|
|
|
|
|
let Inst{19-16} = Rn;
|
2010-11-30 08:14:31 +08:00
|
|
|
|
let Inst{15-12} = Rt{3-0};
|
2011-09-08 08:39:19 +08:00
|
|
|
|
let Inst{11} = 1;
|
|
|
|
|
// (P, W) = (1, 1) Pre-indexed or (0, 1) Post-indexed
|
|
|
|
|
let Inst{10} = pre; // The P bit.
|
2011-09-08 09:01:32 +08:00
|
|
|
|
let Inst{9} = offset{8}; // Sign bit
|
2011-09-08 08:39:19 +08:00
|
|
|
|
let Inst{8} = 1; // The W bit.
|
2011-09-08 09:01:32 +08:00
|
|
|
|
let Inst{7-0} = offset{7-0};
|
2011-09-13 02:56:30 +08:00
|
|
|
|
|
|
|
|
|
let DecoderMethod = "DecodeT2LdStPre";
|
2009-07-02 15:28:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-28 03:59:26 +08:00
|
|
|
|
// T1Pat - Same as Pat<>, but requires that the compiler be in Thumb1 mode.
|
|
|
|
|
class T1Pat<dag pattern, dag result> : Pat<pattern, result> {
|
2010-11-02 01:08:58 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb, IsThumb1Only];
|
2009-07-28 03:59:26 +08:00
|
|
|
|
}
|
2009-07-02 15:28:31 +08:00
|
|
|
|
|
2011-05-04 01:29:22 +08:00
|
|
|
|
// T2v6Pat - Same as Pat<>, but requires V6T2 Thumb2 mode.
|
|
|
|
|
class T2v6Pat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [IsThumb2, HasV6T2];
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-27 10:26:13 +08:00
|
|
|
|
// T2Pat - Same as Pat<>, but requires that the compiler be in Thumb2 mode.
|
|
|
|
|
class T2Pat<dag pattern, dag result> : Pat<pattern, result> {
|
2009-07-02 14:38:40 +08:00
|
|
|
|
list<Predicate> Predicates = [IsThumb2];
|
2009-06-24 01:48:47 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-11 10:11:05 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// ARM VFP Instruction templates.
|
|
|
|
|
//
|
|
|
|
|
|
2009-07-11 01:03:29 +08:00
|
|
|
|
// Almost all VFP instructions are predicable.
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class VFPI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
|
2010-10-13 05:22:40 +08:00
|
|
|
|
bits<4> p;
|
|
|
|
|
let Inst{31-28} = p;
|
2009-07-11 01:03:29 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", asm);
|
2009-07-11 01:03:29 +08:00
|
|
|
|
let Pattern = pattern;
|
2010-12-02 05:54:50 +08:00
|
|
|
|
let PostEncoderMethod = "VFPThumb2PostEncoder";
|
2011-08-10 04:55:18 +08:00
|
|
|
|
let DecoderNamespace = "VFP";
|
2009-07-11 01:03:29 +08:00
|
|
|
|
list<Predicate> Predicates = [HasVFP2];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Special cases
|
2011-07-14 07:22:26 +08:00
|
|
|
|
class VFPXI<dag oops, dag iops, AddrMode am, int sz,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
IndexMode im, Format f, InstrItinClass itin,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2009-11-02 08:10:38 +08:00
|
|
|
|
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
|
2010-11-17 08:45:23 +08:00
|
|
|
|
bits<4> p;
|
|
|
|
|
let Inst{31-28} = p;
|
2009-07-11 01:03:29 +08:00
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
2010-05-25 04:08:34 +08:00
|
|
|
|
let AsmString = asm;
|
2009-07-11 01:03:29 +08:00
|
|
|
|
let Pattern = pattern;
|
2010-12-02 05:54:50 +08:00
|
|
|
|
let PostEncoderMethod = "VFPThumb2PostEncoder";
|
2011-08-10 04:55:18 +08:00
|
|
|
|
let DecoderNamespace = "VFP";
|
2009-07-11 01:03:29 +08:00
|
|
|
|
list<Predicate> Predicates = [HasVFP2];
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class VFPAI<dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: VFPI<oops, iops, AddrModeNone, 4, IndexModeNone, f, itin,
|
2010-12-02 05:54:50 +08:00
|
|
|
|
opc, asm, "", pattern> {
|
|
|
|
|
let PostEncoderMethod = "VFPThumb2PostEncoder";
|
|
|
|
|
}
|
2009-07-11 01:03:29 +08:00
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
// ARM VFP addrmode5 loads and stores
|
|
|
|
|
class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2008-11-12 05:48:44 +08:00
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: VFPI<oops, iops, AddrMode5, 4, IndexModeNone,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
VFPLdStFrm, itin, opc, asm, "", pattern> {
|
2010-11-04 08:59:42 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Dd;
|
|
|
|
|
bits<13> addr;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{23} = addr{8}; // U (add = (U == '1'))
|
|
|
|
|
let Inst{22} = Dd{4};
|
|
|
|
|
let Inst{19-16} = addr{12-9}; // Rn
|
|
|
|
|
let Inst{15-12} = Dd{3-0};
|
|
|
|
|
let Inst{7-0} = addr{7-0}; // imm8
|
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
let Inst{27-24} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 1; // Double precision
|
2009-11-02 08:11:06 +08:00
|
|
|
|
|
2011-02-16 08:35:02 +08:00
|
|
|
|
// Loads & stores operate on both NEON and VFP pipelines.
|
2010-04-05 11:10:20 +08:00
|
|
|
|
let D = VFPNeonDomain;
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
2008-11-12 05:48:44 +08:00
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: VFPI<oops, iops, AddrMode5, 4, IndexModeNone,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
VFPLdStFrm, itin, opc, asm, "", pattern> {
|
2010-11-04 08:59:42 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<13> addr;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{23} = addr{8}; // U (add = (U == '1'))
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
let Inst{19-16} = addr{12-9}; // Rn
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{7-0} = addr{7-0}; // imm8
|
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
let Inst{27-24} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 0; // Single precision
|
2011-02-16 08:35:02 +08:00
|
|
|
|
|
|
|
|
|
// Loads & stores operate on both NEON and VFP pipelines.
|
|
|
|
|
let D = VFPNeonDomain;
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-25 18:26:26 +08:00
|
|
|
|
class AHI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
[ARM] Armv8.2-A FP16 code generation (part 1/3)
This is the groundwork for Armv8.2-A FP16 code generation .
Clang passes and returns _Float16 values as floats, together with the required
bitconverts and truncs etc. to implement correct AAPCS behaviour, see D42318.
We will implement half-precision argument passing/returning lowering in the ARM
backend soon, but for now this means that this:
_Float16 sub(_Float16 a, _Float16 b) {
return a + b;
}
gets lowered to this:
define float @sub(float %a.coerce, float %b.coerce) {
entry:
%0 = bitcast float %a.coerce to i32
%tmp.0.extract.trunc = trunc i32 %0 to i16
%1 = bitcast i16 %tmp.0.extract.trunc to half
<SNIP>
%add = fadd half %1, %3
<SNIP>
}
When FullFP16 is *not* supported, we don't make f16 a legal type, and we get
legalization for "free", i.e. nothing changes and everything works as before.
And also f16 argument passing/returning is handled.
When FullFP16 is supported, we do make f16 a legal type, and have 2 places that
we need to patch up: f16 argument passing and returning, which involves minor
tweaks to avoid unnecessary code generation for some bitcasts.
As a "demonstrator" that this works for the different FP16, FullFP16, softfp
modes, etc., I've added match rules to the VSUB instruction description showing
that we can codegen this instruction from IR, but more importantly, also to
some conversion instructions. These conversions were causing issue before in
the FP16 and FullFP16 cases.
I've also added match rules to the VLDRH and VSTRH desriptions, so that we can
actually compile the entire half-precision sub code example above. This showed
that these loads and stores had the wrong addressing mode specified: AddrMode5
instead of AddrMode5FP16, which turned out not be implemented at all, so that
has also been added.
This is the minimal patch that shows all the different moving parts. In patch
2/3 I will add some efficient lowering of bitcasts, and in 2/3 I will add the
remaining Armv8.2-A FP16 instruction descriptions.
Thanks to Sam Parker and Oliver Stannard for their help and reviews!
Differential Revision: https://reviews.llvm.org/D38315
llvm-svn: 323512
2018-01-26 17:26:40 +08:00
|
|
|
|
: VFPI<oops, iops, AddrMode5FP16, 4, IndexModeNone,
|
2016-01-25 18:26:26 +08:00
|
|
|
|
VFPLdStFrm, itin, opc, asm, "", pattern> {
|
|
|
|
|
list<Predicate> Predicates = [HasFullFP16];
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<13> addr;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{23} = addr{8}; // U (add = (U == '1'))
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
let Inst{19-16} = addr{12-9}; // Rn
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{7-0} = addr{7-0}; // imm8
|
|
|
|
|
|
|
|
|
|
let Inst{27-24} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{11-8} = 0b1001; // Half precision
|
|
|
|
|
|
|
|
|
|
// Loads & stores operate on both NEON and VFP pipelines.
|
|
|
|
|
let D = VFPNeonDomain;
|
[ARM] Make fullfp16 instructions not conditionalisable.
More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.
In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.
(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)
So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.
I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.
Reviewers: SjoerdMeijer, t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57823
llvm-svn: 354768
2019-02-25 18:39:53 +08:00
|
|
|
|
|
|
|
|
|
let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
|
2016-01-25 18:26:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-16 08:31:02 +08:00
|
|
|
|
// VFP Load / store multiple pseudo instructions.
|
|
|
|
|
class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<AddrMode4, 4, IndexModeNone, Pseudo, VFPNeonDomain,
|
2010-09-16 08:31:02 +08:00
|
|
|
|
cstr, itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [HasVFP2];
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
// Load / store multiple
|
2013-05-31 23:55:51 +08:00
|
|
|
|
|
|
|
|
|
// Unknown precision
|
|
|
|
|
class AXXI4<dag oops, dag iops, IndexMode im,
|
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: VFPXI<oops, iops, AddrMode4, 4, im,
|
|
|
|
|
VFPLdStFrm, NoItinerary, asm, cstr, pattern> {
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<13> regs;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{22} = 0;
|
|
|
|
|
let Inst{15-12} = regs{11-8};
|
|
|
|
|
let Inst{7-1} = regs{7-1};
|
|
|
|
|
|
|
|
|
|
let Inst{27-25} = 0b110;
|
|
|
|
|
let Inst{11-8} = 0b1011;
|
|
|
|
|
let Inst{0} = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Double precision
|
2010-09-08 08:25:50 +08:00
|
|
|
|
class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
|
2010-03-13 09:08:20 +08:00
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: VFPXI<oops, iops, AddrMode4, 4, im,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
VFPLdStMulFrm, itin, asm, cstr, pattern> {
|
2010-11-17 08:45:23 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<13> regs;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{22} = regs{12};
|
|
|
|
|
let Inst{15-12} = regs{11-8};
|
2013-05-31 23:55:51 +08:00
|
|
|
|
let Inst{7-1} = regs{7-1};
|
2010-11-17 08:45:23 +08:00
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
let Inst{27-25} = 0b110;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 1; // Double precision
|
2013-05-31 23:55:51 +08:00
|
|
|
|
let Inst{0} = 0;
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-05-31 23:55:51 +08:00
|
|
|
|
// Single Precision
|
2010-09-08 08:25:50 +08:00
|
|
|
|
class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
|
2010-03-13 09:08:20 +08:00
|
|
|
|
string asm, string cstr, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: VFPXI<oops, iops, AddrMode4, 4, im,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
VFPLdStMulFrm, itin, asm, cstr, pattern> {
|
2010-11-17 08:45:23 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<4> Rn;
|
|
|
|
|
bits<13> regs;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{19-16} = Rn;
|
|
|
|
|
let Inst{22} = regs{8};
|
|
|
|
|
let Inst{15-12} = regs{12-9};
|
|
|
|
|
let Inst{7-0} = regs{7-0};
|
|
|
|
|
|
2008-11-12 05:48:44 +08:00
|
|
|
|
let Inst{27-25} = 0b110;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 0; // Single precision
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Double precision, unary
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class ADuI<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, list<dag> pattern>
|
2009-08-07 00:52:47 +08:00
|
|
|
|
: VFPAI<oops, iops, VFPUnaryFrm, itin, opc, asm, pattern> {
|
2010-11-01 14:00:39 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Dd;
|
|
|
|
|
bits<5> Dm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Dm{3-0};
|
|
|
|
|
let Inst{5} = Dm{4};
|
|
|
|
|
let Inst{15-12} = Dd{3-0};
|
|
|
|
|
let Inst{22} = Dd{4};
|
|
|
|
|
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 1; // Double precision
|
2013-07-09 19:26:18 +08:00
|
|
|
|
let Inst{7-6} = opcod4;
|
|
|
|
|
let Inst{4} = opcod5;
|
2013-10-24 23:49:39 +08:00
|
|
|
|
|
|
|
|
|
let Predicates = [HasVFP2, HasDPVFP];
|
2013-07-09 19:26:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Double precision, unary, not-predicated
|
|
|
|
|
class ADuInp<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
|
|
|
|
: VFPXI<oops, iops, AddrModeNone, 4, IndexModeNone, VFPUnaryFrm, itin, asm, "", pattern> {
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Dd;
|
|
|
|
|
bits<5> Dm;
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Dm{3-0};
|
|
|
|
|
let Inst{5} = Dm{4};
|
|
|
|
|
let Inst{15-12} = Dd{3-0};
|
|
|
|
|
let Inst{22} = Dd{4};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 1; // Double precision
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{7-6} = opcod4;
|
|
|
|
|
let Inst{4} = opcod5;
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Double precision, binary
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class ADbI<bits<5> opcod1, bits<2> opcod2, bit op6, bit op4, dag oops,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
dag iops, InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2009-08-07 00:52:47 +08:00
|
|
|
|
: VFPAI<oops, iops, VFPBinaryFrm, itin, opc, asm, pattern> {
|
2010-11-01 14:00:39 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Dd;
|
|
|
|
|
bits<5> Dn;
|
|
|
|
|
bits<5> Dm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Dm{3-0};
|
|
|
|
|
let Inst{5} = Dm{4};
|
|
|
|
|
let Inst{19-16} = Dn{3-0};
|
|
|
|
|
let Inst{7} = Dn{4};
|
|
|
|
|
let Inst{15-12} = Dd{3-0};
|
|
|
|
|
let Inst{22} = Dd{4};
|
|
|
|
|
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 1; // Double precision
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2013-10-24 23:49:39 +08:00
|
|
|
|
|
|
|
|
|
let Predicates = [HasVFP2, HasDPVFP];
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-04 22:57:20 +08:00
|
|
|
|
// FP, binary, not predicated
|
2013-07-07 04:50:18 +08:00
|
|
|
|
class ADbInp<bits<5> opcod1, bits<2> opcod2, bit opcod3, dag oops, dag iops,
|
2013-07-04 22:57:20 +08:00
|
|
|
|
InstrItinClass itin, string asm, list<dag> pattern>
|
2013-07-09 17:59:04 +08:00
|
|
|
|
: VFPXI<oops, iops, AddrModeNone, 4, IndexModeNone, VFPBinaryFrm, itin,
|
|
|
|
|
asm, "", pattern>
|
2013-07-04 22:57:20 +08:00
|
|
|
|
{
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Dd;
|
|
|
|
|
bits<5> Dn;
|
|
|
|
|
bits<5> Dm;
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Dm{3-0};
|
|
|
|
|
let Inst{5} = Dm{4};
|
|
|
|
|
let Inst{19-16} = Dn{3-0};
|
|
|
|
|
let Inst{7} = Dn{4};
|
|
|
|
|
let Inst{15-12} = Dd{3-0};
|
|
|
|
|
let Inst{22} = Dd{4};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 1; // double precision
|
2013-07-07 04:50:18 +08:00
|
|
|
|
let Inst{6} = opcod3;
|
2013-07-04 22:57:20 +08:00
|
|
|
|
let Inst{4} = 0;
|
2013-10-24 23:49:39 +08:00
|
|
|
|
|
|
|
|
|
let Predicates = [HasVFP2, HasDPVFP];
|
2013-07-04 22:57:20 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-09 17:59:04 +08:00
|
|
|
|
// Single precision, unary, predicated
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class ASuI<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, list<dag> pattern>
|
2009-08-07 00:52:47 +08:00
|
|
|
|
: VFPAI<oops, iops, VFPUnaryFrm, itin, opc, asm, pattern> {
|
2010-11-01 14:00:39 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
2013-07-09 17:59:04 +08:00
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 0; // Single precision
|
|
|
|
|
let Inst{7-6} = opcod4;
|
|
|
|
|
let Inst{4} = opcod5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Single precision, unary, non-predicated
|
|
|
|
|
class ASuInp<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
|
|
|
|
: VFPXI<oops, iops, AddrModeNone, 4, IndexModeNone,
|
|
|
|
|
VFPUnaryFrm, itin, asm, "", pattern> {
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 0; // Single precision
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{7-6} = opcod4;
|
|
|
|
|
let Inst{4} = opcod5;
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-01 10:42:55 +08:00
|
|
|
|
// Single precision unary, if no NEON. Same as ASuI except not available if
|
|
|
|
|
// NEON is enabled.
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class ASuIn<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, list<dag> pattern>
|
|
|
|
|
: ASuI<opcod1, opcod2, opcod3, opcod4, opcod5, oops, iops, itin, opc, asm,
|
|
|
|
|
pattern> {
|
2009-08-05 04:39:05 +08:00
|
|
|
|
list<Predicate> Predicates = [HasVFP2,DontUseNEONForFP];
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-11 10:11:05 +08:00
|
|
|
|
// Single precision, binary
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class ASbI<bits<5> opcod1, bits<2> opcod2, bit op6, bit op4, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
2009-08-07 00:52:47 +08:00
|
|
|
|
: VFPAI<oops, iops, VFPBinaryFrm, itin, opc, asm, pattern> {
|
2010-11-01 14:00:39 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sn;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{19-16} = Sn{4-1};
|
|
|
|
|
let Inst{7} = Sn{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
2010-10-13 06:03:19 +08:00
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 0; // Single precision
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2008-11-11 10:11:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-04 22:57:20 +08:00
|
|
|
|
// Single precision, binary, not predicated
|
2013-07-07 04:50:18 +08:00
|
|
|
|
class ASbInp<bits<5> opcod1, bits<2> opcod2, bit opcod3, dag oops, dag iops,
|
2013-07-04 22:57:20 +08:00
|
|
|
|
InstrItinClass itin, string asm, list<dag> pattern>
|
|
|
|
|
: VFPXI<oops, iops, AddrModeNone, 4, IndexModeNone,
|
|
|
|
|
VFPBinaryFrm, itin, asm, "", pattern>
|
|
|
|
|
{
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sn;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{19-16} = Sn{4-1};
|
|
|
|
|
let Inst{7} = Sn{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{11-9} = 0b101;
|
|
|
|
|
let Inst{8} = 0; // Single precision
|
2013-07-07 04:50:18 +08:00
|
|
|
|
let Inst{6} = opcod3;
|
2013-07-04 22:57:20 +08:00
|
|
|
|
let Inst{4} = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-01 10:42:55 +08:00
|
|
|
|
// Single precision binary, if no NEON. Same as ASbI except not available if
|
|
|
|
|
// NEON is enabled.
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class ASbIn<bits<5> opcod1, bits<2> opcod2, bit op6, bit op4, dag oops,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
dag iops, InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2010-01-30 07:21:10 +08:00
|
|
|
|
: ASbI<opcod1, opcod2, op6, op4, oops, iops, itin, opc, asm, pattern> {
|
2009-08-05 01:53:06 +08:00
|
|
|
|
list<Predicate> Predicates = [HasVFP2,DontUseNEONForFP];
|
2010-11-01 14:00:39 +08:00
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sn;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{19-16} = Sn{4-1};
|
|
|
|
|
let Inst{7} = Sn{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
2009-08-05 01:53:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-01-25 18:26:26 +08:00
|
|
|
|
// Half precision, unary, predicated
|
|
|
|
|
class AHuI<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin, string opc,
|
|
|
|
|
string asm, list<dag> pattern>
|
|
|
|
|
: VFPAI<oops, iops, VFPUnaryFrm, itin, opc, asm, pattern> {
|
|
|
|
|
list<Predicate> Predicates = [HasFullFP16];
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
|
|
|
|
let Inst{11-8} = 0b1001; // Half precision
|
|
|
|
|
let Inst{7-6} = opcod4;
|
|
|
|
|
let Inst{4} = opcod5;
|
[ARM] Make fullfp16 instructions not conditionalisable.
More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.
In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.
(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)
So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.
I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.
Reviewers: SjoerdMeijer, t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57823
llvm-svn: 354768
2019-02-25 18:39:53 +08:00
|
|
|
|
|
|
|
|
|
let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
|
2016-01-25 18:26:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Half precision, unary, non-predicated
|
|
|
|
|
class AHuInp<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<2> opcod4,
|
|
|
|
|
bit opcod5, dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string asm, list<dag> pattern>
|
|
|
|
|
: VFPXI<oops, iops, AddrModeNone, 4, IndexModeNone,
|
|
|
|
|
VFPUnaryFrm, itin, asm, "", pattern> {
|
|
|
|
|
list<Predicate> Predicates = [HasFullFP16];
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
|
|
|
|
let Inst{11-8} = 0b1001; // Half precision
|
|
|
|
|
let Inst{7-6} = opcod4;
|
|
|
|
|
let Inst{4} = opcod5;
|
[ARM] Make fullfp16 instructions not conditionalisable.
More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.
In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.
(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)
So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.
I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.
Reviewers: SjoerdMeijer, t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57823
llvm-svn: 354768
2019-02-25 18:39:53 +08:00
|
|
|
|
|
|
|
|
|
let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
|
2016-01-25 18:26:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Half precision, binary
|
|
|
|
|
class AHbI<bits<5> opcod1, bits<2> opcod2, bit op6, bit op4, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: VFPAI<oops, iops, VFPBinaryFrm, itin, opc, asm, pattern> {
|
|
|
|
|
list<Predicate> Predicates = [HasFullFP16];
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sn;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{19-16} = Sn{4-1};
|
|
|
|
|
let Inst{7} = Sn{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{11-8} = 0b1001; // Half precision
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
[ARM] Make fullfp16 instructions not conditionalisable.
More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.
In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.
(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)
So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.
I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.
Reviewers: SjoerdMeijer, t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57823
llvm-svn: 354768
2019-02-25 18:39:53 +08:00
|
|
|
|
|
|
|
|
|
let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
|
2016-01-25 18:26:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Half precision, binary, not predicated
|
|
|
|
|
class AHbInp<bits<5> opcod1, bits<2> opcod2, bit opcod3, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string asm, list<dag> pattern>
|
|
|
|
|
: VFPXI<oops, iops, AddrModeNone, 4, IndexModeNone,
|
|
|
|
|
VFPBinaryFrm, itin, asm, "", pattern> {
|
|
|
|
|
list<Predicate> Predicates = [HasFullFP16];
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Sd;
|
|
|
|
|
bits<5> Sn;
|
|
|
|
|
bits<5> Sm;
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands.
|
|
|
|
|
let Inst{3-0} = Sm{4-1};
|
|
|
|
|
let Inst{5} = Sm{0};
|
|
|
|
|
let Inst{19-16} = Sn{4-1};
|
|
|
|
|
let Inst{7} = Sn{0};
|
|
|
|
|
let Inst{15-12} = Sd{4-1};
|
|
|
|
|
let Inst{22} = Sd{0};
|
|
|
|
|
|
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{11-8} = 0b1001; // Half precision
|
|
|
|
|
let Inst{6} = opcod3;
|
|
|
|
|
let Inst{4} = 0;
|
[ARM] Make fullfp16 instructions not conditionalisable.
More or less all the instructions defined in the v8.2a full-fp16
extension are defined as UNPREDICTABLE if you put them in an IT block
(Thumb) or use with any condition other than AL (ARM). LLVM didn't
know that, and was happy to conditionalise them.
In order to force these instructions to count as not predicable, I had
to make a small Tablegen change. The code generation back end mostly
decides if an instruction was predicable by looking for something it
can identify as a predicate operand; there's an isPredicable bit flag
that overrides that check in the positive direction, but nothing that
overrides it in the negative direction.
(I considered the alternative approach of actually removing the
predicate operand from those instructions, but thought that it would
be more painful overall for instructions differing only in data type
to have different shapes of operand list. This way, the only code that
has to notice the difference is the if-converter.)
So I've added an isUnpredicable bit alongside isPredicable, and set
that bit on the right subset of FP16 instructions, and also on the
VSEL, VMAXNM/VMINNM and VRINT[ANPM] families which should be
unpredicable for all data types.
I've included a couple of representative regression tests, both of
which previously caused an fp16 instruction to be conditionalised in
ARM state and (with -arm-no-restrict-it) to be put in an IT block in
Thumb.
Reviewers: SjoerdMeijer, t.p.northover, efriedma
Reviewed By: efriedma
Subscribers: jdoerfert, javed.absar, kristof.beyls, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57823
llvm-svn: 354768
2019-02-25 18:39:53 +08:00
|
|
|
|
|
|
|
|
|
let isUnpredicable = 1; // FP16 instructions cannot in general be conditional
|
2016-01-25 18:26:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-12 14:41:41 +08:00
|
|
|
|
// VFP conversion instructions
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class AVConv1I<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<4> opcod4,
|
|
|
|
|
dag oops, dag iops, InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2009-08-07 00:52:47 +08:00
|
|
|
|
: VFPAI<oops, iops, VFPConv1Frm, itin, opc, asm, pattern> {
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{27-23} = opcod1;
|
|
|
|
|
let Inst{21-20} = opcod2;
|
|
|
|
|
let Inst{19-16} = opcod3;
|
|
|
|
|
let Inst{11-8} = opcod4;
|
2008-11-12 14:41:41 +08:00
|
|
|
|
let Inst{6} = 1;
|
2010-01-30 07:21:10 +08:00
|
|
|
|
let Inst{4} = 0;
|
2008-11-12 03:40:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-12 02:47:03 +08:00
|
|
|
|
// VFP conversion between floating-point and fixed-point
|
|
|
|
|
class AVConv1XI<bits<5> op1, bits<2> op2, bits<4> op3, bits<4> op4, bit op5,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin, string opc, string asm,
|
|
|
|
|
list<dag> pattern>
|
2010-02-12 02:47:03 +08:00
|
|
|
|
: AVConv1I<op1, op2, op3, op4, oops, iops, itin, opc, asm, pattern> {
|
2011-12-23 03:55:21 +08:00
|
|
|
|
bits<5> fbits;
|
2010-02-12 02:47:03 +08:00
|
|
|
|
// size (fixed-point number): sx == 0 ? 16 : 32
|
|
|
|
|
let Inst{7} = op5; // sx
|
2011-12-23 03:55:21 +08:00
|
|
|
|
let Inst{5} = fbits{0};
|
|
|
|
|
let Inst{3-0} = fbits{4-1};
|
2010-02-12 02:47:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-11 06:17:39 +08:00
|
|
|
|
// VFP conversion instructions, if no NEON
|
2010-01-30 07:21:10 +08:00
|
|
|
|
class AVConv1In<bits<5> opcod1, bits<2> opcod2, bits<4> opcod3, bits<4> opcod4,
|
2009-08-11 06:17:39 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
2010-01-30 07:21:10 +08:00
|
|
|
|
: AVConv1I<opcod1, opcod2, opcod3, opcod4, oops, iops, itin, opc, asm,
|
|
|
|
|
pattern> {
|
2009-08-11 06:17:39 +08:00
|
|
|
|
list<Predicate> Predicates = [HasVFP2,DontUseNEONForFP];
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-12 14:41:41 +08:00
|
|
|
|
class AVConvXI<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, Format f,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin,
|
|
|
|
|
string opc, string asm, list<dag> pattern>
|
|
|
|
|
: VFPAI<oops, iops, f, itin, opc, asm, pattern> {
|
2008-11-12 06:46:12 +08:00
|
|
|
|
let Inst{27-20} = opcod1;
|
|
|
|
|
let Inst{11-8} = opcod2;
|
|
|
|
|
let Inst{4} = 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AVConv2I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv2Frm, itin, opc, asm, pattern>;
|
2008-11-12 14:41:41 +08:00
|
|
|
|
|
2010-03-24 01:23:59 +08:00
|
|
|
|
class AVConv3I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv3Frm, itin, opc, asm, pattern>;
|
2008-11-12 14:41:41 +08:00
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AVConv4I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv4Frm, itin, opc, asm, pattern>;
|
2008-11-12 14:41:41 +08:00
|
|
|
|
|
2009-08-07 00:52:47 +08:00
|
|
|
|
class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, list<dag> pattern>
|
|
|
|
|
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv5Frm, itin, opc, asm, pattern>;
|
2008-11-12 03:40:26 +08:00
|
|
|
|
|
2008-08-29 14:41:12 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2009-06-23 07:27:02 +08:00
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
// ARM NEON Instruction templates.
|
|
|
|
|
//
|
2008-08-29 14:41:12 +08:00
|
|
|
|
|
2010-03-20 08:17:00 +08:00
|
|
|
|
class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
|
|
|
|
|
InstrItinClass itin, string opc, string dt, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
|
2009-11-24 05:57:23 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
|
2009-11-24 05:57:23 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [HasNEON];
|
2011-08-16 07:38:54 +08:00
|
|
|
|
let DecoderNamespace = "NEON";
|
2009-11-24 05:57:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Same as NeonI except it does not have a "data type" specifier.
|
2010-03-24 04:40:44 +08:00
|
|
|
|
class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
|
|
|
|
|
InstrItinClass itin, string opc, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", "\t", asm);
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [HasNEON];
|
2011-08-16 07:38:54 +08:00
|
|
|
|
let DecoderNamespace = "NEON";
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-17 21:59:38 +08:00
|
|
|
|
// Same as NeonI except it is not predicated
|
|
|
|
|
class NeonInp<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
|
|
|
|
|
InstrItinClass itin, string opc, string dt, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
|
|
|
|
: InstARM<am, 4, im, f, NeonDomain, cstr, itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = iops;
|
|
|
|
|
let AsmString = !strconcat(opc, ".", dt, "\t", asm);
|
|
|
|
|
let Pattern = pattern;
|
|
|
|
|
list<Predicate> Predicates = [HasNEON];
|
|
|
|
|
let DecoderNamespace = "NEON";
|
|
|
|
|
|
|
|
|
|
let Inst{31-28} = 0b1111;
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-08 05:53:04 +08:00
|
|
|
|
class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
2010-03-20 08:17:00 +08:00
|
|
|
|
: NeonI<oops, iops, AddrMode6, IndexModeNone, NLdStFrm, itin, opc, dt, asm,
|
|
|
|
|
cstr, pattern> {
|
2009-07-09 02:11:30 +08:00
|
|
|
|
let Inst{31-24} = 0b11110100;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{23} = op23;
|
2009-10-20 08:19:08 +08:00
|
|
|
|
let Inst{21-20} = op21_20;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-8} = op11_8;
|
|
|
|
|
let Inst{7-4} = op7_4;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-11-15 13:19:05 +08:00
|
|
|
|
let PostEncoderMethod = "NEONThumb2LoadStorePostEncoder";
|
2011-08-11 03:01:10 +08:00
|
|
|
|
let DecoderNamespace = "NEONLoadStore";
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-11-02 08:05:05 +08:00
|
|
|
|
bits<5> Vd;
|
2010-11-03 07:47:29 +08:00
|
|
|
|
bits<6> Rn;
|
|
|
|
|
bits<4> Rm;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-11-02 08:05:05 +08:00
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
2010-11-03 07:47:29 +08:00
|
|
|
|
let Inst{19-16} = Rn{3-0};
|
|
|
|
|
let Inst{3-0} = Rm{3-0};
|
2009-07-09 02:11:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-11-03 04:47:39 +08:00
|
|
|
|
class NLdStLn<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: NLdSt<op23, op21_20, op11_8, op7_4, oops, iops, itin, opc,
|
|
|
|
|
dt, asm, cstr, pattern> {
|
|
|
|
|
bits<3> lane;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-26 07:27:42 +08:00
|
|
|
|
class PseudoNLdSt<dag oops, dag iops, InstrItinClass itin, string cstr>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<AddrMode6, 4, IndexModeNone, Pseudo, NeonDomain, cstr,
|
2010-09-14 07:55:10 +08:00
|
|
|
|
itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
|
|
|
|
list<Predicate> Predicates = [HasNEON];
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-07 04:36:55 +08:00
|
|
|
|
class PseudoNeonI<dag oops, dag iops, InstrItinClass itin, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<AddrModeNone, 4, IndexModeNone, Pseudo, NeonDomain, cstr,
|
2010-08-26 07:27:42 +08:00
|
|
|
|
itin> {
|
|
|
|
|
let OutOperandList = oops;
|
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
2010-10-07 04:36:55 +08:00
|
|
|
|
let Pattern = pattern;
|
2010-08-26 07:27:42 +08:00
|
|
|
|
list<Predicate> Predicates = [HasNEON];
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 00:43:47 +08:00
|
|
|
|
class NDataI<dag oops, dag iops, Format f, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
2010-03-24 00:43:47 +08:00
|
|
|
|
: NeonI<oops, iops, AddrModeNone, IndexModeNone, f, itin, opc, dt, asm, cstr,
|
|
|
|
|
pattern> {
|
2009-11-24 05:57:23 +08:00
|
|
|
|
let Inst{31-25} = 0b1111001;
|
2010-11-15 13:19:05 +08:00
|
|
|
|
let PostEncoderMethod = "NEONThumb2DataIPostEncoder";
|
2011-08-16 07:38:54 +08:00
|
|
|
|
let DecoderNamespace = "NEONData";
|
2009-11-24 05:57:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 04:40:44 +08:00
|
|
|
|
class NDataXI<dag oops, dag iops, Format f, InstrItinClass itin,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2010-03-24 04:40:44 +08:00
|
|
|
|
: NeonXI<oops, iops, AddrModeNone, IndexModeNone, f, itin, opc, asm,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
cstr, pattern> {
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Inst{31-25} = 0b1111001;
|
2010-12-11 06:32:08 +08:00
|
|
|
|
let PostEncoderMethod = "NEONThumb2DataIPostEncoder";
|
2011-08-16 07:38:54 +08:00
|
|
|
|
let DecoderNamespace = "NEONData";
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NEON "one register and a modified immediate" format.
|
|
|
|
|
class N1ModImm<bit op23, bits<3> op21_19, bits<4> op11_8, bit op7, bit op6,
|
|
|
|
|
bit op5, bit op4,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
string opc, string dt, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2010-03-24 07:09:14 +08:00
|
|
|
|
: NDataI<oops, iops, N1RegModImmFrm, itin, opc, dt, asm, cstr, pattern> {
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{23} = op23;
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Inst{21-19} = op21_19;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-8} = op11_8;
|
|
|
|
|
let Inst{7} = op7;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{5} = op5;
|
|
|
|
|
let Inst{4} = op4;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-27 01:40:54 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<13> SIMM;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-27 01:40:54 +08:00
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{24} = SIMM{7};
|
|
|
|
|
let Inst{18-16} = SIMM{6-4};
|
|
|
|
|
let Inst{3-0} = SIMM{3-0};
|
2019-07-23 17:19:24 +08:00
|
|
|
|
let DecoderMethod = "DecodeVMOVModImmInstruction";
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NEON 2 vector register format.
|
|
|
|
|
class N2V<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
bits<5> op11_7, bit op6, bit op4,
|
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
2010-03-24 08:57:50 +08:00
|
|
|
|
: NDataI<oops, iops, N2RegFrm, itin, opc, dt, asm, cstr, pattern> {
|
2009-11-24 05:57:23 +08:00
|
|
|
|
let Inst{24-23} = op24_23;
|
|
|
|
|
let Inst{21-20} = op21_20;
|
|
|
|
|
let Inst{19-18} = op19_18;
|
|
|
|
|
let Inst{17-16} = op17_16;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-7} = op11_7;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-26 02:43:52 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
2009-11-24 05:57:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-18 19:53:22 +08:00
|
|
|
|
// Same as N2V but not predicated.
|
2013-09-19 19:59:01 +08:00
|
|
|
|
class N2Vnp<bits<2> op19_18, bits<2> op17_16, bits<3> op10_8, bit op7, bit op6,
|
2013-07-18 19:53:22 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin, string OpcodeStr,
|
2014-04-28 21:53:00 +08:00
|
|
|
|
string Dt, list<dag> pattern>
|
2013-07-18 19:53:22 +08:00
|
|
|
|
: NeonInp<oops, iops, AddrModeNone, IndexModeNone, N2RegFrm, itin,
|
|
|
|
|
OpcodeStr, Dt, "$Vd, $Vm", "", pattern> {
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
|
|
|
|
|
// Encode constant bits
|
|
|
|
|
let Inst{27-23} = 0b00111;
|
|
|
|
|
let Inst{21-20} = 0b11;
|
2013-09-19 19:59:01 +08:00
|
|
|
|
let Inst{19-18} = op19_18;
|
2013-07-18 19:53:22 +08:00
|
|
|
|
let Inst{17-16} = op17_16;
|
|
|
|
|
let Inst{11} = 0;
|
|
|
|
|
let Inst{10-8} = op10_8;
|
|
|
|
|
let Inst{7} = op7;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = 0;
|
|
|
|
|
|
|
|
|
|
let DecoderNamespace = "NEON";
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-24 05:57:23 +08:00
|
|
|
|
// Same as N2V except it doesn't have a datatype suffix.
|
|
|
|
|
class N2VX<bits<2> op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
bits<5> op11_7, bit op6, bit op4,
|
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2010-03-24 08:57:50 +08:00
|
|
|
|
: NDataXI<oops, iops, N2RegFrm, itin, opc, asm, cstr, pattern> {
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Inst{24-23} = op24_23;
|
|
|
|
|
let Inst{21-20} = op21_20;
|
|
|
|
|
let Inst{19-18} = op19_18;
|
|
|
|
|
let Inst{17-16} = op17_16;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-7} = op11_7;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-26 02:43:52 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NEON 2 vector register with immediate.
|
2009-10-21 10:15:46 +08:00
|
|
|
|
class N2VImm<bit op24, bit op23, bits<4> op11_8, bit op7, bit op6, bit op4,
|
2010-03-26 04:39:04 +08:00
|
|
|
|
dag oops, dag iops, Format f, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
2010-03-26 04:39:04 +08:00
|
|
|
|
: NDataI<oops, iops, f, itin, opc, dt, asm, cstr, pattern> {
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{24} = op24;
|
|
|
|
|
let Inst{23} = op23;
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Inst{11-8} = op11_8;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{7} = op7;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-27 04:56:57 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
bits<6> SIMM;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
|
|
|
|
let Inst{21-16} = SIMM{5-0};
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-27 11:56:52 +08:00
|
|
|
|
// NEON 3 vector register format.
|
2011-03-31 07:45:29 +08:00
|
|
|
|
|
2011-05-20 01:34:53 +08:00
|
|
|
|
class N3VCommon<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
|
|
|
|
bit op4, dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string dt, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2010-03-27 05:26:28 +08:00
|
|
|
|
: NDataI<oops, iops, f, itin, opc, dt, asm, cstr, pattern> {
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{24} = op24;
|
|
|
|
|
let Inst{23} = op23;
|
2009-11-24 05:57:23 +08:00
|
|
|
|
let Inst{21-20} = op21_20;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-8} = op11_8;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2011-03-31 07:45:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class N3V<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6, bit op4,
|
|
|
|
|
dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
|
|
|
|
: N3VCommon<op24, op23, op21_20, op11_8, op6, op4,
|
|
|
|
|
oops, iops, f, itin, opc, dt, asm, cstr, pattern> {
|
2010-10-22 04:21:49 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vn;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{19-16} = Vn{3-0};
|
|
|
|
|
let Inst{7} = Vn{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
2009-11-24 05:57:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-07-17 21:59:38 +08:00
|
|
|
|
class N3Vnp<bits<5> op27_23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
|
|
|
|
bit op4, dag oops, dag iops,Format f, InstrItinClass itin,
|
2014-04-28 21:53:00 +08:00
|
|
|
|
string OpcodeStr, string Dt, list<dag> pattern>
|
2013-07-17 21:59:38 +08:00
|
|
|
|
: NeonInp<oops, iops, AddrModeNone, IndexModeNone, f, itin, OpcodeStr,
|
|
|
|
|
Dt, "$Vd, $Vn, $Vm", "", pattern> {
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vn;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
|
|
|
|
|
// Encode instruction operands
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{19-16} = Vn{3-0};
|
|
|
|
|
let Inst{7} = Vn{4};
|
|
|
|
|
let Inst{5} = Vm{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
|
|
|
|
|
// Encode constant bits
|
|
|
|
|
let Inst{27-23} = op27_23;
|
|
|
|
|
let Inst{21-20} = op21_20;
|
|
|
|
|
let Inst{11-8} = op11_8;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-20 01:34:53 +08:00
|
|
|
|
class N3VLane32<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
|
|
|
|
bit op4, dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string dt, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2011-03-31 07:45:29 +08:00
|
|
|
|
: N3VCommon<op24, op23, op21_20, op11_8, op6, op4,
|
|
|
|
|
oops, iops, f, itin, opc, dt, asm, cstr, pattern> {
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vn;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
bit lane;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{19-16} = Vn{3-0};
|
|
|
|
|
let Inst{7} = Vn{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
let Inst{5} = lane;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-20 01:34:53 +08:00
|
|
|
|
class N3VLane16<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
|
|
|
|
bit op4, dag oops, dag iops, Format f, InstrItinClass itin,
|
|
|
|
|
string opc, string dt, string asm, string cstr,
|
|
|
|
|
list<dag> pattern>
|
2011-03-31 07:45:29 +08:00
|
|
|
|
: N3VCommon<op24, op23, op21_20, op11_8, op6, op4,
|
|
|
|
|
oops, iops, f, itin, opc, dt, asm, cstr, pattern> {
|
|
|
|
|
|
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vn;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
bits<2> lane;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{19-16} = Vn{3-0};
|
|
|
|
|
let Inst{7} = Vn{4};
|
|
|
|
|
let Inst{2-0} = Vm{2-0};
|
|
|
|
|
let Inst{5} = lane{1};
|
|
|
|
|
let Inst{3} = lane{0};
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-24 05:35:03 +08:00
|
|
|
|
// Same as N3V except it doesn't have a data type suffix.
|
2010-03-24 01:23:59 +08:00
|
|
|
|
class N3VX<bit op24, bit op23, bits<2> op21_20, bits<4> op11_8, bit op6,
|
|
|
|
|
bit op4,
|
2010-03-27 11:56:52 +08:00
|
|
|
|
dag oops, dag iops, Format f, InstrItinClass itin,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
string opc, string asm, string cstr, list<dag> pattern>
|
2010-03-27 11:56:52 +08:00
|
|
|
|
: NDataXI<oops, iops, f, itin, opc, asm, cstr, pattern> {
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{24} = op24;
|
|
|
|
|
let Inst{23} = op23;
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Inst{21-20} = op21_20;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-8} = op11_8;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = op4;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-26 02:28:30 +08:00
|
|
|
|
// Instruction operands.
|
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vn;
|
|
|
|
|
bits<5> Vm;
|
|
|
|
|
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{19-16} = Vn{3-0};
|
|
|
|
|
let Inst{7} = Vn{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NEON VMOVs between scalar and core registers.
|
|
|
|
|
class NVLaneOp<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
dag oops, dag iops, Format f, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, list<dag> pattern>
|
2011-07-14 07:22:26 +08:00
|
|
|
|
: InstARM<AddrModeNone, 4, IndexModeNone, f, NeonDomain,
|
2010-03-24 01:23:59 +08:00
|
|
|
|
"", itin> {
|
2009-06-23 07:27:02 +08:00
|
|
|
|
let Inst{27-20} = opcod1;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-8} = opcod2;
|
|
|
|
|
let Inst{6-5} = opcod3;
|
|
|
|
|
let Inst{4} = 1;
|
2011-04-07 02:27:46 +08:00
|
|
|
|
// A8.6.303, A8.6.328, A8.6.329
|
|
|
|
|
let Inst{3-0} = 0b0000;
|
2009-11-24 05:57:23 +08:00
|
|
|
|
|
|
|
|
|
let OutOperandList = oops;
|
2010-03-19 05:06:54 +08:00
|
|
|
|
let InOperandList = !con(iops, (ins pred:$p));
|
replace stuff like:
let AsmString = !strconcat(
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
!strconcat("\t", asm));
with:
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
:)
llvm-svn: 115720
2010-10-06 08:05:18 +08:00
|
|
|
|
let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
|
2009-11-24 05:57:23 +08:00
|
|
|
|
let Pattern = pattern;
|
2009-06-23 07:27:02 +08:00
|
|
|
|
list<Predicate> Predicates = [HasNEON];
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-11-15 13:19:05 +08:00
|
|
|
|
let PostEncoderMethod = "NEONThumb2DupPostEncoder";
|
2011-08-11 03:01:10 +08:00
|
|
|
|
let DecoderNamespace = "NEONDup";
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-28 05:28:09 +08:00
|
|
|
|
bits<5> V;
|
|
|
|
|
bits<4> R;
|
2010-10-28 03:25:54 +08:00
|
|
|
|
bits<4> p;
|
2010-10-28 05:28:09 +08:00
|
|
|
|
bits<4> lane;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-28 03:25:54 +08:00
|
|
|
|
let Inst{31-28} = p{3-0};
|
2010-10-28 05:28:09 +08:00
|
|
|
|
let Inst{7} = V{4};
|
|
|
|
|
let Inst{19-16} = V{3-0};
|
|
|
|
|
let Inst{15-12} = R{3-0};
|
2009-06-23 07:27:02 +08:00
|
|
|
|
}
|
|
|
|
|
class NVGetLane<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, list<dag> pattern>
|
2010-06-26 07:56:05 +08:00
|
|
|
|
: NVLaneOp<opcod1, opcod2, opcod3, oops, iops, NGetLnFrm, itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
opc, dt, asm, pattern>;
|
2009-06-23 07:27:02 +08:00
|
|
|
|
class NVSetLane<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, list<dag> pattern>
|
2010-06-26 07:56:05 +08:00
|
|
|
|
: NVLaneOp<opcod1, opcod2, opcod3, oops, iops, NSetLnFrm, itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
opc, dt, asm, pattern>;
|
2009-06-23 07:27:02 +08:00
|
|
|
|
class NVDup<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
|
2009-08-07 00:52:47 +08:00
|
|
|
|
dag oops, dag iops, InstrItinClass itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
string opc, string dt, string asm, list<dag> pattern>
|
2010-06-26 07:56:05 +08:00
|
|
|
|
: NVLaneOp<opcod1, opcod2, opcod3, oops, iops, NDupFrm, itin,
|
2009-11-24 05:57:23 +08:00
|
|
|
|
opc, dt, asm, pattern>;
|
2009-08-05 01:53:06 +08:00
|
|
|
|
|
2010-03-26 01:01:27 +08:00
|
|
|
|
// Vector Duplicate Lane (from scalar to all elements)
|
|
|
|
|
class NVDupLane<bits<4> op19_16, bit op6, dag oops, dag iops,
|
|
|
|
|
InstrItinClass itin, string opc, string dt, string asm,
|
|
|
|
|
list<dag> pattern>
|
2010-03-26 05:49:12 +08:00
|
|
|
|
: NDataI<oops, iops, NVDupLnFrm, itin, opc, dt, asm, "", pattern> {
|
2010-03-26 01:01:27 +08:00
|
|
|
|
let Inst{24-23} = 0b11;
|
|
|
|
|
let Inst{21-20} = 0b11;
|
|
|
|
|
let Inst{19-16} = op19_16;
|
2010-08-31 15:50:46 +08:00
|
|
|
|
let Inst{11-7} = 0b11000;
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{4} = 0;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-28 03:25:54 +08:00
|
|
|
|
bits<5> Vd;
|
|
|
|
|
bits<5> Vm;
|
2010-11-20 06:42:55 +08:00
|
|
|
|
|
2010-10-28 03:25:54 +08:00
|
|
|
|
let Inst{22} = Vd{4};
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{5} = Vm{4};
|
|
|
|
|
let Inst{3-0} = Vm{3-0};
|
2010-03-26 01:01:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
2009-08-05 01:53:06 +08:00
|
|
|
|
// NEONFPPat - Same as Pat<>, but requires that the compiler be using NEON
|
|
|
|
|
// for single-precision FP.
|
|
|
|
|
class NEONFPPat<dag pattern, dag result> : Pat<pattern, result> {
|
|
|
|
|
list<Predicate> Predicates = [HasNEON,UseNEONForFP];
|
|
|
|
|
}
|
2011-11-15 06:28:39 +08:00
|
|
|
|
|
|
|
|
|
// VFP/NEON Instruction aliases for type suffices.
|
2016-06-03 21:19:43 +08:00
|
|
|
|
// Note: When EmitPriority == 1, the alias will be used for printing
|
|
|
|
|
class VFPDataTypeInstAlias<string opc, string dt, string asm, dag Result, bit EmitPriority = 0> :
|
2019-07-10 16:59:17 +08:00
|
|
|
|
InstAlias<!strconcat(opc, dt, "\t", asm), Result, EmitPriority>, Requires<[HasFPRegs]>;
|
2011-12-07 09:50:36 +08:00
|
|
|
|
|
2016-06-03 21:19:43 +08:00
|
|
|
|
// Note: When EmitPriority == 1, the alias will be used for printing
|
|
|
|
|
multiclass VFPDTAnyInstAlias<string opc, string asm, dag Result, bit EmitPriority = 0> {
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".8", asm, Result, EmitPriority>;
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".16", asm, Result, EmitPriority>;
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".32", asm, Result, EmitPriority>;
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".64", asm, Result, EmitPriority>;
|
2011-12-03 02:52:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2016-06-03 21:19:43 +08:00
|
|
|
|
// Note: When EmitPriority == 1, the alias will be used for printing
|
|
|
|
|
multiclass NEONDTAnyInstAlias<string opc, string asm, dag Result, bit EmitPriority = 0> {
|
2012-01-25 01:23:29 +08:00
|
|
|
|
let Predicates = [HasNEON] in {
|
2016-06-03 21:19:43 +08:00
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".8", asm, Result, EmitPriority>;
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".16", asm, Result, EmitPriority>;
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".32", asm, Result, EmitPriority>;
|
|
|
|
|
def : VFPDataTypeInstAlias<opc, ".64", asm, Result, EmitPriority>;
|
2012-01-25 01:23:29 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-03 02:52:30 +08:00
|
|
|
|
// The same alias classes using AsmPseudo instead, for the more complex
|
|
|
|
|
// stuff in NEON that InstAlias can't quite handle.
|
|
|
|
|
// Note that we can't use anonymous defm references here like we can
|
|
|
|
|
// above, as we care about the ultimate instruction enum names generated, unlike
|
|
|
|
|
// for instalias defs.
|
|
|
|
|
class NEONDataTypeAsmPseudoInst<string opc, string dt, string asm, dag iops> :
|
2011-12-03 06:01:52 +08:00
|
|
|
|
AsmPseudoInst<!strconcat(opc, dt, "\t", asm), iops>, Requires<[HasNEON]>;
|
2011-12-07 09:17:58 +08:00
|
|
|
|
|
2017-09-29 21:11:33 +08:00
|
|
|
|
// 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};
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-17 19:29:49 +08:00
|
|
|
|
// In Armv8.2-A, some NEON instructions are added that encode Vn and Vm
|
|
|
|
|
// differently:
|
|
|
|
|
// if Q == ‘1’ then UInt(N:Vn) else UInt(Vn:N);
|
|
|
|
|
// if Q == ‘1’ then UInt(M:Vm) else UInt(Vm:M);
|
|
|
|
|
// Class N3VCP8 above describes the Q=1 case, and this class the Q=0 case.
|
|
|
|
|
class N3VCP8Q0<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{4-1};
|
|
|
|
|
let Inst{15-12} = Vd{3-0};
|
|
|
|
|
let Inst{11-8} = 0b1000;
|
|
|
|
|
let Inst{7} = Vn{0};
|
|
|
|
|
let Inst{6} = op6;
|
|
|
|
|
let Inst{5} = Vm{0};
|
|
|
|
|
let Inst{4} = op4;
|
|
|
|
|
let Inst{3-0} = Vm{4-1};
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-29 21:11:33 +08:00
|
|
|
|
// Operand types for complex instructions
|
2017-10-03 22:38:52 +08:00
|
|
|
|
class ComplexRotationOperand<int Angle, int Remainder, string Type, string Diag>
|
2017-09-29 21:11:33 +08:00
|
|
|
|
: AsmOperandClass {
|
|
|
|
|
let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
|
2017-10-03 22:38:52 +08:00
|
|
|
|
let DiagnosticString = "complex rotation must be " # Diag;
|
2017-09-29 21:11:33 +08:00
|
|
|
|
let Name = "ComplexRotation" # Type;
|
|
|
|
|
}
|
|
|
|
|
def complexrotateop : Operand<i32> {
|
2017-10-03 22:38:52 +08:00
|
|
|
|
let ParserMatchClass = ComplexRotationOperand<90, 0, "Even", "0, 90, 180 or 270">;
|
2017-09-29 21:11:33 +08:00
|
|
|
|
let PrintMethod = "printComplexRotationOp<90, 0>";
|
|
|
|
|
}
|
|
|
|
|
def complexrotateopodd : Operand<i32> {
|
2017-10-03 22:38:52 +08:00
|
|
|
|
let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd", "90 or 270">;
|
2017-09-29 21:11:33 +08:00
|
|
|
|
let PrintMethod = "printComplexRotationOp<180, 90>";
|
|
|
|
|
}
|
|
|
|
|
|
[ARM] Add <saturate> operand to SQRSHRL and UQRSHLL
Summary:
According to the new Armv8-M specification
https://static.docs.arm.com/ddi0553/bh/DDI0553B_h_armv8m_arm.pdf the
instructions SQRSHRL and UQRSHLL now have an additional immediate
operand <saturate>. The new assembly syntax is:
SQRSHRL<c> RdaLo, RdaHi, #<saturate>, Rm
UQRSHLL<c> RdaLo, RdaHi, #<saturate>, Rm
where <saturate> can be either 64 (the existing behavior) or 48, in
that case the result is saturated to 48 bits.
The new operand is encoded as follows:
#64 Encoded as sat = 0
#48 Encoded as sat = 1
sat is bit 7 of the instruction bit pattern.
This patch adds a new assembler operand class MveSaturateOperand which
implements parsing and encoding. Decoding is implemented in
DecodeMVEOverlappingLongShift.
Reviewers: ostannard, simon_tatham, t.p.northover, samparker, dmgreen, SjoerdMeijer
Reviewed By: simon_tatham
Subscribers: javed.absar, kristof.beyls, hiraditya, pbarrio, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64810
llvm-svn: 366555
2019-07-19 17:46:28 +08:00
|
|
|
|
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";
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-07 09:17:58 +08:00
|
|
|
|
// Data type suffix token aliases. Implements Table A7-3 in the ARM ARM.
|
|
|
|
|
def : TokenAlias<".s8", ".i8">;
|
|
|
|
|
def : TokenAlias<".u8", ".i8">;
|
|
|
|
|
def : TokenAlias<".s16", ".i16">;
|
|
|
|
|
def : TokenAlias<".u16", ".i16">;
|
|
|
|
|
def : TokenAlias<".s32", ".i32">;
|
|
|
|
|
def : TokenAlias<".u32", ".i32">;
|
2011-12-07 09:50:36 +08:00
|
|
|
|
def : TokenAlias<".s64", ".i64">;
|
|
|
|
|
def : TokenAlias<".u64", ".i64">;
|
2011-12-07 09:17:58 +08:00
|
|
|
|
|
|
|
|
|
def : TokenAlias<".i8", ".8">;
|
|
|
|
|
def : TokenAlias<".i16", ".16">;
|
|
|
|
|
def : TokenAlias<".i32", ".32">;
|
2011-12-07 09:50:36 +08:00
|
|
|
|
def : TokenAlias<".i64", ".64">;
|
2011-12-07 09:17:58 +08:00
|
|
|
|
|
|
|
|
|
def : TokenAlias<".p8", ".8">;
|
|
|
|
|
def : TokenAlias<".p16", ".16">;
|
|
|
|
|
|
|
|
|
|
def : TokenAlias<".f32", ".32">;
|
|
|
|
|
def : TokenAlias<".f64", ".64">;
|
|
|
|
|
def : TokenAlias<".f", ".f32">;
|
|
|
|
|
def : TokenAlias<".d", ".f64">;
|